Problem with merge after a dir rename

Matt Mackall mpm at selenic.com
Wed Jan 13 09:34:10 CST 2016


On Tue, 2016-01-12 at 15:28 -0500, Long Vu wrote:
> Hi,
> 
> We are cleaning up our source tree filesystem layout and we encounter
> this problem.
> 
> I've captured it in mercurial test format below, against current tip of
> stable.
> 
> Is this a known problem?  Is there a quick work-around to prevent
> mercurial from silently randomly choosing a destination dir?
> 
> create initial repo
>   $ hg init repo
>   $ cd repo
>   $ mkdir -p java-project/com/package
>   $ echo Source > java-project/com/package/Source.java
>   $ echo Test > java-project/com/package/Test.java
>   $ hg ci -Am "create source test file in same folder initially"
>   adding java-project/com/package/Source.java
>   adding java-project/com/package/Test.java
>   $ hg -q branch releasebranch
>   $ hg ci -m "cut release branch"

(Neither Java's weird directory layout conventions nor your branching strategy
appear to be relevant here, so that level of detail is only making your example
harder to read.)

> perform refactoring on trunk
>   $ hg -q up default
>   $ mkdir -p java-project/source/com/package
>   $ hg mv java-project/com/package/Source.java java-
> project/source/com/package/
>   $ hg mv java-project/com java-project/test/com
>   moving java-project/com/package/Test.java to
> java-project/test/com/package/Test.java
>   $ hg ci -Am "refactoring on trunk, proper source/ test/ layout"
> 
> create new file in release branch, merge forward and get wrong behavior
>   $ hg -q up releasebranch
>   $ echo Source2 > java-project/com/package/Source2.java
>   $ echo Test2 > java-project/com/package/Test2.java
>   $ hg ci -Am "create new source test on old branch to test merge
> forward to trunk"
>   adding java-project/com/package/Source2.java
>   adding java-project/com/package/Test2.java
>   $ hg -q up default
>   $ hg merge releasebranch
>   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
>   (branch merge, don't forget to commit)

>   $ hg diff
>   abort: java-project/com/package/Source2.java@[a-f0-9]{12}: not found
> in manifest! (re)
>   [255]

Don't know what this is about but I can't seem to repro it.

> Test2.java should have been under java-project/test/com/package/, not
> "source".

So the theory is that we should only infer a directory move when ALL the files
in a given directory are moved. But apparently there's a bug here. The non-
determinism is caused by randomization of Python's hashing constant. Give this
patch a try if you can:

diff -r 81bca91a0507 mercurial/copies.py
--- a/mercurial/copies.py	Tue Jan 12 15:08:03 2016 -0600
+++ b/mercurial/copies.py	Wed Jan 13 09:32:20 2016 -0600
@@ -401,13 +401,13 @@
             continue
         elif dsrc in d1 and ddst in d1:
             # directory wasn't entirely moved locally
-            invalid.add(dsrc)
+            invalid.add(dsrc + "/")
         elif dsrc in d2 and ddst in d2:
             # directory wasn't entirely moved remotely
-            invalid.add(dsrc)
-        elif dsrc in dirmove and dirmove[dsrc] != ddst:
+            invalid.add(dsrc + "/")
+        elif dsrc + "/" in dirmove and dirmove[dsrc + "/"] != ddst + "/":
             # files from the same directory moved to two different places
-            invalid.add(dsrc)
+            invalid.add(dsrc + "/")
         else:
             # looks good so far
             dirmove[dsrc + "/"] = ddst + "/"

-- 
Mathematics is the supreme nostalgia of our time.



More information about the Mercurial mailing list