hgext/inotify/linuxserver.py
author Bryan O'Sullivan <bryano@fb.com>
Thu, 21 Mar 2013 16:31:29 -0700
changeset 18793 a821ec835223
parent 18097 ae54cff742e2
permissions -rw-r--r--
completion: selectively use debugpathcomplete in bash_completion The current bash_completion code can be very slow in a large working directory. It always uses "hg status" to generate possibly matching files, which checks the status of every file. We often don't care about status when completing, so that cost is very high. As the new debugpathcomplete command does not check the status of files, it offers much better performance for commands that only care about completing names.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
     1
# linuxserver.py - inotify status server for linux
6239
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
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     6
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9900
diff changeset
     7
# GNU General Public License version 2 or any later version.
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     8
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
     9
from mercurial.i18n import _
16354
9f98fe05ecf1 inotify: catch SignalInterrupt during shutdown (issue3351)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 14179
diff changeset
    10
from mercurial import osutil, util, error
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
    11
import server
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
    12
import errno, os, select, stat, sys, time
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    13
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    14
try:
6994
bf727bab38b9 Use relative imports in inotify.server.
Brendan Cully <brendan@kublai.com>
parents: 6287
diff changeset
    15
    import linux as inotify
bf727bab38b9 Use relative imports in inotify.server.
Brendan Cully <brendan@kublai.com>
parents: 6287
diff changeset
    16
    from linux import watcher
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    17
except ImportError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    18
    raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    19
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
    20
def walkrepodirs(dirstate, absroot):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    21
    '''Iterate over all subdirectories of this repo.
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    22
    Exclude the .hg directory, any nested repos, and ignored dirs.'''
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    23
    def walkit(dirname, top):
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
    24
        fullpath = server.join(absroot, dirname)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
        try:
8321
ec985dcfd7da inotify: inotify.server.walkrepodirs() simplify
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8320
diff changeset
    26
            for name, kind in osutil.listdir(fullpath):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    27
                if kind == stat.S_IFDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    28
                    if name == '.hg':
8323
589a82fb02a2 inotify: inotify.server.walk*() cleanup
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8322
diff changeset
    29
                        if not top:
589a82fb02a2 inotify: inotify.server.walk*() cleanup
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8322
diff changeset
    30
                            return
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    31
                    else:
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
    32
                        d = server.join(dirname, name)
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
    33
                        if dirstate._ignore(d):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    34
                            continue
8322
3c6c21eb3416 inotify: inotify.server.walkrepodirs() simplify walking
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8321
diff changeset
    35
                        for subdir in walkit(d, False):
3c6c21eb3416 inotify: inotify.server.walkrepodirs() simplify walking
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8321
diff changeset
    36
                            yield subdir
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    37
        except OSError, err:
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
    38
            if err.errno not in server.walk_ignored_errors:
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    39
                raise
8324
b923d599c309 inotify: inotify.server.walk*() remove unnecessary var
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8323
diff changeset
    40
        yield fullpath
8322
3c6c21eb3416 inotify: inotify.server.walkrepodirs() simplify walking
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8321
diff changeset
    41
3c6c21eb3416 inotify: inotify.server.walkrepodirs() simplify walking
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8321
diff changeset
    42
    return walkit('', True)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    43
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
    44
def _explain_watch_limit(ui, dirstate, rootabs):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
    path = '/proc/sys/fs/inotify/max_user_watches'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    46
    try:
14179
64481eee6215 hgext: fixup a couple missed file().read() instances
Matt Mackall <mpm@selenic.com>
parents: 11567
diff changeset
    47
        limit = int(util.readfile(path))
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    48
    except IOError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    49
        if err.errno != errno.ENOENT:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
            raise
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
        raise util.Abort(_('this system does not seem to '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    52
                           'support inotify'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    53
    ui.warn(_('*** the current per-user limit on the number '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    54
              'of inotify watches is %s\n') % limit)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    55
    ui.warn(_('*** this limit is too low to watch every '
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
              'directory in this repository\n'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    57
    ui.warn(_('*** counting directories: '))
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
    58
    ndirs = len(list(walkrepodirs(dirstate, rootabs)))
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    59
    ui.warn(_('found %d\n') % ndirs)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    60
    newlimit = min(limit, 1024)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    61
    while newlimit < ((limit + ndirs) * 1.1):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    62
        newlimit *= 2
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    63
    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
    64
            (limit, newlimit))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    65
    ui.warn(_('***  echo %d > %s\n') % (newlimit, path))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    66
    raise util.Abort(_('cannot watch %s until inotify watch limit is raised')
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
    67
                     % rootabs)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    68
8610
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    69
class pollable(object):
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    70
    """
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    71
    Interface to support polling.
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    72
    The file descriptor returned by fileno() is registered to a polling
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    73
    object.
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    74
    Usage:
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    75
        Every tick, check if an event has happened since the last tick:
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    76
        * If yes, call handle_events
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    77
        * If no, call handle_timeout
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    78
    """
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    79
    poll_events = select.POLLIN
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    80
    instances = {}
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    81
    poll = select.poll()
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    82
8610
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    83
    def fileno(self):
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    84
        raise NotImplementedError
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    85
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    86
    def handle_events(self, events):
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    87
        raise NotImplementedError
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    88
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    89
    def handle_timeout(self):
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    90
        raise NotImplementedError
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    91
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    92
    def shutdown(self):
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    93
        raise NotImplementedError
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
    94
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    95
    def register(self, timeout):
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    96
        fd = self.fileno()
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    97
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    98
        pollable.poll.register(fd, pollable.poll_events)
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
    99
        pollable.instances[fd] = self
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   100
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   101
        self.registered = True
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   102
        self.timeout = timeout
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   103
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   104
    def unregister(self):
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   105
        pollable.poll.unregister(self)
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   106
        self.registered = False
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   107
8793
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   108
    @classmethod
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   109
    def run(cls):
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   110
        while True:
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   111
            timeout = None
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   112
            timeobj = None
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   113
            for obj in cls.instances.itervalues():
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   114
                if obj.timeout is not None and (timeout is None
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   115
                                                or obj.timeout < timeout):
8793
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   116
                    timeout, timeobj = obj.timeout, obj
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   117
            try:
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   118
                events = cls.poll.poll(timeout)
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   119
            except select.error, err:
11567
34cc8b84407f removed exception args indexing (not supported by py3k)
Renato Cunha <renatoc@gmail.com>
parents: 10494
diff changeset
   120
                if err.args[0] == errno.EINTR:
8793
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   121
                    continue
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   122
                raise
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   123
            if events:
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   124
                by_fd = {}
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   125
                for fd, event in events:
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   126
                    by_fd.setdefault(fd, []).append(event)
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   127
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   128
                for fd, events in by_fd.iteritems():
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   129
                    cls.instances[fd].handle_pollevents(events)
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   130
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   131
            elif timeobj:
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   132
                timeobj.handle_timeout()
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   133
8791
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   134
def eventaction(code):
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   135
    """
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   136
    Decorator to help handle events in repowatcher
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   137
    """
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   138
    def decorator(f):
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   139
        def wrapper(self, wpath):
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   140
            if code == 'm' and wpath in self.lastevent and \
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   141
                self.lastevent[wpath] in 'cm':
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   142
                return
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   143
            self.lastevent[wpath] = code
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   144
            self.timeout = 250
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   145
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   146
            f(self, wpath)
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   147
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   148
        wrapper.func_name = f.func_name
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   149
        return wrapper
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   150
    return decorator
23730a475363 inotify.server: the decorator eventaction() shouldn't be a method of repowatcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8787
diff changeset
   151
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   152
class repowatcher(server.repowatcher, pollable):
8610
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
   153
    """
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
   154
    Watches inotify events
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
   155
    """
8383
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   156
    mask = (
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   157
        inotify.IN_ATTRIB |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   158
        inotify.IN_CREATE |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   159
        inotify.IN_DELETE |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   160
        inotify.IN_DELETE_SELF |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   161
        inotify.IN_MODIFY |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   162
        inotify.IN_MOVED_FROM |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   163
        inotify.IN_MOVED_TO |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   164
        inotify.IN_MOVE_SELF |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   165
        inotify.IN_ONLYDIR |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   166
        inotify.IN_UNMOUNT |
dcfdcb51ac5c inotify: make mask a class variable since it's instance-independant
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8382
diff changeset
   167
        0)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   168
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   169
    def __init__(self, ui, dirstate, root):
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   170
        server.repowatcher.__init__(self, ui, dirstate, root)
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   171
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   172
        self.lastevent = {}
10090
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   173
        self.dirty = False
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   174
        try:
8385
1536501ade62 inotify: Coding Style: name classes in lowercase.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8384
diff changeset
   175
            self.watcher = watcher.watcher()
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   176
        except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   177
            raise util.Abort(_('inotify service not available: %s') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   178
                             err.strerror)
8385
1536501ade62 inotify: Coding Style: name classes in lowercase.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8384
diff changeset
   179
        self.threshold = watcher.threshold(self.watcher)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   180
        self.fileno = self.watcher.fileno
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   181
        self.register(timeout=None)
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   182
8604
578f2a0049cd inotify: do not recurse in handle_timeout(): call it explicitely, not in scan()
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8600
diff changeset
   183
        self.handle_timeout()
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   184
        self.scan()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   185
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   186
    def event_time(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   187
        last = self.last_event
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   188
        now = time.time()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   189
        self.last_event = now
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   190
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   191
        if last is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   192
            return 'start'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   193
        delta = now - last
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   194
        if delta < 5:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   195
            return '+%.3f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   196
        if delta < 50:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   197
            return '+%.2f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   198
        return '+%.1f' % delta
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   199
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   200
    def add_watch(self, path, mask):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   201
        if not path:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   202
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   203
        if self.watcher.path(path) is None:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   204
            if self.ui.debugflag:
9349
56fb15ad8fb1 inotify: server: use wprefix everywhere, introduce prefixlen
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9348
diff changeset
   205
                self.ui.note(_('watching %r\n') % path[self.prefixlen:])
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   206
            try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   207
                self.watcher.add(path, mask)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   208
            except OSError, err:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   209
                if err.errno in (errno.ENOENT, errno.ENOTDIR):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   210
                    return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   211
                if err.errno != errno.ENOSPC:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   212
                    raise
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   213
                _explain_watch_limit(self.ui, self.dirstate, self.wprefix)
6239
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 setup(self):
9349
56fb15ad8fb1 inotify: server: use wprefix everywhere, introduce prefixlen
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9348
diff changeset
   216
        self.ui.note(_('watching directories under %r\n') % self.wprefix)
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   217
        self.add_watch(self.wprefix + '.hg', inotify.IN_DELETE)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   218
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   219
    def scan(self, topdir=''):
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   220
        ds = self.dirstate._map.copy()
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   221
        self.add_watch(server.join(self.wprefix, topdir), self.mask)
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   222
        for root, dirs, files in server.walk(self.dirstate, self.wprefix,
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   223
                                             topdir):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   224
            for d in dirs:
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   225
                self.add_watch(server.join(root, d), self.mask)
9349
56fb15ad8fb1 inotify: server: use wprefix everywhere, introduce prefixlen
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9348
diff changeset
   226
            wroot = root[self.prefixlen:]
8334
0695288e8c37 inotify: inotify.server.walk() filetype is never used, do not yield it
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8325
diff changeset
   227
            for fn in files:
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   228
                wfn = server.join(wroot, fn)
8599
1f706b1b62f3 inotify: server: refactor updatestatus()
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8557
diff changeset
   229
                self.updatefile(wfn, self.getstat(wfn))
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   230
                ds.pop(wfn, None)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   231
        wtopdir = topdir
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   232
        if wtopdir and wtopdir[-1] != '/':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   233
            wtopdir += '/'
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   234
        for wfn, state in ds.iteritems():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   235
            if not wfn.startswith(wtopdir):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   236
                continue
7302
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   237
            try:
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   238
                st = self.stat(wfn)
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   239
            except OSError:
972737252d05 inotify: server raising an error when removing a file (issue1371)
Gerard Korsten <soonkia77@gmail.com>
parents: 7280
diff changeset
   240
                status = state[0]
8599
1f706b1b62f3 inotify: server: refactor updatestatus()
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8557
diff changeset
   241
                self.deletefile(wfn, status)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   242
            else:
8599
1f706b1b62f3 inotify: server: refactor updatestatus()
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8557
diff changeset
   243
                self.updatefile(wfn, st)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   244
        self.check_deleted('!')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   245
        self.check_deleted('r')
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   246
8606
1c5752dabf76 inotify: use a decorator instead of dispatching calls
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8605
diff changeset
   247
    @eventaction('c')
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   248
    def created(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   249
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   250
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   251
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   252
            st = self.stat(wpath)
10089
8fab31727037 inotify: follow new files if they are regular or a symlink.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9933
diff changeset
   253
            if stat.S_ISREG(st[0]) or stat.S_ISLNK(st[0]):
8599
1f706b1b62f3 inotify: server: refactor updatestatus()
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8557
diff changeset
   254
                self.updatefile(wpath, st)
7280
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7220
diff changeset
   255
        except OSError:
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   256
            pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   257
8606
1c5752dabf76 inotify: use a decorator instead of dispatching calls
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8605
diff changeset
   258
    @eventaction('m')
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   259
    def modified(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   260
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   261
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   262
        try:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   263
            st = self.stat(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   264
            if stat.S_ISREG(st[0]):
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   265
                if self.dirstate[wpath] in 'lmn':
8599
1f706b1b62f3 inotify: server: refactor updatestatus()
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8557
diff changeset
   266
                    self.updatefile(wpath, st)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   267
        except OSError:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   268
            pass
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   269
8606
1c5752dabf76 inotify: use a decorator instead of dispatching calls
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8605
diff changeset
   270
    @eventaction('d')
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   271
    def deleted(self, wpath):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   272
        if wpath == '.hgignore':
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   273
            self.update_hgignore()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   274
        elif wpath.startswith('.hg/'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   275
            return
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   276
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   277
        self.deletefile(wpath, self.dirstate[wpath])
6287
c86207d41512 Spacing cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6239
diff changeset
   278
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   279
    def process_create(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   280
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   281
            self.ui.note(_('%s event: created %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   282
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   283
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   284
        if evt.mask & inotify.IN_ISDIR:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   285
            self.scan(wpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   286
        else:
8606
1c5752dabf76 inotify: use a decorator instead of dispatching calls
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8605
diff changeset
   287
            self.created(wpath)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   288
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   289
    def process_delete(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   290
        if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   291
            self.ui.note(_('%s event: deleted %s\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   292
                         (self.event_time(), wpath))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   293
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   294
        if evt.mask & inotify.IN_ISDIR:
9115
b55d44719b47 inotify: server: new data structure to keep track of changes.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8953
diff changeset
   295
            tree = self.tree.dir(wpath)
b55d44719b47 inotify: server: new data structure to keep track of changes.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8953
diff changeset
   296
            todelete = [wfn for wfn, ignore in tree.walk('?')]
b55d44719b47 inotify: server: new data structure to keep track of changes.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8953
diff changeset
   297
            for fn in todelete:
b55d44719b47 inotify: server: new data structure to keep track of changes.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8953
diff changeset
   298
                self.deletefile(fn, '?')
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   299
            self.scan(wpath)
8600
d46cdfcecaf1 inotify: proper fix for issue1542 (partially reverting 67e59a9886d5)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8599
diff changeset
   300
        else:
8606
1c5752dabf76 inotify: use a decorator instead of dispatching calls
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8605
diff changeset
   301
            self.deleted(wpath)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   302
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   303
    def process_modify(self, wpath, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   304
        if self.ui.debugflag:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   305
            self.ui.note(_('%s event: modified %s\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   306
                         (self.event_time(), wpath))
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
        if not (evt.mask & inotify.IN_ISDIR):
8606
1c5752dabf76 inotify: use a decorator instead of dispatching calls
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8605
diff changeset
   309
            self.modified(wpath)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   310
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   311
    def process_unmount(self, evt):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   312
        self.ui.warn(_('filesystem containing %s was unmounted\n') %
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   313
                     evt.fullpath)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   314
        sys.exit(0)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   315
8609
aeaa0bd9dc24 inotify: process all inotify events in one batch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8608
diff changeset
   316
    def handle_pollevents(self, events):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   317
        if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   318
            self.ui.note(_('%s readable: %d bytes\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   319
                         (self.event_time(), self.threshold.readable()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   320
        if not self.threshold():
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   321
            if self.registered:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   322
                if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   323
                    self.ui.note(_('%s below threshold - unhooking\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   324
                                 (self.event_time()))
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   325
                self.unregister()
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   326
                self.timeout = 250
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   327
        else:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   328
            self.read_events()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   329
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   330
    def read_events(self, bufsize=None):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   331
        events = self.watcher.read(bufsize)
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   332
        if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   333
            self.ui.note(_('%s reading %d events\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   334
                         (self.event_time(), len(events)))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   335
        for evt in events:
10091
0ce645cc3f20 inotify: completely ignore events on the repository root
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10090
diff changeset
   336
            if evt.fullpath == self.wprefix[:-1]:
0ce645cc3f20 inotify: completely ignore events on the repository root
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10090
diff changeset
   337
                # events on the root of the repository
0ce645cc3f20 inotify: completely ignore events on the repository root
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10090
diff changeset
   338
                # itself, e.g. permission changes or repository move
0ce645cc3f20 inotify: completely ignore events on the repository root
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10090
diff changeset
   339
                continue
8953
e1d119f450f0 inotify: server: remove wpath method
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8952
diff changeset
   340
            assert evt.fullpath.startswith(self.wprefix)
9349
56fb15ad8fb1 inotify: server: use wprefix everywhere, introduce prefixlen
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9348
diff changeset
   341
            wpath = evt.fullpath[self.prefixlen:]
8953
e1d119f450f0 inotify: server: remove wpath method
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8952
diff changeset
   342
9117
a87bc6e2a907 inotify: server: explicitely ignore events in subdirs of .hg/ (issue1735)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9116
diff changeset
   343
            # paths have been normalized, wpath never ends with a '/'
a87bc6e2a907 inotify: server: explicitely ignore events in subdirs of .hg/ (issue1735)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9116
diff changeset
   344
a87bc6e2a907 inotify: server: explicitely ignore events in subdirs of .hg/ (issue1735)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9116
diff changeset
   345
            if wpath.startswith('.hg/') and evt.mask & inotify.IN_ISDIR:
a87bc6e2a907 inotify: server: explicitely ignore events in subdirs of .hg/ (issue1735)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9116
diff changeset
   346
                # ignore subdirectories of .hg/ (merge, patches...)
a87bc6e2a907 inotify: server: explicitely ignore events in subdirs of .hg/ (issue1735)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9116
diff changeset
   347
                continue
10090
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   348
            if wpath == ".hg/wlock":
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   349
                if evt.mask & inotify.IN_DELETE:
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   350
                    self.dirstate.invalidate()
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   351
                    self.dirty = False
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   352
                    self.scan()
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   353
                elif evt.mask & inotify.IN_CREATE:
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   354
                    self.dirty = True
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   355
            else:
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   356
                if self.dirty:
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   357
                    continue
9117
a87bc6e2a907 inotify: server: explicitely ignore events in subdirs of .hg/ (issue1735)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9116
diff changeset
   358
10090
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   359
                if evt.mask & inotify.IN_UNMOUNT:
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   360
                    self.process_unmount(wpath, evt)
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   361
                elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB):
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   362
                    self.process_modify(wpath, evt)
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   363
                elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF |
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   364
                                 inotify.IN_MOVED_FROM):
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   365
                    self.process_delete(wpath, evt)
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   366
                elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO):
a3ad96ead8f0 inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 10089
diff changeset
   367
                    self.process_create(wpath, evt)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   368
8605
ed2d9bdbfad2 inotify: do not defer inotify events processing
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8604
diff changeset
   369
        self.lastevent.clear()
ed2d9bdbfad2 inotify: do not defer inotify events processing
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8604
diff changeset
   370
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   371
    def handle_timeout(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   372
        if not self.registered:
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   373
            if self.ui.debugflag:
6961
12163fb21fce i18n: mark strings for translation in inotify extension
Martin Geisler <mg@daimi.au.dk>
parents: 6909
diff changeset
   374
                self.ui.note(_('%s hooking back up with %d bytes readable\n') %
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   375
                             (self.event_time(), self.threshold.readable()))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   376
            self.read_events(0)
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   377
            self.register(timeout=None)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   378
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   379
        self.timeout = None
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   380
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   381
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   382
        self.watcher.close()
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   383
8555
3e09bc5fee12 inotify: introduce debuginotify, which lists which paths are under watch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8554
diff changeset
   384
    def debug(self):
3e09bc5fee12 inotify: introduce debuginotify, which lists which paths are under watch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8554
diff changeset
   385
        """
3e09bc5fee12 inotify: introduce debuginotify, which lists which paths are under watch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8554
diff changeset
   386
        Returns a sorted list of relatives paths currently watched,
3e09bc5fee12 inotify: introduce debuginotify, which lists which paths are under watch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8554
diff changeset
   387
        for debugging purposes.
3e09bc5fee12 inotify: introduce debuginotify, which lists which paths are under watch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8554
diff changeset
   388
        """
9349
56fb15ad8fb1 inotify: server: use wprefix everywhere, introduce prefixlen
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9348
diff changeset
   389
        return sorted(tuple[0][self.prefixlen:] for tuple in self.watcher)
8555
3e09bc5fee12 inotify: introduce debuginotify, which lists which paths are under watch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8554
diff changeset
   390
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   391
class socketlistener(server.socketlistener, pollable):
8610
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
   392
    """
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
   393
    Listens for client queries on unix socket inotify.sock
8ef1f63e554c inotify: server: use a common 'pollable' interface for server & repowatcher
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8609
diff changeset
   394
    """
9350
b789ea382fc0 inotify: server: use dirstate instead of repo
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9349
diff changeset
   395
    def __init__(self, ui, root, repowatcher, timeout):
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   396
        server.socketlistener.__init__(self, ui, root, repowatcher, timeout)
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   397
        self.register(timeout=timeout)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   398
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   399
    def handle_timeout(self):
10494
08064db9f005 inotify/inserve: implement --timeout-idle option (issue885)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10463
diff changeset
   400
        raise server.TimeoutException
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   401
8609
aeaa0bd9dc24 inotify: process all inotify events in one batch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8608
diff changeset
   402
    def handle_pollevents(self, events):
aeaa0bd9dc24 inotify: process all inotify events in one batch
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8608
diff changeset
   403
        for e in events:
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   404
            self.accept_connection()
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   405
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   406
    def shutdown(self):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   407
        self.sock.close()
18097
ae54cff742e2 posix: move server side of unix domain sockets out of inotify
Bryan O'Sullivan <bryano@fb.com>
parents: 16354
diff changeset
   408
        self.sock.cleanup()
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   409
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   410
    def answer_stat_query(self, cs):
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   411
        if self.repowatcher.timeout:
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   412
            # We got a query while a rescan is pending.  Make sure we
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   413
            # rescan before responding, or we could give back a wrong
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   414
            # answer.
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   415
            self.repowatcher.handle_timeout()
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   416
        return server.socketlistener.answer_stat_query(self, cs)
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   417
8385
1536501ade62 inotify: Coding Style: name classes in lowercase.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8384
diff changeset
   418
class master(object):
9351
206f7f4c5c2a inotify: client: no repo use
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9350
diff changeset
   419
    def __init__(self, ui, dirstate, root, timeout=None):
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   420
        self.ui = ui
9351
206f7f4c5c2a inotify: client: no repo use
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9350
diff changeset
   421
        self.repowatcher = repowatcher(ui, dirstate, root)
9933
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   422
        self.socketlistener = socketlistener(ui, root, self.repowatcher,
2e7902158af9 inotify: create a common, OS-independent server entry point
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9900
diff changeset
   423
                                             timeout)
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   424
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   425
    def shutdown(self):
8792
3e23b1d20837 inotify: refactor (un)register methods into pollable object
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8791
diff changeset
   426
        for obj in pollable.instances.itervalues():
16354
9f98fe05ecf1 inotify: catch SignalInterrupt during shutdown (issue3351)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 14179
diff changeset
   427
            try:
9f98fe05ecf1 inotify: catch SignalInterrupt during shutdown (issue3351)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 14179
diff changeset
   428
                obj.shutdown()
9f98fe05ecf1 inotify: catch SignalInterrupt during shutdown (issue3351)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 14179
diff changeset
   429
            except error.SignalInterrupt:
9f98fe05ecf1 inotify: catch SignalInterrupt during shutdown (issue3351)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 14179
diff changeset
   430
                pass
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   431
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   432
    def run(self):
8335
713ec3f9c9de inotify: Clarify the use of "watcher" name.
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8334
diff changeset
   433
        self.repowatcher.setup()
6239
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   434
        self.ui.note(_('finished setup\n'))
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   435
        if os.getenv('TIME_STARTUP'):
39cfcef4f463 Add inotify extension
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   436
            sys.exit(0)
8793
9d0c521bce0e inotify: put the "while True: poll()" loop in pollable class
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8792
diff changeset
   437
        pollable.run()