hgext/inotify/server.py
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
Sun, 23 Mar 2008 21:03:24 -0300
changeset 6370 6440e25a1ba3
parent 6287 c86207d41512
child 6762 f67d1468ac50
child 6994 bf727bab38b9
permissions -rw-r--r--
localrepo.commit: grab locks before getting the list of files to commit Somebody may change the dirstate after we've determined the parents of the working dir and run repo.status, but before we called wlock(). This should also fix issue997, where backout would change a file without changing its size and then call repo.commit without passing the list of files. If this happened in less than one second, we wouldn't detect any file changes - the in-memory dirstate still has the cached stat data for that file. Grabbing the wlock early causes the dirstate to be invalidated and we end up reading the dirstate file again, which has that file marked for lookup (size == -1). A better fix would be for backout to give repo.commit the exact list of files, but that'll require some changes to the revert operation. A significant user-visible change is that the precommit hook is always run with both locks grabbed - previously, hg commit would run it before grabbing any locks, but hg import would run it after grabbing locks.
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
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     9
from mercurial.i18n import gettext as _
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    10
from mercurial import osutil, ui, util
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    11
import common
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    12
import errno, os, select, socket, stat, struct, sys, time
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:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    15
    import hgext.inotify.linux as inotify
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    16
    from hgext.inotify.linux import watcher
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
    print >> sys.stderr, '*** native support is required for this extension'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    19
    raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    20
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    21
class AlreadyStartedException(Exception): pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    22
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    23
def join(a, b):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    24
    if a:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
        if a[-1] == '/':
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 a + '/' + b
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    28
    return b
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    29
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    30
walk_ignored_errors = (errno.ENOENT, errno.ENAMETOOLONG)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    31
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    32
def walkrepodirs(repo):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    33
    '''Iterate over all subdirectories of this repo.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    34
    Exclude the .hg directory, any nested repos, and ignored dirs.'''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    35
    rootslash = repo.root + os.sep
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    36
    def walkit(dirname, top):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    37
        hginside = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    38
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    39
            for name, kind in osutil.listdir(rootslash + dirname):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    40
                if kind == stat.S_IFDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    41
                    if name == '.hg':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    42
                        hginside = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    43
                        if not top: break
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    44
                    else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
                        d = join(dirname, name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    46
                        if repo.dirstate._ignore(d):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    47
                            continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    48
                        for subdir, hginsub in walkit(d, False):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    49
                            if not hginsub:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
                                yield subdir, False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    52
            if err.errno not in walk_ignored_errors:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    53
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    54
        yield rootslash + dirname, hginside
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    55
    for dirname, hginside in walkit('', True):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
        yield dirname
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    57
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    58
def walk(repo, root):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    59
    '''Like os.walk, but only yields regular files.'''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    60
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    61
    # This function is critical to performance during startup.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    62
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    63
    reporoot = root == ''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    64
    rootslash = repo.root + os.sep
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    65
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    66
    def walkit(root, reporoot):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    67
        files, dirs = [], []
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    68
        hginside = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    69
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    70
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    71
            fullpath = rootslash + root
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    72
            for name, kind in osutil.listdir(fullpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    73
                if kind == stat.S_IFDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    74
                    if name == '.hg':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    75
                        hginside = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    76
                        if reporoot:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    77
                            continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    78
                        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    79
                            break
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    80
                    dirs.append(name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    81
                elif kind in (stat.S_IFREG, stat.S_IFLNK):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    82
                    path = join(root, name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    83
                    files.append((name, kind))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    84
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    85
            yield hginside, fullpath, dirs, files
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    86
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    87
            for subdir in dirs:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    88
                path = join(root, subdir)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    89
                if repo.dirstate._ignore(path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    90
                    continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    91
                for result in walkit(path, False):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    92
                    if not result[0]:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    93
                        yield result
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    94
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    95
            if err.errno not in walk_ignored_errors:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    96
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    97
    for result in walkit(root, reporoot):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    98
        yield result[1:]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    99
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   100
def _explain_watch_limit(ui, repo, count):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   101
    path = '/proc/sys/fs/inotify/max_user_watches'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   102
    try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   103
        limit = int(file(path).read())
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   104
    except IOError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   105
        if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   106
            raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   107
        raise util.Abort(_('this system does not seem to '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   108
                           'support inotify'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   109
    ui.warn(_('*** the current per-user limit on the number '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   110
              'of inotify watches is %s\n') % limit)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   111
    ui.warn(_('*** this limit is too low to watch every '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   112
              'directory in this repository\n'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   113
    ui.warn(_('*** counting directories: '))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   114
    ndirs = len(list(walkrepodirs(repo)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   115
    ui.warn(_('found %d\n') % ndirs)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   116
    newlimit = min(limit, 1024)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   117
    while newlimit < ((limit + ndirs) * 1.1):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   118
        newlimit *= 2
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   119
    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
   120
            (limit, newlimit))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   121
    ui.warn(_('***  echo %d > %s\n') % (newlimit, path))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   122
    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
   123
                     % repo.root)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   124
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   125
class Watcher(object):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   126
    poll_events = select.POLLIN
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   127
    statuskeys = 'almr!?'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   128
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   129
    def __init__(self, ui, repo, master):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   130
        self.ui = ui
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   131
        self.repo = repo
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   132
        self.wprefix = self.repo.wjoin('')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   133
        self.timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   134
        self.master = master
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   135
        self.mask = (
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   136
            inotify.IN_ATTRIB |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   137
            inotify.IN_CREATE |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   138
            inotify.IN_DELETE |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   139
            inotify.IN_DELETE_SELF |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   140
            inotify.IN_MODIFY |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   141
            inotify.IN_MOVED_FROM |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   142
            inotify.IN_MOVED_TO |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   143
            inotify.IN_MOVE_SELF |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   144
            inotify.IN_ONLYDIR |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   145
            inotify.IN_UNMOUNT |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   146
            0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   147
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   148
            self.watcher = watcher.Watcher()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   149
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   150
            raise util.Abort(_('inotify service not available: %s') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   151
                             err.strerror)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   152
        self.threshold = watcher.Threshold(self.watcher)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   153
        self.registered = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   154
        self.fileno = self.watcher.fileno
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   155
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   156
        self.repo.dirstate.__class__.inotifyserver = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   157
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   158
        self.tree = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   159
        self.statcache = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   160
        self.statustrees = dict([(s, {}) for s in self.statuskeys])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   161
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   162
        self.watches = 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   163
        self.last_event = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   164
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   165
        self.eventq = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   166
        self.deferred = 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   167
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   168
        self.ds_info = self.dirstate_info()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   169
        self.scan()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   170
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   171
    def event_time(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   172
        last = self.last_event
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   173
        now = time.time()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   174
        self.last_event = now
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   175
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   176
        if last is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   177
            return 'start'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   178
        delta = now - last
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   179
        if delta < 5:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   180
            return '+%.3f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   181
        if delta < 50:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   182
            return '+%.2f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   183
        return '+%.1f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   184
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   185
    def dirstate_info(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   186
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   187
            st = os.lstat(self.repo.join('dirstate'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   188
            return st.st_mtime, st.st_ino
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   189
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   190
            if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   191
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   192
            return 0, 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   193
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   194
    def add_watch(self, path, mask):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   195
        if not path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   196
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   197
        if self.watcher.path(path) is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   198
            if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   199
                self.ui.note(_('watching %r\n') % path[len(self.wprefix):])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   200
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   201
                self.watcher.add(path, mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   202
                self.watches += 1
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   203
            except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   204
                if err.errno in (errno.ENOENT, errno.ENOTDIR):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   205
                    return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   206
                if err.errno != errno.ENOSPC:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   207
                    raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   208
                _explain_watch_limit(self.ui, self.repo, self.watches)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   209
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   210
    def setup(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   211
        self.ui.note(_('watching directories under %r\n') % self.repo.root)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   212
        self.add_watch(self.repo.path, inotify.IN_DELETE)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   213
        self.check_dirstate()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   214
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   215
    def wpath(self, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   216
        path = evt.fullpath
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   217
        if path == self.repo.root:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   218
            return ''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   219
        if path.startswith(self.wprefix):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   220
            return path[len(self.wprefix):]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   221
        raise 'wtf? ' + path
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   222
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   223
    def dir(self, tree, path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   224
        if path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   225
            for name in path.split('/'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   226
                tree.setdefault(name, {})
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   227
                tree = tree[name]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   228
        return tree
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   229
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   230
    def lookup(self, path, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   231
        if path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   232
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   233
                for name in path.split('/'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   234
                    tree = tree[name]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   235
            except KeyError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   236
                return 'x'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   237
            except TypeError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   238
                return 'd'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   239
        return tree
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   240
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   241
    def split(self, path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   242
        c = path.rfind('/')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   243
        if c == -1:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   244
            return '', path
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   245
        return path[:c], path[c+1:]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   246
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   247
    def filestatus(self, fn, st):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   248
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   249
            type_, mode, size, time = self.repo.dirstate._map[fn][:4]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   250
        except KeyError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   251
            type_ = '?'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   252
        if type_ == 'n':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   253
            if not st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   254
                return '!'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   255
            st_mode, st_size, st_mtime = st
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   256
            if size and (size != st_size or (mode ^ st_mode) & 0100):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   257
                return 'm'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   258
            if time != int(st_mtime):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   259
                return 'l'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   260
            return 'n'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   261
        if type_ in 'ma' and not st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   262
            return '!'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   263
        if type_ == '?' and self.repo.dirstate._ignore(fn):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   264
            return 'i'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   265
        return type_
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   266
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   267
    def updatestatus(self, wfn, st=None, status=None, oldstatus=None):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   268
        if st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   269
            status = self.filestatus(wfn, st)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   270
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   271
            self.statcache.pop(wfn, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   272
        root, fn = self.split(wfn)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   273
        d = self.dir(self.tree, root)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   274
        if oldstatus is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   275
            oldstatus = d.get(fn)
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:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   293
                self.ui.note('status: %r dir(%d) -> %s\n' %
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:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   296
                self.ui.note('status: %r %s -> %s\n' %
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':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   300
                d[fn] = status
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:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   304
                        dd[fn] = status
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
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   339
            status = state[0]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   340
            st = self.getstat(wfn)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   341
            if status == 'r' and not st:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   342
                self.updatestatus(wfn, st, status=status)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   343
            else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   344
                self.updatestatus(wfn, st, oldstatus=status)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   345
        self.check_deleted('!')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   346
        self.check_deleted('r')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   347
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   348
    def check_dirstate(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   349
        ds_info = self.dirstate_info()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   350
        if ds_info == self.ds_info:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   351
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   352
        self.ds_info = ds_info
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   353
        if not self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   354
            self.last_event = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   355
        self.ui.note(_('%s dirstate reload\n') % self.event_time())
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   356
        self.repo.dirstate.invalidate()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   357
        self.scan()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   358
        self.ui.note(_('%s end dirstate reload\n') % self.event_time())
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   359
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   360
    def walk(self, states, tree, prefix=''):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   361
        # This is the "inner loop" when talking to the client.
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   362
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   363
        for name, val in tree.iteritems():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   364
            path = join(prefix, name)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   365
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   366
                if val in states:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   367
                    yield path, val
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   368
            except TypeError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   369
                for p in self.walk(states, val, path):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   370
                    yield p
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   371
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   372
    def update_hgignore(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   373
        # An update of the ignore file can potentially change the
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   374
        # states of all unknown and ignored files.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   375
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   376
        # 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
   377
        # changes their list of ignore files at run time, we'll
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   378
        # potentially never see changes to them.  We could get the
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   379
        # client to report to us what ignore data they're using.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   380
        # 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
   381
        # worms.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   382
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   383
        if self.repo.dirstate.ignorefunc is not None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   384
            self.repo.dirstate.ignorefunc = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   385
            self.ui.note('rescanning due to .hgignore change\n')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   386
            self.scan()
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   387
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   388
    def getstat(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   389
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   390
            return self.statcache[wpath]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   391
        except KeyError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   392
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   393
                return self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   394
            except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   395
                if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   396
                    raise
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   397
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   398
    def stat(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   399
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   400
            st = os.lstat(join(self.wprefix, wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   401
            ret = st.st_mode, st.st_size, st.st_mtime
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   402
            self.statcache[wpath] = ret
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   403
            return ret
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   404
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   405
            self.statcache.pop(wpath, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   406
            raise
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   407
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   408
    def created(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   409
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   410
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   411
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   412
            st = self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   413
            if stat.S_ISREG(st[0]):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   414
                self.updatestatus(wpath, st)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   415
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   416
            pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   417
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   418
    def modified(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   419
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   420
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   421
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   422
            st = self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   423
            if stat.S_ISREG(st[0]):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   424
                if self.repo.dirstate[wpath] in 'lmn':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   425
                    self.updatestatus(wpath, st)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   426
        except OSError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   427
            pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   428
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   429
    def deleted(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   430
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   431
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   432
        elif wpath.startswith('.hg/'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   433
            if wpath == '.hg/wlock':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   434
                self.check_dirstate()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   435
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   436
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   437
        self.updatestatus(wpath, None)
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   438
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   439
    def schedule_work(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   440
        self.eventq.setdefault(wpath, [])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   441
        prev = self.eventq[wpath]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   442
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   443
            if prev and evt == 'm' and prev[-1] in 'cm':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   444
                return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   445
            self.eventq[wpath].append(evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   446
        finally:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   447
            self.deferred += 1
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   448
            self.timeout = 250
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   449
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   450
    def deferred_event(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   451
        if evt == 'c':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   452
            self.created(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   453
        elif evt == 'm':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   454
            self.modified(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   455
        elif evt == 'd':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   456
            self.deleted(wpath)
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   457
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   458
    def process_create(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   459
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   460
            self.ui.note(_('%s event: created %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   461
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   462
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   463
        if evt.mask & inotify.IN_ISDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   464
            self.scan(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   465
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   466
            self.schedule_work(wpath, 'c')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   467
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   468
    def process_delete(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   469
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   470
            self.ui.note(('%s event: deleted %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   471
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   472
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   473
        if evt.mask & inotify.IN_ISDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   474
            self.scan(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   475
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   476
            self.schedule_work(wpath, 'd')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   477
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   478
    def process_modify(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   479
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   480
            self.ui.note(_('%s event: modified %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   481
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   482
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   483
        if not (evt.mask & inotify.IN_ISDIR):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   484
            self.schedule_work(wpath, 'm')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   485
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   486
    def process_unmount(self, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   487
        self.ui.warn(_('filesystem containing %s was unmounted\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   488
                     evt.fullpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   489
        sys.exit(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   490
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   491
    def handle_event(self, fd, event):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   492
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   493
            self.ui.note('%s readable: %d bytes\n' %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   494
                         (self.event_time(), self.threshold.readable()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   495
        if not self.threshold():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   496
            if self.registered:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   497
                if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   498
                    self.ui.note('%s below threshold - unhooking\n' %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   499
                                 (self.event_time()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   500
                self.master.poll.unregister(fd)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   501
                self.registered = False
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   502
                self.timeout = 250
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   503
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   504
            self.read_events()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   505
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   506
    def read_events(self, bufsize=None):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   507
        events = self.watcher.read(bufsize)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   508
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   509
            self.ui.note('%s reading %d events\n' %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   510
                         (self.event_time(), len(events)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   511
        for evt in events:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   512
            wpath = self.wpath(evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   513
            if evt.mask & inotify.IN_UNMOUNT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   514
                self.process_unmount(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   515
            elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   516
                self.process_modify(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   517
            elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF |
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   518
                             inotify.IN_MOVED_FROM):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   519
                self.process_delete(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   520
            elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   521
                self.process_create(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   522
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   523
    def handle_timeout(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   524
        if not self.registered:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   525
            if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   526
                self.ui.note('%s hooking back up with %d bytes readable\n' %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   527
                             (self.event_time(), self.threshold.readable()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   528
            self.read_events(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   529
            self.master.poll.register(self, select.POLLIN)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   530
            self.registered = True
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   531
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   532
        if self.eventq:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   533
            if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   534
                self.ui.note('%s processing %d deferred events as %d\n' %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   535
                             (self.event_time(), self.deferred,
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   536
                              len(self.eventq)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   537
            eventq = self.eventq.items()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   538
            eventq.sort()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   539
            for wpath, evts in eventq:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   540
                for evt in evts:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   541
                    self.deferred_event(wpath, evt)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   542
            self.eventq.clear()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   543
            self.deferred = 0
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   544
        self.timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   545
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   546
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   547
        self.watcher.close()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   548
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   549
class Server(object):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   550
    poll_events = select.POLLIN
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   551
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   552
    def __init__(self, ui, repo, watcher, timeout):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   553
        self.ui = ui
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   554
        self.repo = repo
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   555
        self.watcher = watcher
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   556
        self.timeout = timeout
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   557
        self.sock = socket.socket(socket.AF_UNIX)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   558
        self.sockpath = self.repo.join('inotify.sock')
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:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   563
                raise AlreadyStartedException(_('could not start server: %s') \
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   564
                                              % err[1])
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   565
            raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   566
        self.sock.listen(5)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   567
        self.fileno = self.sock.fileno
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   568
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   569
    def handle_timeout(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   570
        pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   571
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   572
    def handle_event(self, fd, event):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   573
        sock, addr = self.sock.accept()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   574
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   575
        cs = common.recvcs(sock)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   576
        version = ord(cs.read(1))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   577
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   578
        sock.sendall(chr(common.version))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   579
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   580
        if version != common.version:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   581
            self.ui.warn(_('received query from incompatible client '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   582
                           'version %d\n') % version)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   583
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   584
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   585
        names = cs.read().split('\0')
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   586
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   587
        states = names.pop()
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
        self.ui.note(_('answering query for %r\n') % states)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   590
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   591
        if self.watcher.timeout:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   592
            # 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
   593
            # rescan before responding, or we could give back a wrong
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   594
            # answer.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   595
            self.watcher.handle_timeout()
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 not names:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   598
            def genresult(states, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   599
                for fn, state in self.watcher.walk(states, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   600
                    yield fn
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   601
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   602
            def genresult(states, tree):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   603
                for fn in names:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   604
                    l = self.watcher.lookup(fn, tree)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   605
                    try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   606
                        if l in states:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   607
                            yield fn
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   608
                    except TypeError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   609
                        for f, s in self.watcher.walk(states, l, fn):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   610
                            yield f
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   611
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   612
        results = ['\0'.join(r) for r in [
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   613
            genresult('l', self.watcher.statustrees['l']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   614
            genresult('m', self.watcher.statustrees['m']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   615
            genresult('a', self.watcher.statustrees['a']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   616
            genresult('r', self.watcher.statustrees['r']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   617
            genresult('!', self.watcher.statustrees['!']),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   618
            '?' in states and genresult('?', self.watcher.statustrees['?']) or [],
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   619
            [],
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   620
            'c' in states and genresult('n', self.watcher.tree) or [],
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   621
            ]]
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   622
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   623
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   624
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   625
                sock.sendall(struct.pack(common.resphdrfmt,
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   626
                                         *map(len, results)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   627
                sock.sendall(''.join(results))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   628
            finally:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   629
                sock.shutdown(socket.SHUT_WR)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   630
        except socket.error, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   631
            if err[0] != errno.EPIPE:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   632
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   633
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   634
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   635
        self.sock.close()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   636
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   637
            os.unlink(self.sockpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   638
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   639
            if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   640
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   641
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   642
class Master(object):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   643
    def __init__(self, ui, repo, timeout=None):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   644
        self.ui = ui
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   645
        self.repo = repo
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   646
        self.poll = select.poll()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   647
        self.watcher = Watcher(ui, repo, self)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   648
        self.server = Server(ui, repo, self.watcher, timeout)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   649
        self.table = {}
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   650
        for obj in (self.watcher, self.server):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   651
            fd = obj.fileno()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   652
            self.table[fd] = obj
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   653
            self.poll.register(fd, obj.poll_events)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   654
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   655
    def register(self, fd, mask):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   656
        self.poll.register(fd, mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   657
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   658
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   659
        for obj in self.table.itervalues():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   660
            obj.shutdown()
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
    def run(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   663
        self.watcher.setup()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   664
        self.ui.note(_('finished setup\n'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   665
        if os.getenv('TIME_STARTUP'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   666
            sys.exit(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   667
        while True:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   668
            timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   669
            timeobj = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   670
            for obj in self.table.itervalues():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   671
                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
   672
                    timeout, timeobj = obj.timeout, obj
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   673
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   674
                if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   675
                    if timeout is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   676
                        self.ui.note('polling: no timeout\n')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   677
                    else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   678
                        self.ui.note('polling: %sms timeout\n' % timeout)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   679
                events = self.poll.poll(timeout)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   680
            except select.error, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   681
                if err[0] == errno.EINTR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   682
                    continue
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   683
                raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   684
            if events:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   685
                for fd, event in events:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   686
                    self.table[fd].handle_event(fd, event)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   687
            elif timeobj:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   688
                timeobj.handle_timeout()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   689
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   690
def start(ui, repo):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   691
    m = Master(ui, repo)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   692
    sys.stdout.flush()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   693
    sys.stderr.flush()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   694
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   695
    pid = os.fork()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   696
    if pid:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   697
        return pid
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   698
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   699
    os.setsid()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   700
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   701
    fd = os.open('/dev/null', os.O_RDONLY)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   702
    os.dup2(fd, 0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   703
    if fd > 0:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   704
        os.close(fd)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   705
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   706
    fd = os.open(ui.config('inotify', 'log', '/dev/null'),
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   707
                 os.O_RDWR | os.O_CREAT | os.O_TRUNC)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   708
    os.dup2(fd, 1)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   709
    os.dup2(fd, 2)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   710
    if fd > 2:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   711
        os.close(fd)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   712
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   713
    try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   714
        m.run()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   715
    finally:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   716
        m.shutdown()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   717
        os._exit(0)