# HG changeset patch # User Alexis S. L. Carvalho # Date 2008-03-19 20:55:21 # Node ID af3f26b6bba45c0a88500214f91fbdcec7abf3c3 # Parent 41c77bb8d7f309a6b0ea6194b9c1618a4f86eff0 dirstate: ignore stat data for files that were updated too recently This should fix the race where hg commit foo happens in the same second and status is fooled into thinking foo is clean. A configuration item is used to determine the timeout, since different filesystems may have different requirements (I think VFAT needs 3s, while most Unix filesystems are fine with 1s). diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -10,7 +10,7 @@ of the GNU General Public License, incor from node import nullid from i18n import _ import struct, os, bisect, stat, strutil, util, errno, ignore -import cStringIO, osutil +import cStringIO, osutil, sys _unknown = ('?', 0, 0, 0) _format = ">cllll" @@ -66,6 +66,12 @@ class dirstate(object): elif name == '_checkexec': self._checkexec = util.checkexec(self._root) return self._checkexec + elif name == '_limit': + try: + self._limit = int(self._ui.config('ui', 'limit', 1)) + except ValueError: + self._limit = 1 + return self._limit else: raise AttributeError, name @@ -335,6 +341,11 @@ class dirstate(object): def write(self): if not self._dirty: return + st = self._opener("dirstate", "w", atomictemp=True) + if self._limit > 0: + limit = util.fstat(st).st_mtime - self._limit + else: + limit = sys.maxint cs = cStringIO.StringIO() copymap = self._copymap pack = struct.pack @@ -343,10 +354,11 @@ class dirstate(object): for f, e in self._map.iteritems(): if f in copymap: f = "%s\0%s" % (f, copymap[f]) + if e[3] > limit and e[0] == 'n': + e = (e[0], 0, -1, -1, 0) e = pack(_format, e[0], e[1], e[2], e[3], len(f)) write(e) write(f) - st = self._opener("dirstate", "w", atomictemp=True) st.write(cs.getvalue()) st.rename() self._dirty = self._dirtypl = False diff --git a/tests/test-filebranch.out b/tests/test-filebranch.out --- a/tests/test-filebranch.out +++ b/tests/test-filebranch.out @@ -3,10 +3,10 @@ 4 files updated, 0 files merged, 0 files creating branch a creating branch b we shouldn't have anything but n state here -n 644 2 bar -n 644 3 baz -n 644 3 foo -n 644 2 quux +n 0 -1 bar +n 0 -1 baz +n 0 -1 foo +n 0 -1 quux merging pulling from ../a searching for changes diff --git a/tests/test-rebuildstate.out b/tests/test-rebuildstate.out --- a/tests/test-rebuildstate.out +++ b/tests/test-rebuildstate.out @@ -2,7 +2,7 @@ adding bar adding foo % state dump a 0 -1 baz -n 644 0 foo +n 0 -1 foo r 0 0 bar % status A baz