##// END OF EJS Templates
inotify: fix status . in repo.root
Brendan Cully -
r7393:92c952c4 default
parent child Browse files
Show More
@@ -1,123 +1,125
1 # __init__.py - inotify-based status acceleration for Linux
1 # __init__.py - inotify-based status acceleration for Linux
2 #
2 #
3 # Copyright 2006, 2007, 2008 Bryan O'Sullivan <bos@serpentine.com>
3 # Copyright 2006, 2007, 2008 Bryan O'Sullivan <bos@serpentine.com>
4 # Copyright 2007, 2008 Brendan Cully <brendan@kublai.com>
4 # Copyright 2007, 2008 Brendan Cully <brendan@kublai.com>
5 #
5 #
6 # This software may be used and distributed according to the terms
6 # This software may be used and distributed according to the terms
7 # of the GNU General Public License, incorporated herein by reference.
7 # of the GNU General Public License, incorporated herein by reference.
8
8
9 '''inotify-based status acceleration for Linux systems
9 '''inotify-based status acceleration for Linux systems
10 '''
10 '''
11
11
12 # todo: socket permissions
12 # todo: socket permissions
13
13
14 from mercurial.i18n import _
14 from mercurial.i18n import _
15 from mercurial import cmdutil, util
15 from mercurial import cmdutil, util
16 import client, errno, os, server, socket
16 import client, errno, os, server, socket
17 from weakref import proxy
17 from weakref import proxy
18
18
19 def serve(ui, repo, **opts):
19 def serve(ui, repo, **opts):
20 '''start an inotify server for this repository'''
20 '''start an inotify server for this repository'''
21 timeout = opts.get('timeout')
21 timeout = opts.get('timeout')
22 if timeout:
22 if timeout:
23 timeout = float(timeout) * 1e3
23 timeout = float(timeout) * 1e3
24
24
25 class service:
25 class service:
26 def init(self):
26 def init(self):
27 try:
27 try:
28 self.master = server.Master(ui, repo, timeout)
28 self.master = server.Master(ui, repo, timeout)
29 except server.AlreadyStartedException, inst:
29 except server.AlreadyStartedException, inst:
30 raise util.Abort(str(inst))
30 raise util.Abort(str(inst))
31
31
32 def run(self):
32 def run(self):
33 try:
33 try:
34 self.master.run()
34 self.master.run()
35 finally:
35 finally:
36 self.master.shutdown()
36 self.master.shutdown()
37
37
38 service = service()
38 service = service()
39 cmdutil.service(opts, initfn=service.init, runfn=service.run)
39 cmdutil.service(opts, initfn=service.init, runfn=service.run)
40
40
41 def reposetup(ui, repo):
41 def reposetup(ui, repo):
42 if not repo.local():
42 if not repo.local():
43 return
43 return
44
44
45 # XXX: weakref until hg stops relying on __del__
45 # XXX: weakref until hg stops relying on __del__
46 repo = proxy(repo)
46 repo = proxy(repo)
47
47
48 class inotifydirstate(repo.dirstate.__class__):
48 class inotifydirstate(repo.dirstate.__class__):
49 # Set to True if we're the inotify server, so we don't attempt
49 # Set to True if we're the inotify server, so we don't attempt
50 # to recurse.
50 # to recurse.
51 inotifyserver = False
51 inotifyserver = False
52
52
53 def status(self, match, ignored, clean, unknown=True):
53 def status(self, match, ignored, clean, unknown=True):
54 files = match.files()
54 files = match.files()
55 if '.' in files:
56 files = []
55 try:
57 try:
56 if not ignored and not self.inotifyserver:
58 if not ignored and not self.inotifyserver:
57 result = client.query(ui, repo, files, match, False,
59 result = client.query(ui, repo, files, match, False,
58 clean, unknown)
60 clean, unknown)
59 if ui.config('inotify', 'debug'):
61 if ui.config('inotify', 'debug'):
60 r2 = super(inotifydirstate, self).status(
62 r2 = super(inotifydirstate, self).status(
61 match, False, clean, unknown)
63 match, False, clean, unknown)
62 for c,a,b in zip('LMARDUIC', result, r2):
64 for c,a,b in zip('LMARDUIC', result, r2):
63 for f in a:
65 for f in a:
64 if f not in b:
66 if f not in b:
65 ui.warn('*** inotify: %s +%s\n' % (c, f))
67 ui.warn('*** inotify: %s +%s\n' % (c, f))
66 for f in b:
68 for f in b:
67 if f not in a:
69 if f not in a:
68 ui.warn('*** inotify: %s -%s\n' % (c, f))
70 ui.warn('*** inotify: %s -%s\n' % (c, f))
69 result = r2
71 result = r2
70
72
71 if result is not None:
73 if result is not None:
72 return result
74 return result
73 except (OSError, socket.error), err:
75 except (OSError, socket.error), err:
74 if err[0] == errno.ECONNREFUSED:
76 if err[0] == errno.ECONNREFUSED:
75 ui.warn(_('(found dead inotify server socket; '
77 ui.warn(_('(found dead inotify server socket; '
76 'removing it)\n'))
78 'removing it)\n'))
77 os.unlink(repo.join('inotify.sock'))
79 os.unlink(repo.join('inotify.sock'))
78 if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and \
80 if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and \
79 ui.configbool('inotify', 'autostart', True):
81 ui.configbool('inotify', 'autostart', True):
80 query = None
82 query = None
81 ui.debug(_('(starting inotify server)\n'))
83 ui.debug(_('(starting inotify server)\n'))
82 try:
84 try:
83 try:
85 try:
84 server.start(ui, repo)
86 server.start(ui, repo)
85 query = client.query
87 query = client.query
86 except server.AlreadyStartedException, inst:
88 except server.AlreadyStartedException, inst:
87 # another process may have started its own
89 # another process may have started its own
88 # inotify server while this one was starting.
90 # inotify server while this one was starting.
89 ui.debug(str(inst))
91 ui.debug(str(inst))
90 query = client.query
92 query = client.query
91 except Exception, inst:
93 except Exception, inst:
92 ui.warn(_('could not start inotify server: '
94 ui.warn(_('could not start inotify server: '
93 '%s\n') % inst)
95 '%s\n') % inst)
94 if query:
96 if query:
95 try:
97 try:
96 return query(ui, repo, files or [], match,
98 return query(ui, repo, files or [], match,
97 ignored, clean, unknown)
99 ignored, clean, unknown)
98 except socket.error, err:
100 except socket.error, err:
99 ui.warn(_('could not talk to new inotify '
101 ui.warn(_('could not talk to new inotify '
100 'server: %s\n') % err[-1])
102 'server: %s\n') % err[-1])
101 elif err[0] == errno.ENOENT:
103 elif err[0] == errno.ENOENT:
102 ui.warn(_('(inotify server not running)\n'))
104 ui.warn(_('(inotify server not running)\n'))
103 else:
105 else:
104 ui.warn(_('failed to contact inotify server: %s\n')
106 ui.warn(_('failed to contact inotify server: %s\n')
105 % err[-1])
107 % err[-1])
106 ui.print_exc()
108 ui.print_exc()
107 # replace by old status function
109 # replace by old status function
108 self.status = super(inotifydirstate, self).status
110 self.status = super(inotifydirstate, self).status
109
111
110 return super(inotifydirstate, self).status(
112 return super(inotifydirstate, self).status(
111 match, ignored, clean, unknown)
113 match, ignored, clean, unknown)
112
114
113 repo.dirstate.__class__ = inotifydirstate
115 repo.dirstate.__class__ = inotifydirstate
114
116
115 cmdtable = {
117 cmdtable = {
116 '^inserve':
118 '^inserve':
117 (serve,
119 (serve,
118 [('d', 'daemon', None, _('run server in background')),
120 [('d', 'daemon', None, _('run server in background')),
119 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
121 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
120 ('t', 'idle-timeout', '', _('minutes to sit idle before exiting')),
122 ('t', 'idle-timeout', '', _('minutes to sit idle before exiting')),
121 ('', 'pid-file', '', _('name of file to write process ID to'))],
123 ('', 'pid-file', '', _('name of file to write process ID to'))],
122 _('hg inserve [OPT]...')),
124 _('hg inserve [OPT]...')),
123 }
125 }
@@ -1,30 +1,38
1 #!/bin/sh
1 #!/bin/sh
2
2
3 "$TESTDIR/hghave" inotify || exit 80
3 "$TESTDIR/hghave" inotify || exit 80
4
4
5 hg init
5 hg init
6
6
7 touch a b c d e
7 touch a b c d e
8 mkdir dir
8 mkdir dir
9 mkdir dir/bar
9 mkdir dir/bar
10 touch dir/x dir/y dir/bar/foo
10 touch dir/x dir/y dir/bar/foo
11
11
12 hg ci -Am m
12 hg ci -Am m
13
13
14 echo "[extensions]" >> $HGRCPATH
14 echo "[extensions]" >> $HGRCPATH
15 echo "inotify=" >> $HGRCPATH
15 echo "inotify=" >> $HGRCPATH
16
16
17 echo % inserve
17 echo % inserve
18 hg inserve -d --pid-file=hg.pid
18 hg inserve -d --pid-file=hg.pid
19 cat hg.pid >> "$DAEMON_PIDS"
19 cat hg.pid >> "$DAEMON_PIDS"
20
20
21 # let the daemon finish its stuff
21 # let the daemon finish its stuff
22 sleep 1
22 sleep 1
23 # issue907
23 # issue907
24 hg status
24 hg status
25 echo % clean
25 echo % clean
26 hg status -c
26 hg status -c
27 echo % all
27 echo % all
28 hg status -A
28 hg status -A
29
29
30 echo '% path patterns'
31 echo x > dir/x
32 hg status .
33 hg status dir
34 cd dir
35 hg status .
36 cd ..
37
30 kill `cat hg.pid`
38 kill `cat hg.pid`
@@ -1,29 +1,34
1 adding a
1 adding a
2 adding b
2 adding b
3 adding c
3 adding c
4 adding d
4 adding d
5 adding dir/bar/foo
5 adding dir/bar/foo
6 adding dir/x
6 adding dir/x
7 adding dir/y
7 adding dir/y
8 adding e
8 adding e
9 % inserve
9 % inserve
10 ? hg.pid
10 ? hg.pid
11 % clean
11 % clean
12 C a
12 C a
13 C b
13 C b
14 C c
14 C c
15 C d
15 C d
16 C dir/bar/foo
16 C dir/bar/foo
17 C dir/x
17 C dir/x
18 C dir/y
18 C dir/y
19 C e
19 C e
20 % all
20 % all
21 ? hg.pid
21 ? hg.pid
22 C a
22 C a
23 C b
23 C b
24 C c
24 C c
25 C d
25 C d
26 C dir/bar/foo
26 C dir/bar/foo
27 C dir/x
27 C dir/x
28 C dir/y
28 C dir/y
29 C e
29 C e
30 % path patterns
31 M dir/x
32 ? hg.pid
33 M dir/x
34 M x
General Comments 0
You need to be logged in to leave comments. Login now