Problem with merge after a dir rename

Long Vu long.vu at intelerad.com
Thu Jan 14 12:59:49 CST 2016


On Thu, Jan 14, 2016 at 10:59 AM, Long Vu <long.vu at intelerad.com> wrote:
> On Wed, Jan 13, 2016 at 10:34 AM, Matt Mackall <mpm at selenic.com> wrote:
>> 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.)
>>
>
> Just being defensive in case someone says "this looks like an edge
> case, why would you ever do renames like that".
>
>>> 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.
>
> Weird, I can consistently reproduce with our real repo and this toy repo.
>
> That said we are on Centos 6 with python 2.6.6 so maybe I should retry
> with Cento 7 and Python 2.7.5 (the one that came with Centos 7).
>

Tested on Centos 7 (python 2.7.5), not able to reproduce this diff
problem anymore.

The "wrong move destination guess on merge" is still there.  And now
we see it chooses test/ instead of source/ as destination.

--- /home/lvu/src/mercurial/tests/test-mercurial-merge-after-dir-rename.t
+++ /home/lvu/src/mercurial/tests/test-mercurial-merge-after-dir-rename.t.err
@@ -30,17 +30,31 @@
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hh diff --traceback --debug
-  abort: java-project/com/package/Source2.java@[a-f0-9]{12}: not
found in manifest! (re)
-  [255]
+  diff -r 10ef7cf6855256996bb917152e85ba04f0883e6a
java-project/test/com/package/Source2.java
+  --- /dev/null        Thu Jan 01 00:00:00 1970 +0000
+  +++ b/java-project/test/com/package/Source2.java     Thu Jan 14
18:36:59 2016 +0000
+  @@ -0,0 +1,1 @@
+  +Source2
+  diff -r 10ef7cf6855256996bb917152e85ba04f0883e6a
java-project/test/com/package/Test2.java
+  --- /dev/null        Thu Jan 01 00:00:00 1970 +0000
+  +++ b/java-project/test/com/package/Test2.java       Thu Jan 14
18:36:59 2016 +0000
+  @@ -0,0 +1,1 @@
+  +Test2
 Test2.java should have been under java-project/test/com/package/, not "source".
 In fact, the destination (source/test) seems to be random as one of my re-run,
 I saw it put under test.
   $ hh st
-  A java-project/source/com/package/Source2.java
-  A java-project/source/com/package/Test2.java
+  A java-project/test/com/package/Source2.java
+  A java-project/test/com/package/Test2.java
   $ hh st --copies
+  A java-project/test/com/package/Source2.java
+    java-project/com/package/Source2.java
+  A java-project/test/com/package/Test2.java
+    java-project/com/package/Test2.java
   $ hh ci -m "commit the merge"
   $ hh st --ch .
+  A java-project/test/com/package/Source2.java
+  A java-project/test/com/package/Test2.java

 I think mercurial should prompt the user instead of silently randomly deciding
 the destination.

ERROR: test-mercurial-merge-after-dir-rename.t output changed

>>
>>> 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 + "/"
>>
>
> Will try the proposed patch, thanks.
>

Patch also works on Centos 7.  Thanks for the very quick patch.

--- /home/lvu/src/mercurial/tests/test-mercurial-merge-after-dir-rename.t
+++ /home/lvu/src/mercurial/tests/test-mercurial-merge-after-dir-rename.t.err
@@ -30,17 +30,29 @@
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hh diff --traceback --debug
-  abort: java-project/com/package/Source2.java@[a-f0-9]{12}: not
found in manifest! (re)
-  [255]
+  diff -r 10ef7cf6855256996bb917152e85ba04f0883e6a
java-project/com/package/Source2.java
+  --- /dev/null        Thu Jan 01 00:00:00 1970 +0000
+  +++ b/java-project/com/package/Source2.java  Thu Jan 14 18:56:37 2016 +0000
+  @@ -0,0 +1,1 @@
+  +Source2
+  diff -r 10ef7cf6855256996bb917152e85ba04f0883e6a
java-project/com/package/Test2.java
+  --- /dev/null        Thu Jan 01 00:00:00 1970 +0000
+  +++ b/java-project/com/package/Test2.java    Thu Jan 14 18:56:37 2016 +0000
+  @@ -0,0 +1,1 @@
+  +Test2
 Test2.java should have been under java-project/test/com/package/, not "source".
 In fact, the destination (source/test) seems to be random as one of my re-run,
 I saw it put under test.
   $ hh st
-  A java-project/source/com/package/Source2.java
-  A java-project/source/com/package/Test2.java
+  M java-project/com/package/Source2.java
+  M java-project/com/package/Test2.java
   $ hh st --copies
+  M java-project/com/package/Source2.java
+  M java-project/com/package/Test2.java
   $ hh ci -m "commit the merge"
   $ hh st --ch .
+  A java-project/com/package/Source2.java
+  A java-project/com/package/Test2.java

 I think mercurial should prompt the user instead of silently randomly deciding
 the destination.

ERROR: test-mercurial-merge-after-dir-rename.t output changed



-- 
Long Vu | Build Controller | Intelerad | +1-514-931-6222 ext. 7743

-- 

This email or any attachments may contain confidential or legally 
privileged information intended for the sole use of the addressees. Any 
use, redistribution, disclosure, or reproduction of this information, 
except as intended, is prohibited. If you received this email in error, 
please notify the sender and remove all copies of the message, including 
any attachments.



More information about the Mercurial mailing list