duplicatecopies: do not mark items not in the dirstate as copies
authorSiddharth Agarwal <sid0@fb.com>
Thu, 28 Mar 2013 18:27:19 -0700
changeset 18853 78d760aa3607
parent 18852 300844cb1a56
child 18858 f02045645d12
child 18859 9a1c8f29bc0e
duplicatecopies: do not mark items not in the dirstate as copies Consider the following repo: 0 -- 1 (renames a to b) \ - 2 If we're rebasing 2 onto 1, then duplicatecopies is called with arguments (2, 1). copies.pathcopies goes backwards from 1 to 0 and returns the pair dst = a, src = b. Of course, since we're working on top of 2, at this point a doesn't exist in the dirstate. Extra entries in the copymap are currently harmless because the copymap is only queried for items in the dirstate map. However, if the dirstate.copy method becomes one of the sources used to determine which files have changed, this will prove problematic. Note that we can't avoid going backwards in general -- consider this repo: 0 -- 1 (renames a to b) \ - 2 (renames a to c) Rebasing 2 onto 1 should produce a rename from b to c.
mercurial/cmdutil.py
--- a/mercurial/cmdutil.py	Thu Mar 28 00:14:27 2013 -0700
+++ b/mercurial/cmdutil.py	Thu Mar 28 18:27:19 2013 -0700
@@ -1593,7 +1593,10 @@
 def duplicatecopies(repo, rev, fromrev):
     '''reproduce copies from fromrev to rev in the dirstate'''
     for dst, src in copies.pathcopies(repo[fromrev], repo[rev]).iteritems():
-        repo.dirstate.copy(src, dst)
+        # copies.pathcopies returns backward renames, so dst might not
+        # actually be in the dirstate
+        if repo.dirstate[dst] in "nma":
+            repo.dirstate.copy(src, dst)
 
 def commit(ui, repo, commitfunc, pats, opts):
     '''commit the specified files or all outstanding changes'''