revert: apply normallookup on reverted file if size isn't changed (issue4583) stable
authorFUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Fri, 24 Apr 2015 23:52:41 +0900
branchstable
changeset 24843 21b33f0460e0
parent 24842 ca1ad8ef38be
child 24844 6c6aee6d395b
revert: apply normallookup on reverted file if size isn't changed (issue4583) Before this patch, reverting a file to the revision other than the parent doesn't update dirstate. This seems to expect that timestamp and/or size will be changed by reverting. But if (1) dirstate of file "f" is filled with timestamp before reverting and (2) size and timestamp of file "f" isn't changed at reverting, file "f" is recognized as CLEAN unexpectedly. This patch applies "dirstate.normallookup()" on reverted file, if size isn't changed. Making "localrepository.wwrite()" return length of written data is needed to avoid additional (and redundant) "lstat(2)" on the reverted file. "filectx.size()" can't be used to know it, because data may be decoded at being written out. BTW, interactive reverting may cause similar problem, too. But this patch doesn't focus on fixing it, because (1) interactive (maybe slow) reverting changes one (or both) of size/timestamp of reverted files in many usecases, and (2) changes to fix it seems not suitable for stable branch.
mercurial/cmdutil.py
mercurial/localrepo.py
tests/test-merge-tools.t
--- a/mercurial/cmdutil.py	Thu Apr 23 21:23:13 2015 +0200
+++ b/mercurial/cmdutil.py	Fri Apr 24 23:52:41 2015 +0900
@@ -3066,7 +3066,7 @@
     node = ctx.node()
     def checkout(f):
         fc = ctx[f]
-        repo.wwrite(f, fc.data(), fc.flags())
+        return repo.wwrite(f, fc.data(), fc.flags())
 
     audit_path = pathutil.pathauditor(repo.root)
     for f in actions['forget'][0]:
@@ -3114,9 +3114,13 @@
         del fp
     else:
         for f in actions['revert'][0]:
-            checkout(f)
+            wsize = checkout(f)
             if normal:
                 normal(f)
+            elif wsize == repo.dirstate._map[f][2]:
+                # changes may be overlooked without normallookup,
+                # if size isn't changed at reverting
+                repo.dirstate.normallookup(f)
 
     for f in actions['add'][0]:
         checkout(f)
--- a/mercurial/localrepo.py	Thu Apr 23 21:23:13 2015 +0200
+++ b/mercurial/localrepo.py	Fri Apr 24 23:52:41 2015 +0900
@@ -917,6 +917,10 @@
         return self._filter(self._encodefilterpats, filename, data)
 
     def wwrite(self, filename, data, flags):
+        """write ``data`` into ``filename`` in the working directory
+
+        This returns length of written (maybe decoded) data.
+        """
         data = self._filter(self._decodefilterpats, filename, data)
         if 'l' in flags:
             self.wvfs.symlink(data, filename)
@@ -924,6 +928,7 @@
             self.wvfs.write(filename, data)
             if 'x' in flags:
                 self.wvfs.setflags(filename, False, True)
+        return len(data)
 
     def wwritedata(self, filename, data):
         return self._filter(self._decodefilterpats, filename, data)
--- a/tests/test-merge-tools.t	Thu Apr 23 21:23:13 2015 +0200
+++ b/tests/test-merge-tools.t	Fri Apr 24 23:52:41 2015 +0900
@@ -608,7 +608,16 @@
   true.executable=cat
   # hg update -C 1
   $ hg update -q 0
+  $ f -s f
+  f: size=17
+  $ touch -t 200001010000 f
+  $ hg status f
   $ hg revert -q -r 1 .
+  $ f -s f
+  f: size=17
+  $ touch -t 200001010000 f
+  $ hg status f
+  M f
   $ hg update -r 2
   merging f
   revision 1
@@ -634,7 +643,16 @@
   true.executable=cat
   # hg update -C 1
   $ hg update -q 0
+  $ f -s f
+  f: size=17
+  $ touch -t 200001010000 f
+  $ hg status f
   $ hg revert -q -r 1 .
+  $ f -s f
+  f: size=17
+  $ touch -t 200001010000 f
+  $ hg status f
+  M f
   $ hg update -r 2 --tool false
   merging f
   merging f failed!