dirstate: ignore stat data for files that were updated too recently
authorAlexis S. L. Carvalho <alexis@cecm.usp.br>
Wed, 19 Mar 2008 17:55:21 -0300
changeset 6326 af3f26b6bba4
parent 6325 41c77bb8d7f3
child 6327 6d952dc2abc9
dirstate: ignore stat data for files that were updated too recently This should fix the race where hg commit foo <change foo without changing its size> 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).
mercurial/dirstate.py
tests/test-filebranch.out
tests/test-rebuildstate.out
--- a/mercurial/dirstate.py	Thu Mar 20 11:12:35 2008 -0500
+++ b/mercurial/dirstate.py	Wed Mar 19 17:55:21 2008 -0300
@@ -10,7 +10,7 @@
 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 @@
         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 @@
     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 @@
         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
--- a/tests/test-filebranch.out	Thu Mar 20 11:12:35 2008 -0500
+++ b/tests/test-filebranch.out	Wed Mar 19 17:55:21 2008 -0300
@@ -3,10 +3,10 @@
 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
--- a/tests/test-rebuildstate.out	Thu Mar 20 11:12:35 2008 -0500
+++ b/tests/test-rebuildstate.out	Wed Mar 19 17:55:21 2008 -0300
@@ -2,7 +2,7 @@
 adding foo
 % state dump
 a   0         -1 baz
-n 644          0 foo
+n   0         -1 foo
 r   0          0 bar
 % status
 A baz