changeset 7566:5f7e3f17aece

mq: drop copy records when refreshing regular patches (issue1441) Copy information was saved in a common loop, then refined in a git-only block. The problem was the latter did filter out renames occuring in the current patch and irrelevant to commit. In the non-git case, copy records still existed in the dirstate, referencing removed files, making the commit to fail. Git and non-git copy handling paths are now separated for simplicity. Reported by Gary Bernhardt
author Patrick Mezard <pmezard@gmail.com>
date Sun, 04 Jan 2009 21:32:40 +0100
parents 5f162f61e479
children 0946294d1f32 81deb1ba4402
files hgext/mq.py mercurial/dirstate.py tests/test-mq-qrefresh tests/test-mq-qrefresh.out
diffstat 4 files changed, 63 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/mq.py	Sun Jan 04 19:10:42 2009 +0100
+++ b/hgext/mq.py	Sun Jan 04 21:32:40 2009 +0100
@@ -1190,17 +1190,16 @@
                     patchf.write(chunk)
 
                 try:
-                    copies = {}
-                    for dst in a:
-                        src = repo.dirstate.copied(dst)
-                        # during qfold, the source file for copies may
-                        # be removed. Treat this as a simple add.
-                        if src is not None and src in repo.dirstate:
-                            copies.setdefault(src, []).append(dst)
-                        repo.dirstate.add(dst)
-                    # remember the copies between patchparent and tip
-                    # this may be slow, so don't do it if we're not tracking copies
                     if self.diffopts().git:
+                        copies = {}
+                        for dst in a:
+                            src = repo.dirstate.copied(dst)
+                            # during qfold, the source file for copies may
+                            # be removed. Treat this as a simple add.
+                            if src is not None and src in repo.dirstate:
+                                copies.setdefault(src, []).append(dst)
+                            repo.dirstate.add(dst)
+                        # remember the copies between patchparent and tip
                         for dst in aaa:
                             f = repo.file(dst)
                             src = f.renamed(man[dst])
@@ -1211,9 +1210,15 @@
                             # we can't copy a file created by the patch itself
                             if dst in copies:
                                 del copies[dst]
-                    for src, dsts in copies.iteritems():
-                        for dst in dsts:
-                            repo.dirstate.copy(src, dst)
+                        for src, dsts in copies.iteritems():
+                            for dst in dsts:
+                                repo.dirstate.copy(src, dst)
+                    else:
+                        for dst in a:
+                            repo.dirstate.add(dst)
+                        # Drop useless copy information
+                        for f in list(repo.dirstate.copies()):
+                            repo.dirstate.copy(None, f)
                     for f in r:
                         repo.dirstate.remove(f)
                     # if the patch excludes a modified file, mark that
--- a/mercurial/dirstate.py	Sun Jan 04 19:10:42 2009 +0100
+++ b/mercurial/dirstate.py	Sun Jan 04 21:32:40 2009 +0100
@@ -216,10 +216,15 @@
         self._dirty = False
 
     def copy(self, source, dest):
+        """Mark dest as a copy of source. Unmark dest if source is None.
+        """
         if source == dest:
             return
         self._dirty = True
-        self._copymap[dest] = source
+        if source is not None:
+            self._copymap[dest] = source
+        elif dest in self._copymap:
+            del self._copymap[dest]
 
     def copied(self, file):
         return self._copymap.get(file, None)
--- a/tests/test-mq-qrefresh	Sun Jan 04 19:10:42 2009 +0100
+++ b/tests/test-mq-qrefresh	Sun Jan 04 21:32:40 2009 +0100
@@ -123,15 +123,12 @@
 echo
 cd ..
 
-
-
-echo "[diff]" >> $HGRCPATH
-echo "git=True" >> $HGRCPATH
-
 # Test qrefresh --git losing copy metadata
 echo % create test repo
 hg init repo
 cd repo
+echo "[diff]" >> .hg/hgrc
+echo "git=True" >> .hg/hgrc
 echo a > a
 hg ci -Am adda
 hg copy a ab
@@ -146,3 +143,27 @@
 hg qdiff
 cd ..
 
+# Test issue 1441: qrefresh confused after hg rename
+echo % issue1441 without git patches
+hg init repo-1441
+cd repo-1441
+echo a > a
+hg add a
+hg qnew -f p
+hg mv a b
+hg qrefresh
+hg qdiff --nodates
+cd ..
+
+echo % issue1441 with git patches
+hg init repo-1441-git
+cd repo-1441-git
+echo "[diff]" >> .hg/hgrc
+echo "git=True" >> .hg/hgrc
+echo a > a
+hg add a
+hg qnew -f p
+hg mv a b
+hg qrefresh
+hg qdiff --nodates
+cd ..
\ No newline at end of file
--- a/tests/test-mq-qrefresh.out	Sun Jan 04 19:10:42 2009 +0100
+++ b/tests/test-mq-qrefresh.out	Sun Jan 04 21:32:40 2009 +0100
@@ -253,3 +253,16 @@
 @@ -1,1 +1,2 @@
  a
 +c
+% issue1441 without git patches
+diff -r 000000000000 b
+--- /dev/null
++++ b/b
+@@ -0,0 +1,1 @@
++a
+% issue1441 with git patches
+diff --git a/b b/b
+new file mode 100644
+--- /dev/null
++++ b/b
+@@ -0,0 +1,1 @@
++a