--- a/mercurial/merge.py Wed Aug 01 14:32:05 2007 -0700
+++ b/mercurial/merge.py Thu Aug 02 13:03:25 2007 +0200
@@ -9,10 +9,11 @@
from i18n import _
import errno, util, os, tempfile, context
-def filemerge(repo, fw, fo, wctx, mctx):
+def filemerge(repo, fw, fd, fo, wctx, mctx):
"""perform a 3-way merge in the working directory
- fw = filename in the working directory
+ fw = original filename in the working directory
+ fd = destination filename in the working directory
fo = filename in other parent
wctx, mctx = working and merge changecontexts
"""
@@ -27,15 +28,16 @@
return name
fcm = wctx.filectx(fw)
+ fcmdata = wctx.filectx(fd).data()
fco = mctx.filectx(fo)
- if not fco.cmp(fcm.data()): # files identical?
+ if not fco.cmp(fcmdata): # files identical?
return None
fca = fcm.ancestor(fco)
if not fca:
fca = repo.filectx(fw, fileid=nullrev)
- a = repo.wjoin(fw)
+ a = repo.wjoin(fd)
b = temp("base", fca)
c = temp("other", fco)
@@ -49,11 +51,11 @@
cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
or "hgmerge")
r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
- environ={'HG_FILE': fw,
+ environ={'HG_FILE': fd,
'HG_MY_NODE': str(wctx.parents()[0]),
'HG_OTHER_NODE': str(mctx)})
if r:
- repo.ui.warn(_("merging %s failed!\n") % fw)
+ repo.ui.warn(_("merging %s failed!\n") % fd)
os.unlink(b)
os.unlink(c)
@@ -380,6 +382,15 @@
updated, merged, removed, unresolved = 0, 0, 0, 0
action.sort()
+ # prescan for copy/renames
+ for a in action:
+ f, m = a[:2]
+ if m == 'm': # merge
+ f2, fd, flags, move = a[2:]
+ if f != fd:
+ repo.ui.debug(_("copying %s to %s\n") % (f, fd))
+ repo.wwrite(fd, repo.wread(f), flags)
+
for a in action:
f, m = a[:2]
if f and f[0] == "/":
@@ -396,7 +407,7 @@
removed += 1
elif m == "m": # merge
f2, fd, flags, move = a[2:]
- r = filemerge(repo, f, f2, wctx, mctx)
+ r = filemerge(repo, f, fd, f2, wctx, mctx)
if r > 0:
unresolved += 1
else:
@@ -404,12 +415,9 @@
updated += 1
else:
merged += 1
- if f != fd:
- repo.ui.debug(_("copying %s to %s\n") % (f, fd))
- repo.wwrite(fd, repo.wread(f), flags)
- if move:
- repo.ui.debug(_("removing %s\n") % f)
- os.unlink(repo.wjoin(f))
+ if f != fd and move:
+ repo.ui.debug(_("removing %s\n") % f)
+ os.unlink(repo.wjoin(f))
util.set_exec(repo.wjoin(fd), "x" in flags)
elif m == "g": # get
flags = a[2]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-double-merge Thu Aug 02 13:03:25 2007 +0200
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+hg init repo
+cd repo
+
+echo line 1 > foo
+hg ci -qAm 'add foo' -d "1000000 0"
+
+# copy foo to bar and change both files
+hg cp foo bar
+echo line 2-1 >> foo
+echo line 2-2 >> bar
+hg ci -m 'cp foo bar; change both' -d "1000000 0"
+
+# in another branch, change foo in a way that doesn't conflict with
+# the other changes
+hg up -qC 0
+echo line 0 >| foo
+hg cat foo >> foo
+hg ci -m 'change foo' -d "1000000 0"
+
+# we get conflicts that shouldn't be there
+hg merge --debug
+
+echo "-- foo --"
+cat foo
+
+echo "-- bar --"
+cat bar
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-double-merge.out Thu Aug 02 13:03:25 2007 +0200
@@ -0,0 +1,20 @@
+resolving manifests
+ overwrite None partial False
+ ancestor 310fd17130da local 2092631ce82b+ remote 7731dad1c2b9
+ foo: versions differ -> m
+ foo: remote copied to bar -> m
+copying foo to bar
+merging foo and bar
+my foo@2092631ce82b+ other bar@7731dad1c2b9 ancestor foo@310fd17130da
+merging foo
+my foo@2092631ce82b+ other foo@7731dad1c2b9 ancestor foo@310fd17130da
+0 files updated, 2 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+-- foo --
+line 0
+line 1
+line 2-1
+-- bar --
+line 0
+line 1
+line 2-2
--- a/tests/test-merge9.out Wed Aug 01 14:32:05 2007 -0700
+++ b/tests/test-merge9.out Thu Aug 02 13:03:25 2007 +0200
@@ -5,7 +5,7 @@
merging bar
merging bar failed!
merging foo and baz
-merging foo failed!
+merging baz failed!
1 files updated, 0 files merged, 0 files removed, 2 files unresolved
There are unresolved merges, you can redo the full merge using:
hg update -C 2
--- a/tests/test-rename-merge1.out Wed Aug 01 14:32:05 2007 -0700
+++ b/tests/test-rename-merge1.out Thu Aug 02 13:03:25 2007 +0200
@@ -7,9 +7,9 @@
a2: divergent renames -> dr
a: remote moved to b -> m
b2: remote created -> g
+copying a to b
merging a and b
my a@f26ec4fc3fa3+ other b@8e765a822af2 ancestor a@af1939970a1c
-copying a to b
removing a
warning: detected divergent renames of a2 to:
c2
--- a/tests/test-rename-merge2.out Wed Aug 01 14:32:05 2007 -0700
+++ b/tests/test-rename-merge2.out Thu Aug 02 13:03:25 2007 +0200
@@ -6,17 +6,17 @@
ancestor 924404dff337 local e300d1c794ec+ remote 735846fee2d7
rev: versions differ -> m
a: remote copied to b -> m
+copying a to b
merging a and b
my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
-copying a to b
merging rev
my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
0 files updated, 2 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
--------------
-M a
M b
a
+C a
--------------
--------------
@@ -49,9 +49,9 @@
ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
rev: versions differ -> m
a: remote moved to b -> m
+copying a to b
merging a and b
my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
-copying a to b
removing a
merging rev
my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
@@ -357,9 +357,9 @@
ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
rev: versions differ -> m
a: remote moved to b -> m
+copying a to b
merging a and b
my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
-copying a to b
removing a
merging rev
my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337