[PATCH] Fix issue 1719, inotify dirstate when dirty (v2: improved matching + extended test)
Simon Heimberg
simohe at besonet.ch
Sat Aug 15 16:50:19 CDT 2009
# HG changeset patch
# User Simon Heimberg <simohe at besonet.ch>
# Date 1250372350 -7200
# Node ID 68874a314191de4a27fbf817fc857d5770a62932
# Parent bde485306b9dd5c8ea8fd9ee939d8879833689d6
inotify: when dirstate is dirty, force local state (fix issue1719)
The inotify server always returns the dirstate from disc. When the dirstate
is modified but not yet written to disc, this is the wrong state. The client
fixes the inconsistent states.
Add a test with mq for issue1719 and a python test
diff -r bde485306b9d -r 68874a314191 hgext/inotify/__init__.py
--- a/hgext/inotify/__init__.py Sam Aug 15 23:39:10 2009 +0200
+++ b/hgext/inotify/__init__.py Sam Aug 15 23:39:10 2009 +0200
@@ -10,8 +10,9 @@
# todo: socket permissions
+import bisect
from mercurial.i18n import _
-from mercurial import cmdutil, util
+from mercurial import cmdutil, util, match as _match
import server
from weakref import proxy
from client import client, QueryFailed
@@ -92,6 +93,45 @@
if f not in a:
ui.warn('*** inotify: %s -%s\n' % (c, f))
result = r2
+ if self._dirty:
+ # dirstate in memory is modified
+ #
+ # Test for all files if the state on disc is consistent
+ # with the state in memory. If it is not use the one
+ # from the memory.
+
+ exact = match.matchfn == match.exact
+ if files and exact:
+ unseen = set(files)
+ elif clean:
+ # add all files from dirstate for potential fixing
+ unseen = set(self)
+ else:
+ # do not check clean files
+ unseen = set(f for f in self if self[f] != 'n')
+
+ fix = set()
+ matchingstates = 'n nm a r nma ? ? n'.split()
+ for files, matching in zip(result, matchingstates):
+ for f in files[:]:
+ unseen.discard(f)
+ if self[f] not in matching:
+ # inconsistent state
+ fix.add(f)
+ files.remove(f)
+ if not exact and (files or match.anypats()):
+ # only keep matching files
+ unseen = set(f for f in unseen if match(f))
+ fix.update(unseen)
+ if fix: # fix states
+ fmatch = _match.exact(match._root, match._cwd, fix)
+ # query dirstate in memory for inconsistent files
+ fresult = super(inotifydirstate, self).status(
+ fmatch, ignored, clean, unknown)
+ for st, fst in zip(result, fresult):
+ for f in fst:
+ # insert filename sorted in result
+ bisect.insort(st, f)
return result
return super(inotifydirstate, self).status(
match, ignored, clean, unknown)
diff -r bde485306b9d -r 68874a314191 tests/test-inotify-dirty.py
--- /dev/null Don Jan 01 00:00:00 1970 +0000
+++ b/tests/test-inotify-dirty.py Sam Aug 15 23:39:10 2009 +0200
@@ -0,0 +1,83 @@
+#!/bin/env python
+
+'Test inotify status while wlock is held (=dirstate is dirty)'
+
+import os, time, sys
+from mercurial import hg, extensions, ui, match
+
+def pstatus(match, ignored=False, clean=False, unknown=False):
+ res = repo.dirstate.status(match, ignored, clean, unknown)
+ for st, files in zip('LMARDUIC', res):
+ if files:
+ print '%s: %s' % (st, ','.join(files)),
+ print ''
+
+def pnstatus(match):
+ pstatus(match, True)
+ pstatus(match, True, True)
+ pstatus(match, True, True, True)
+ pstatus(match, True, False, True)
+ pstatus(match, False, True)
+
+u = ui.ui()
+if os.environ.get('HG_TEST_NO_INOTIFY'):
+ print '#### test without inotify' # for generating correct out file
+else:
+ extensions.load(u, 'inotify', '')
+ try:
+ import hgext.inotify.linux.watcher
+ return True
+ except ImportError:
+ sys.stderr.write('missing feature: inotify extension support\n')
+ sys.exit(80)
+
+os.mkdir('r')
+open('r/.hgignore', 'w').write('.hgignore\n')
+
+repo = hg.repository(u, 'r', create=True)
+
+open('r/cc', 'w').write('0')
+open('r/rr', 'w').write('1')
+open('r/mm', 'w').write('2')
+open('r/dd', 'w').write('3')
+open('r/ll', 'w').write('4')
+open('r/uu', 'w').write('5')
+open('r/aa', 'w').write('6')
+
+time.sleep(1) # wait for second to change
+
+wlock = repo.wlock()
+repo.add('cc rr mm dd ll'.split())
+repo.commit('1st')
+wlock.release()
+
+wlock = repo.wlock()
+open('r/mm', 'w').write('10')
+open('r/ll', 'w').write('0')
+os.unlink('r/dd')
+repo.add(['aa'])
+repo.remove(['rr'])
+
+print '% exact, all'
+m = match.exact(repo.root, '', 'cc rr mm uu aa dd ll ii'.split())
+pnstatus(m)
+
+print '% exact, none'
+m = match.exact(repo.root, '', ['kk'])
+pstatus(m)
+pstatus(m, False, True)
+pstatus(m, True, True, True)
+
+print '% always'
+m = match.always(repo.root, '')
+pnstatus(m)
+
+print '% match *'
+m = match.match(repo.root, '', ['*'])
+pnstatus(m)
+
+print '% match some'
+m = match.match(repo.root, '', 'aa dd cc'.split())
+pnstatus(m)
+
+wlock.release()
diff -r bde485306b9d -r 68874a314191 tests/test-inotify-dirty.py.out
--- /dev/null Don Jan 01 00:00:00 1970 +0000
+++ b/tests/test-inotify-dirty.py.out Sam Aug 15 23:39:10 2009 +0200
@@ -0,0 +1,28 @@
+% exact, all
+L: ll M: mm A: aa R: rr D: dd
+L: ll M: mm A: aa R: rr D: dd C: cc
+L: ll M: mm A: aa R: rr D: dd U: uu C: cc
+L: ll M: mm A: aa R: rr D: dd U: uu
+L: ll M: mm A: aa R: rr D: dd C: cc
+% exact, none
+
+
+
+% always
+L: ll M: mm A: aa R: rr D: dd I: .hgignore
+L: ll M: mm A: aa R: rr D: dd I: .hgignore C: cc
+L: ll M: mm A: aa R: rr D: dd U: uu I: .hgignore C: cc
+L: ll M: mm A: aa R: rr D: dd U: uu I: .hgignore
+L: ll M: mm A: aa R: rr D: dd C: cc
+% match *
+L: ll M: mm A: aa R: rr D: dd I: .hgignore
+L: ll M: mm A: aa R: rr D: dd I: .hgignore C: cc
+L: ll M: mm A: aa R: rr D: dd U: uu I: .hgignore C: cc
+L: ll M: mm A: aa R: rr D: dd U: uu I: .hgignore
+L: ll M: mm A: aa R: rr D: dd C: cc
+% match some
+A: aa D: dd
+A: aa D: dd C: cc
+A: aa D: dd C: cc
+A: aa D: dd
+A: aa D: dd C: cc
diff -r bde485306b9d -r 68874a314191 tests/test-inotify-mq
--- /dev/null Don Jan 01 00:00:00 1970 +0000
+++ b/tests/test-inotify-mq Sam Aug 15 23:39:10 2009 +0200
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+"$TESTDIR/hghave" inotify || exit 80
+
+# qpush changeset which adds or deletes a file succedes (issue1719)
+
+echo [extensions] >> $HGRCPATH
+echo inotify= >> $HGRCPATH
+echo mq= >> $HGRCPATH
+
+hg init a
+cd a
+
+hg qnew adda
+echo 11 > a
+hg add a
+hg qref
+hg qpo
+hg qpu
+hg st
+
+hg qnew rma
+hg rm a
+hg qref
+hg qpo
+hg qpu
+hg st
+
+hg qpo -a
diff -r bde485306b9d -r 68874a314191 tests/test-inotify-mq.out
--- /dev/null Don Jan 01 00:00:00 1970 +0000
+++ b/tests/test-inotify-mq.out Sam Aug 15 23:39:10 2009 +0200
@@ -0,0 +1,11 @@
+popping adda
+patch queue now empty
+applying adda
+now at: adda
+popping rma
+now at: adda
+applying rma
+now at: rma
+popping rma
+popping adda
+patch queue now empty
More information about the Mercurial-devel
mailing list