hgext/inotify/server.py
author Brendan Cully <brendan@kublai.com>
Mon, 01 Dec 2008 13:38:26 -0800
changeset 7451 fca9947652ce
parent 7420 b4ac1e2cd38c
child 7892 67e59a9886d5
permissions -rw-r--r--
inotify: close most file descriptors when autostarting Otherwise, operations that autostart while talking to an SSH repository prevent SSH stderr from closing normally. This causes hangs at the end of hg clone or hg pull -u.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     1
# server.py - inotify status server
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     2
#
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     3
# Copyright 2006, 2007, 2008 Bryan O'Sullivan <bos@serpentine.com>
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     4
# Copyright 2007, 2008 Brendan Cully <brendan@kublai.com>
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     5
#
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     6
# This software may be used and distributed according to the terms
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     7
# of the GNU General Public License, incorporated herein by reference.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     8
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
     9
from mercurial.i18n import _
7420
b4ac1e2cd38c inotify: remove unused imports (thanks pyflakes)
Brendan Cully <brendan@kublai.com>
parents: 7351
diff changeset
    10
from mercurial import osutil, util
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    11
import common
6997
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
    12
import errno, os, select, socket, stat, struct, sys, tempfile, time
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    13
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    14
try:
6994
bf727bab38b9 Use relative imports in inotify.server.
Brendan Cully <brendan@kublai.com>
parents: 6287
diff changeset
    15
    import linux as inotify
bf727bab38b9 Use relative imports in inotify.server.
Brendan Cully <brendan@kublai.com>
parents: 6287
diff changeset
    16
    from linux import watcher
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    17
except ImportError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    18
    raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    19
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    20
class AlreadyStartedException(Exception): pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    21
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    22
def join(a, b):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    23
    if a:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    24
        if a[-1] == '/':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
            return a + b
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    26
        return a + '/' + b
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    27
    return b
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    28
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    29
walk_ignored_errors = (errno.ENOENT, errno.ENAMETOOLONG)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    30
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    31
def walkrepodirs(repo):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    32
    '''Iterate over all subdirectories of this repo.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    33
    Exclude the .hg directory, any nested repos, and ignored dirs.'''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    34
    rootslash = repo.root + os.sep
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    35
    def walkit(dirname, top):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    36
        hginside = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    37
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    38
            for name, kind in osutil.listdir(rootslash + dirname):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    39
                if kind == stat.S_IFDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    40
                    if name == '.hg':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    41
                        hginside = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    42
                        if not top: break
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    43
                    else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    44
                        d = join(dirname, name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
                        if repo.dirstate._ignore(d):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    46
                            continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    47
                        for subdir, hginsub in walkit(d, False):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    48
                            if not hginsub:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    49
                                yield subdir, False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
            if err.errno not in walk_ignored_errors:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    52
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    53
        yield rootslash + dirname, hginside
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    54
    for dirname, hginside in walkit('', True):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    55
        yield dirname
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    57
def walk(repo, root):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    58
    '''Like os.walk, but only yields regular files.'''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    59
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    60
    # This function is critical to performance during startup.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    61
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    62
    reporoot = root == ''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    63
    rootslash = repo.root + os.sep
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    64
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    65
    def walkit(root, reporoot):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    66
        files, dirs = [], []
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    67
        hginside = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    68
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    69
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    70
            fullpath = rootslash + root
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    71
            for name, kind in osutil.listdir(fullpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    72
                if kind == stat.S_IFDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    73
                    if name == '.hg':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    74
                        hginside = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    75
                        if reporoot:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    76
                            continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    77
                        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    78
                            break
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    79
                    dirs.append(name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    80
                elif kind in (stat.S_IFREG, stat.S_IFLNK):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    81
                    path = join(root, name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    82
                    files.append((name, kind))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    83
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    84
            yield hginside, fullpath, dirs, files
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    85
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    86
            for subdir in dirs:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    87
                path = join(root, subdir)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    88
                if repo.dirstate._ignore(path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    89
                    continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    90
                for result in walkit(path, False):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    91
                    if not result[0]:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    92
                        yield result
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    93
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    94
            if err.errno not in walk_ignored_errors:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    95
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    96
    for result in walkit(root, reporoot):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    97
        yield result[1:]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    98
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    99
def _explain_watch_limit(ui, repo, count):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   100
    path = '/proc/sys/fs/inotify/max_user_watches'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   101
    try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   102
        limit = int(file(path).read())
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   103
    except IOError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   104
        if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   105
            raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   106
        raise util.Abort(_('this system does not seem to '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   107
                           'support inotify'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   108
    ui.warn(_('*** the current per-user limit on the number '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   109
              'of inotify watches is %s\n') % limit)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   110
    ui.warn(_('*** this limit is too low to watch every '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   111
              'directory in this repository\n'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   112
    ui.warn(_('*** counting directories: '))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   113
    ndirs = len(list(walkrepodirs(repo)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   114
    ui.warn(_('found %d\n') % ndirs)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   115
    newlimit = min(limit, 1024)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   116
    while newlimit < ((limit + ndirs) * 1.1):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   117
        newlimit *= 2
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   118
    ui.warn(_('*** to raise the limit from %d to %d (run as root):\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   119
            (limit, newlimit))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   120
    ui.warn(_('***  echo %d > %s\n') % (newlimit, path))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   121
    raise util.Abort(_('cannot watch %s until inotify watch limit is raised')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   122
                     % repo.root)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   123
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   124
class Watcher(object):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   125
    poll_events = select.POLLIN
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   126
    statuskeys = 'almr!?'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   127
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   128
    def __init__(self, ui, repo, master):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   129
        self.ui = ui
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   130
        self.repo = repo
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   131
        self.wprefix = self.repo.wjoin('')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   132
        self.timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   133
        self.master = master
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   134
        self.mask = (
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   135
            inotify.IN_ATTRIB |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   136
            inotify.IN_CREATE |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   137
            inotify.IN_DELETE |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   138
            inotify.IN_DELETE_SELF |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   139
            inotify.IN_MODIFY |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   140
            inotify.IN_MOVED_FROM |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   141
            inotify.IN_MOVED_TO |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   142
            inotify.IN_MOVE_SELF |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   143
            inotify.IN_ONLYDIR |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   144
            inotify.IN_UNMOUNT |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   145
            0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   146
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   147
            self.watcher = watcher.Watcher()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   148
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   149
            raise util.Abort(_('inotify service not available: %s') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   150
                             err.strerror)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   151
        self.threshold = watcher.Threshold(self.watcher)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   152
        self.registered = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   153
        self.fileno = self.watcher.fileno
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   154
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   155
        self.repo.dirstate.__class__.inotifyserver = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   156
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   157
        self.tree = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   158
        self.statcache = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   159
        self.statustrees = dict([(s, {}) for s in self.statuskeys])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   160
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   161
        self.watches = 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   162
        self.last_event = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   163
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   164
        self.eventq = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   165
        self.deferred = 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   166
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   167
        self.ds_info = self.dirstate_info()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   168
        self.scan()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   169
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   170
    def event_time(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   171
        last = self.last_event
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   172
        now = time.time()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   173
        self.last_event = now
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   174
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   175
        if last is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   176
            return 'start'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   177
        delta = now - last
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   178
        if delta < 5:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   179
            return '+%.3f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   180
        if delta < 50:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   181
            return '+%.2f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   182
        return '+%.1f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   183
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   184
    def dirstate_info(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   185
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   186
            st = os.lstat(self.repo.join('dirstate'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   187
            return st.st_mtime, st.st_ino
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   188
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   189
            if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   190
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   191
            return 0, 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   192
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   193
    def add_watch(self, path, mask):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   194
        if not path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   195
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   196
        if self.watcher.path(path) is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   197
            if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   198
                self.ui.note(_('watching %r\n') % path[len(self.wprefix):])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   199
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   200
                self.watcher.add(path, mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   201
                self.watches += 1
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   202
            except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   203
                if err.errno in (errno.ENOENT, errno.ENOTDIR):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   204
                    return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   205
                if err.errno != errno.ENOSPC:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   206
                    raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   207
                _explain_watch_limit(self.ui, self.repo, self.watches)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   208
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   209
    def setup(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   210
        self.ui.note(_('watching directories under %r\n') % self.repo.root)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   211
        self.add_watch(self.repo.path, inotify.IN_DELETE)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   212
        self.check_dirstate()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   213
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   214
    def wpath(self, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   215
        path = evt.fullpath
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   216
        if path == self.repo.root:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   217
            return ''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   218
        if path.startswith(self.wprefix):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   219
            return path[len(self.wprefix):]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   220
        raise 'wtf? ' + path
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   221
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   222
    def dir(self, tree, path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   223
        if path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   224
            for name in path.split('/'):
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   225
                tree.setdefault(name, {})
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   226
                tree = tree[name]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   227
        return tree
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   228
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   229
    def lookup(self, path, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   230
        if path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   231
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   232
                for name in path.split('/'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   233
                    tree = tree[name]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   234
            except KeyError:
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   235
                return 'x'
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   236
            except TypeError:
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   237
                return 'd'
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   238
        return tree
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   240
    def split(self, path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   241
        c = path.rfind('/')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   242
        if c == -1:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   243
            return '', path
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   244
        return path[:c], path[c+1:]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   245
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   246
    def filestatus(self, fn, st):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   247
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   248
            type_, mode, size, time = self.repo.dirstate._map[fn][:4]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   249
        except KeyError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   250
            type_ = '?'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   251
        if type_ == 'n':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   252
            if not st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   253
                return '!'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   254
            st_mode, st_size, st_mtime = st
7082
be81b4788115 inotify: fix confusion on files in lookup state
Matt Mackall <mpm@selenic.com>
parents: 6998
diff changeset
   255
            if size == -1:
be81b4788115 inotify: fix confusion on files in lookup state
Matt Mackall <mpm@selenic.com>
parents: 6998
diff changeset
   256
                return 'l'
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   257
            if size and (size != st_size or (mode ^ st_mode) & 0100):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   258
                return 'm'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   259
            if time != int(st_mtime):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   260
                return 'l'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   261
            return 'n'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   262
        if type_ in 'ma' and not st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   263
            return '!'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   264
        if type_ == '?' and self.repo.dirstate._ignore(fn):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   265
            return 'i'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   266
        return type_
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   267
7086
4033195d455b inotify: avoid status getting out of sync
Matt Mackall <mpm@selenic.com>
parents: 7085
diff changeset
   268
    def updatestatus(self, wfn, st=None, status=None):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   269
        if st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   270
            status = self.filestatus(wfn, st)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   271
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   272
            self.statcache.pop(wfn, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   273
        root, fn = self.split(wfn)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   274
        d = self.dir(self.tree, root)
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   275
        oldstatus = d.get(fn)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   276
        isdir = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   277
        if oldstatus:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   278
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   279
                if not status:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   280
                    if oldstatus in 'almn':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   281
                        status = '!'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   282
                    elif oldstatus == 'r':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   283
                        status = 'r'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   284
            except TypeError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   285
                # oldstatus may be a dict left behind by a deleted
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   286
                # directory
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   287
                isdir = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   288
            else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   289
                if oldstatus in self.statuskeys and oldstatus != status:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   290
                    del self.dir(self.statustrees[oldstatus], root)[fn]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   291
        if self.ui.debugflag and oldstatus != status:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   292
            if isdir:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   293
                self.ui.note(_('status: %r dir(%d) -> %s\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   294
                             (wfn, len(oldstatus), status))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   295
            else:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   296
                self.ui.note(_('status: %r %s -> %s\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   297
                             (wfn, oldstatus, status))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   298
        if not isdir:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   299
            if status and status != 'i':
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   300
                d[fn] = status
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   301
                if status in self.statuskeys:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   302
                    dd = self.dir(self.statustrees[status], root)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   303
                    if oldstatus != status or fn not in dd:
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   304
                        dd[fn] = status
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   305
            else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   306
                d.pop(fn, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   307
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   308
    def check_deleted(self, key):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   309
        # Files that had been deleted but were present in the dirstate
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   310
        # may have vanished from the dirstate; we must clean them up.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   311
        nuke = []
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   312
        for wfn, ignore in self.walk(key, self.statustrees[key]):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   313
            if wfn not in self.repo.dirstate:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   314
                nuke.append(wfn)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   315
        for wfn in nuke:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   316
            root, fn = self.split(wfn)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   317
            del self.dir(self.statustrees[key], root)[fn]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   318
            del self.dir(self.tree, root)[fn]
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   319
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   320
    def scan(self, topdir=''):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   321
        self.handle_timeout()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   322
        ds = self.repo.dirstate._map.copy()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   323
        self.add_watch(join(self.repo.root, topdir), self.mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   324
        for root, dirs, entries in walk(self.repo, topdir):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   325
            for d in dirs:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   326
                self.add_watch(join(root, d), self.mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   327
            wroot = root[len(self.wprefix):]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   328
            d = self.dir(self.tree, wroot)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   329
            for fn, kind in entries:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   330
                wfn = join(wroot, fn)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   331
                self.updatestatus(wfn, self.getstat(wfn))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   332
                ds.pop(wfn, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   333
        wtopdir = topdir
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   334
        if wtopdir and wtopdir[-1] != '/':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   335
            wtopdir += '/'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   336
        for wfn, state in ds.iteritems():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   337
            if not wfn.startswith(wtopdir):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   338
                continue
7302
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   339
            try:
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   340
                st = self.stat(wfn)
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   341
            except OSError:
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   342
                status = state[0]
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   343
                self.updatestatus(wfn, None, status=status)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   344
            else:
7086
4033195d455b inotify: avoid status getting out of sync
Matt Mackall <mpm@selenic.com>
parents: 7085
diff changeset
   345
                self.updatestatus(wfn, st)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   346
        self.check_deleted('!')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   347
        self.check_deleted('r')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   348
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   349
    def check_dirstate(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   350
        ds_info = self.dirstate_info()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   351
        if ds_info == self.ds_info:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   352
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   353
        self.ds_info = ds_info
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   354
        if not self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   355
            self.last_event = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   356
        self.ui.note(_('%s dirstate reload\n') % self.event_time())
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   357
        self.repo.dirstate.invalidate()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   358
        self.scan()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   359
        self.ui.note(_('%s end dirstate reload\n') % self.event_time())
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   360
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   361
    def walk(self, states, tree, prefix=''):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   362
        # This is the "inner loop" when talking to the client.
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   363
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   364
        for name, val in tree.iteritems():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   365
            path = join(prefix, name)
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   366
            try:
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   367
                if val in states:
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   368
                    yield path, val
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   369
            except TypeError:
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   370
                for p in self.walk(states, val, path):
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   371
                    yield p
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   372
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   373
    def update_hgignore(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   374
        # An update of the ignore file can potentially change the
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   375
        # states of all unknown and ignored files.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   376
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   377
        # XXX If the user has other ignore files outside the repo, or
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   378
        # changes their list of ignore files at run time, we'll
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   379
        # potentially never see changes to them.  We could get the
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   380
        # client to report to us what ignore data they're using.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   381
        # But it's easier to do nothing than to open that can of
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   382
        # worms.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   383
7085
1fcc282e2c43 inotify: fixup rebuilding ignore
Matt Mackall <mpm@selenic.com>
parents: 7082
diff changeset
   384
        if '_ignore' in self.repo.dirstate.__dict__:
1fcc282e2c43 inotify: fixup rebuilding ignore
Matt Mackall <mpm@selenic.com>
parents: 7082
diff changeset
   385
            delattr(self.repo.dirstate, '_ignore')
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   386
            self.ui.note(_('rescanning due to .hgignore change\n'))
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   387
            self.scan()
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   388
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   389
    def getstat(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   390
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   391
            return self.statcache[wpath]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   392
        except KeyError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   393
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   394
                return self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   395
            except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   396
                if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   397
                    raise
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   398
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   399
    def stat(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   400
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   401
            st = os.lstat(join(self.wprefix, wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   402
            ret = st.st_mode, st.st_size, st.st_mtime
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   403
            self.statcache[wpath] = ret
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   404
            return ret
7280
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7220
diff changeset
   405
        except OSError:
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   406
            self.statcache.pop(wpath, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   407
            raise
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   408
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   409
    def created(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   410
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   411
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   412
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   413
            st = self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   414
            if stat.S_ISREG(st[0]):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   415
                self.updatestatus(wpath, st)
7280
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7220
diff changeset
   416
        except OSError:
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   417
            pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   418
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   419
    def modified(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   420
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   421
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   422
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   423
            st = self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   424
            if stat.S_ISREG(st[0]):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   425
                if self.repo.dirstate[wpath] in 'lmn':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   426
                    self.updatestatus(wpath, st)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   427
        except OSError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   428
            pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   429
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   430
    def deleted(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   431
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   432
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   433
        elif wpath.startswith('.hg/'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   434
            if wpath == '.hg/wlock':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   435
                self.check_dirstate()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   436
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   437
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   438
        self.updatestatus(wpath, None)
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   439
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   440
    def schedule_work(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   441
        self.eventq.setdefault(wpath, [])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   442
        prev = self.eventq[wpath]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   443
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   444
            if prev and evt == 'm' and prev[-1] in 'cm':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   445
                return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   446
            self.eventq[wpath].append(evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   447
        finally:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   448
            self.deferred += 1
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   449
            self.timeout = 250
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   450
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   451
    def deferred_event(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   452
        if evt == 'c':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   453
            self.created(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   454
        elif evt == 'm':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   455
            self.modified(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   456
        elif evt == 'd':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   457
            self.deleted(wpath)
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   458
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   459
    def process_create(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   460
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   461
            self.ui.note(_('%s event: created %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   462
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   463
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   464
        if evt.mask & inotify.IN_ISDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   465
            self.scan(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   466
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   467
            self.schedule_work(wpath, 'c')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   468
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   469
    def process_delete(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   470
        if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   471
            self.ui.note(_('%s event: deleted %s\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   472
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   473
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   474
        if evt.mask & inotify.IN_ISDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   475
            self.scan(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   476
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   477
            self.schedule_work(wpath, 'd')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   478
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   479
    def process_modify(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   480
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   481
            self.ui.note(_('%s event: modified %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   482
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   483
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   484
        if not (evt.mask & inotify.IN_ISDIR):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   485
            self.schedule_work(wpath, 'm')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   486
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   487
    def process_unmount(self, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   488
        self.ui.warn(_('filesystem containing %s was unmounted\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   489
                     evt.fullpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   490
        sys.exit(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   491
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   492
    def handle_event(self, fd, event):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   493
        if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   494
            self.ui.note(_('%s readable: %d bytes\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   495
                         (self.event_time(), self.threshold.readable()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   496
        if not self.threshold():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   497
            if self.registered:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   498
                if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   499
                    self.ui.note(_('%s below threshold - unhooking\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   500
                                 (self.event_time()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   501
                self.master.poll.unregister(fd)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   502
                self.registered = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   503
                self.timeout = 250
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   504
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   505
            self.read_events()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   506
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   507
    def read_events(self, bufsize=None):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   508
        events = self.watcher.read(bufsize)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   509
        if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   510
            self.ui.note(_('%s reading %d events\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   511
                         (self.event_time(), len(events)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   512
        for evt in events:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   513
            wpath = self.wpath(evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   514
            if evt.mask & inotify.IN_UNMOUNT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   515
                self.process_unmount(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   516
            elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   517
                self.process_modify(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   518
            elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   519
                             inotify.IN_MOVED_FROM):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   520
                self.process_delete(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   521
            elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   522
                self.process_create(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   523
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   524
    def handle_timeout(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   525
        if not self.registered:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   526
            if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   527
                self.ui.note(_('%s hooking back up with %d bytes readable\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   528
                             (self.event_time(), self.threshold.readable()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   529
            self.read_events(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   530
            self.master.poll.register(self, select.POLLIN)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   531
            self.registered = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   532
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   533
        if self.eventq:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   534
            if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   535
                self.ui.note(_('%s processing %d deferred events as %d\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   536
                             (self.event_time(), self.deferred,
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   537
                              len(self.eventq)))
6762
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6287
diff changeset
   538
            for wpath, evts in util.sort(self.eventq.items()):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   539
                for evt in evts:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   540
                    self.deferred_event(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   541
            self.eventq.clear()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   542
            self.deferred = 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   543
        self.timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   544
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   545
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   546
        self.watcher.close()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   547
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   548
class Server(object):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   549
    poll_events = select.POLLIN
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   550
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   551
    def __init__(self, ui, repo, watcher, timeout):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   552
        self.ui = ui
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   553
        self.repo = repo
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   554
        self.watcher = watcher
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   555
        self.timeout = timeout
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   556
        self.sock = socket.socket(socket.AF_UNIX)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   557
        self.sockpath = self.repo.join('inotify.sock')
6997
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   558
        self.realsockpath = None
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   559
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   560
            self.sock.bind(self.sockpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   561
        except socket.error, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   562
            if err[0] == errno.EADDRINUSE:
6997
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   563
                raise AlreadyStartedException(_('could not start server: %s')
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   564
                                              % err[1])
6997
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   565
            if err[0] == "AF_UNIX path too long":
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   566
                tempdir = tempfile.mkdtemp(prefix="hg-inotify-")
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   567
                self.realsockpath = os.path.join(tempdir, "inotify.sock")
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   568
                try:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   569
                    self.sock.bind(self.realsockpath)
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   570
                    os.symlink(self.realsockpath, self.sockpath)
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   571
                except (OSError, socket.error), inst:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   572
                    try:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   573
                        os.unlink(self.realsockpath)
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   574
                    except:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   575
                        pass
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   576
                    os.rmdir(tempdir)
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   577
                    if inst.errno == errno.EEXIST:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   578
                        raise AlreadyStartedException(_('could not start server: %s')
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   579
                                                      % inst.strerror)
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   580
                    raise
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   581
            else:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   582
                raise
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   583
        self.sock.listen(5)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   584
        self.fileno = self.sock.fileno
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   585
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   586
    def handle_timeout(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   587
        pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   588
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   589
    def handle_event(self, fd, event):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   590
        sock, addr = self.sock.accept()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   591
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   592
        cs = common.recvcs(sock)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   593
        version = ord(cs.read(1))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   594
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   595
        sock.sendall(chr(common.version))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   596
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   597
        if version != common.version:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   598
            self.ui.warn(_('received query from incompatible client '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   599
                           'version %d\n') % version)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   600
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   601
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   602
        names = cs.read().split('\0')
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   603
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   604
        states = names.pop()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   605
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   606
        self.ui.note(_('answering query for %r\n') % states)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   607
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   608
        if self.watcher.timeout:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   609
            # We got a query while a rescan is pending.  Make sure we
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   610
            # rescan before responding, or we could give back a wrong
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   611
            # answer.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   612
            self.watcher.handle_timeout()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   613
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   614
        if not names:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   615
            def genresult(states, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   616
                for fn, state in self.watcher.walk(states, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   617
                    yield fn
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   618
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   619
            def genresult(states, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   620
                for fn in names:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   621
                    l = self.watcher.lookup(fn, tree)
7351
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   622
                    try:
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   623
                        if l in states:
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   624
                            yield fn
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   625
                    except TypeError:
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   626
                        for f, s in self.watcher.walk(states, l, fn):
5ab0abf27dd9 Backed out changeset c5dbe86b0fee (issue1375)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7350
diff changeset
   627
                            yield f
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   628
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   629
        results = ['\0'.join(r) for r in [
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   630
            genresult('l', self.watcher.statustrees['l']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   631
            genresult('m', self.watcher.statustrees['m']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   632
            genresult('a', self.watcher.statustrees['a']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   633
            genresult('r', self.watcher.statustrees['r']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   634
            genresult('!', self.watcher.statustrees['!']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   635
            '?' in states and genresult('?', self.watcher.statustrees['?']) or [],
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   636
            [],
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   637
            'c' in states and genresult('n', self.watcher.tree) or [],
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   638
            ]]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   639
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   640
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   641
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   642
                sock.sendall(struct.pack(common.resphdrfmt,
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   643
                                         *map(len, results)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   644
                sock.sendall(''.join(results))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   645
            finally:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   646
                sock.shutdown(socket.SHUT_WR)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   647
        except socket.error, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   648
            if err[0] != errno.EPIPE:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   649
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   650
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   651
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   652
        self.sock.close()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   653
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   654
            os.unlink(self.sockpath)
6997
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   655
            if self.realsockpath:
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   656
                os.unlink(self.realsockpath)
9c4e488f105e inotify: workaround ENAMETOOLONG by using symlinks
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6994
diff changeset
   657
                os.rmdir(os.path.dirname(self.realsockpath))
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   658
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   659
            if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   660
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   661
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   662
class Master(object):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   663
    def __init__(self, ui, repo, timeout=None):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   664
        self.ui = ui
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   665
        self.repo = repo
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   666
        self.poll = select.poll()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   667
        self.watcher = Watcher(ui, repo, self)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   668
        self.server = Server(ui, repo, self.watcher, timeout)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   669
        self.table = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   670
        for obj in (self.watcher, self.server):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   671
            fd = obj.fileno()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   672
            self.table[fd] = obj
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   673
            self.poll.register(fd, obj.poll_events)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   674
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   675
    def register(self, fd, mask):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   676
        self.poll.register(fd, mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   677
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   678
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   679
        for obj in self.table.itervalues():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   680
            obj.shutdown()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   681
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   682
    def run(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   683
        self.watcher.setup()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   684
        self.ui.note(_('finished setup\n'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   685
        if os.getenv('TIME_STARTUP'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   686
            sys.exit(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   687
        while True:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   688
            timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   689
            timeobj = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   690
            for obj in self.table.itervalues():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   691
                if obj.timeout is not None and (timeout is None or obj.timeout < timeout):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   692
                    timeout, timeobj = obj.timeout, obj
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   693
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   694
                if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   695
                    if timeout is None:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   696
                        self.ui.note(_('polling: no timeout\n'))
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   697
                    else:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   698
                        self.ui.note(_('polling: %sms timeout\n') % timeout)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   699
                events = self.poll.poll(timeout)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   700
            except select.error, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   701
                if err[0] == errno.EINTR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   702
                    continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   703
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   704
            if events:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   705
                for fd, event in events:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   706
                    self.table[fd].handle_event(fd, event)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   707
            elif timeobj:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   708
                timeobj.handle_timeout()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   709
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   710
def start(ui, repo):
7451
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   711
    def closefds(ignore):
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   712
        # (from python bug #1177468)
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   713
        # close all inherited file descriptors
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   714
        # Python 2.4.1 and later use /dev/urandom to seed the random module's RNG
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   715
        # a file descriptor is kept internally as os._urandomfd (created on demand
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   716
        # the first time os.urandom() is called), and should not be closed
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   717
        try:
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   718
            os.urandom(4)
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   719
            urandom_fd = getattr(os, '_urandomfd', None)
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   720
        except AttributeError:
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   721
            urandom_fd = None
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   722
        ignore.append(urandom_fd)
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   723
        for fd in range(3, 256):
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   724
            if fd in ignore:
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   725
                continue
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   726
            try:
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   727
                os.close(fd)
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   728
            except OSError:
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   729
                pass
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   730
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   731
    m = Master(ui, repo)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   732
    sys.stdout.flush()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   733
    sys.stderr.flush()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   734
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   735
    pid = os.fork()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   736
    if pid:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   737
        return pid
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   738
7451
fca9947652ce inotify: close most file descriptors when autostarting
Brendan Cully <brendan@kublai.com>
parents: 7420
diff changeset
   739
    closefds([m.server.fileno(), m.watcher.fileno()])
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   740
    os.setsid()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   741
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   742
    fd = os.open('/dev/null', os.O_RDONLY)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   743
    os.dup2(fd, 0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   744
    if fd > 0:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   745
        os.close(fd)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   746
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   747
    fd = os.open(ui.config('inotify', 'log', '/dev/null'),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   748
                 os.O_RDWR | os.O_CREAT | os.O_TRUNC)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   749
    os.dup2(fd, 1)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   750
    os.dup2(fd, 2)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   751
    if fd > 2:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   752
        os.close(fd)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   753
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   754
    try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   755
        m.run()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   756
    finally:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   757
        m.shutdown()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   758
        os._exit(0)