changeset 6326:af3f26b6bba4

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).
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Wed, 19 Mar 2008 17:55:21 -0300
parents 41c77bb8d7f3
children 6d952dc2abc9
files mercurial/dirstate.py tests/test-filebranch.out tests/test-rebuildstate.out
diffstat 3 files changed, 19 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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