# HG changeset patch # User Thomas Arendsen Hein # Date 1160035660 -7200 # Node ID 53d6bcccdbefa7e656cf2255f88ce14b74570c66 # Parent 03acd01520acec72948fd6b343447bbe51ac112a# Parent c93ce7f10f8510ff78283f2c76dc76694c20b92d merge with upstream diff -r 03acd01520ac -r 53d6bcccdbef mercurial/commands.py --- a/mercurial/commands.py Thu Oct 05 00:14:21 2006 +0200 +++ b/mercurial/commands.py Thu Oct 05 10:07:40 2006 +0200 @@ -2532,8 +2532,7 @@ for f in changes: ui.write(format % f) - if ((all or opts.get('copies')) and not opts.get('no_status') - and opt == 'added'): + if ((all or opts.get('copies')) and not opts.get('no_status')): copied = repo.dirstate.copied(f) if copied: ui.write(' %s%s' % (copied, end)) diff -r 03acd01520ac -r 53d6bcccdbef mercurial/merge.py --- a/mercurial/merge.py Thu Oct 05 00:14:21 2006 +0200 +++ b/mercurial/merge.py Thu Oct 05 10:07:40 2006 +0200 @@ -54,6 +54,13 @@ 'HG_OTHER_NODE': p2}) if r: repo.ui.warn(_("merging %s failed!\n") % fw) + else: + if fd != fw: + repo.ui.debug(_("copying %s to %s\n") % (fw, fd)) + repo.wwrite(fd, repo.wread(fw)) + if move: + repo.ui.debug(_("removing %s\n") % fw) + os.unlink(a) os.unlink(b) os.unlink(c) @@ -126,6 +133,9 @@ Find moves and copies between m1 and m2 back to limit linkrev """ + if not repo.ui.config("merge", "followcopies"): + return {} + # avoid silly behavior for update from empty dir if not m1: return {} @@ -141,7 +151,7 @@ ''' check if an apparent pair actually matches ''' c2 = ctx(f2, man[f2]) ca = c.ancestor(c2) - if ca: + if ca and ca.path() == c.path() or ca.path() == c2.path(): copy[c.path()] = f2 copy[f2] = c.path() @@ -164,19 +174,17 @@ return copy -def filtermanifest(man, partial): - if partial: - for k in man.keys(): - if not partial(k): del man[k] - -def manifestmerge(ui, m1, m2, ma, overwrite, backwards): +def manifestmerge(ui, m1, m2, ma, copy, overwrite, backwards, partial): """ Merge manifest m1 with m2 using ancestor ma and generate merge action list """ - def fmerge(f): + def fmerge(f, f2=None, fa=None): """merge executable flags""" - a, b, c = ma.execf(f), m1.execf(f), m2.execf(f) + if not f2: + f2 = f + fa = f + a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2) return ((a^b) | (a^c)) ^ a action = [] @@ -187,6 +195,8 @@ # Compare manifests for f, n in m1.iteritems(): + if partial and not partial(f): + continue if f in m2: # are files different? if n != m2[f]: @@ -206,7 +216,18 @@ elif m1.execf(f) != m2.execf(f): if overwrite or fmerge(f) != m1.execf(f): act("update permissions", f, "e", m2.execf(f)) - del m2[f] + elif f in copy: + f2 = copy[f] + if f in ma: # case 3,20 A/B/A + act("remote moved", + f, "c", f2, f2, m1[f], m2[f2], fmerge(f, f2, f), True) + else: + if f2 in m1: # case 2 A,B/B/B + act("local copied", + f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False) + else: # case 4,21 A/B/B + act("local moved", + f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False) elif f in ma: if n != ma[f] and not overwrite: if ui.prompt( @@ -221,7 +242,18 @@ act("remote deleted", f, "r") for f, n in m2.iteritems(): - if f in ma: + if partial and not partial(f): + continue + if f in m1: + continue + if f in copy: + f2 = copy[f] + if f2 in ma or f2 in m1: # already seen + continue + # rename case 1, A/A,B/A + act("remote copied", + f, "c", f2, f, m1[f2], m2[f], fmerge(f2, f, f2), False) + elif f in ma: if overwrite or backwards: act("recreating", f, "g", m2.execf(f), n) elif n != ma[f]: @@ -251,6 +283,12 @@ repo.ui.warn(_("update failed to remove %s: %s!\n") % (f, inst.strerror)) removed +=1 + elif m == "c": # copy + f2, fd, my, other, flag, move = a[2:] + if filemerge(repo, f, f2, fd, my, other, xp1, xp2, move): + unresolved += 1 + util.set_exec(repo.wjoin(fd), flag) + merged += 1 elif m == "m": # merge flag, my, other = a[2:] repo.ui.status(_("merging %s\n") % f) @@ -301,6 +339,25 @@ fl = repo.file(f) f_len = fl.size(fl.rev(other)) repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) + elif m == "c": # copy + f2, fd, my, other, flag, move = a[2:] + if branchmerge: + # We've done a branch merge, mark this file as merged + # so that we properly record the merger later + repo.dirstate.update([fd], 'm') + else: + # We've update-merged a locally modified file, so + # we set the dirstate to emulate a normal checkout + # of that file some time in the past. Thus our + # merge will appear as a normal local file + # modification. + fl = repo.file(f) + f_len = fl.size(fl.rev(other)) + repo.dirstate.update([fd], 'n', st_size=f_len, st_mtime=-1) + if move: + repo.dirstate.update([f], 'r') + if f != fd: + repo.dirstate.copy(f, fd) def update(repo, node, branchmerge=False, force=False, partial=None, wlock=None, show_stats=True, remind=True): @@ -337,8 +394,8 @@ if wc.modified() or wc.added() or wc.removed(): raise util.Abort(_("outstanding uncommitted changes")) - m1 = wc.manifest().copy() - m2 = p2.manifest().copy() + m1 = wc.manifest() + m2 = p2.manifest() ma = pa.manifest() # resolve the manifest to determine which files @@ -351,9 +408,6 @@ action = [] copy = {} - filtermanifest(m1, partial) - filtermanifest(m2, partial) - if not force: checkunknown(repo, m2, wc) if not branchmerge: @@ -361,8 +415,8 @@ if not (backwards or overwrite): copy = findcopies(repo, m1, m2, pa.rev()) - action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards) - del m1, m2, ma + action += manifestmerge(repo.ui, m1, m2, ma, copy, + overwrite, backwards, partial) ### apply phase diff -r 03acd01520ac -r 53d6bcccdbef tests/test-rename-merge1 --- a/tests/test-rename-merge1 Thu Oct 05 00:14:21 2006 +0200 +++ b/tests/test-rename-merge1 Thu Oct 05 10:07:40 2006 +0200 @@ -3,6 +3,8 @@ mkdir t cd t hg init +echo "[merge]" >> .hg/hgrc +echo "followcopies = 1" >> .hg/hgrc echo foo > a echo foo > a2 hg add a a2 @@ -18,6 +20,6 @@ hg ci -m "modify" -d "0 0" echo "merge" hg merge -y --debug -cat a +hg status -AC cat b hg ci -m "merge" -d "0 0" diff -r 03acd01520ac -r 53d6bcccdbef tests/test-rename-merge1.out --- a/tests/test-rename-merge1.out Thu Oct 05 00:14:21 2006 +0200 +++ b/tests/test-rename-merge1.out Thu Oct 05 10:07:40 2006 +0200 @@ -4,11 +4,18 @@ resolving manifests overwrite None branchmerge True partial False ancestor f26ec4fc3fa3 local 8e765a822af2 remote af1939970a1c - b: remote created -> g + a: remote moved -> c b2: remote created -> g -getting b +resolving a +my a@f26ec4fc3fa3 other b@8e765a822af2 ancestor a@af1939970a1c +copying a to b +removing a getting b2 -2 files updated, 0 files merged, 0 files removed, 0 files unresolved +1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) +M b + a +M b2 +R a +C c2 blahblah -foo