Mercurial > public > mercurial-scm > hg-stable
diff mercurial/merge.py @ 3153:c82ea81d6850
Add core copy detection algorithm
This adds findcopies, which detects merge-relevant copies between
files in a pair of manifests back to the merge ancestor.
While the merge code invokes the copy detection routine, it does not
yet use the result.
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 25 Sep 2006 16:45:31 -0500 |
parents | 2ef0b3aae186 |
children | 56c59ba7aa76 |
line wrap: on
line diff
--- a/mercurial/merge.py Mon Sep 25 16:43:21 2006 -0500 +++ b/mercurial/merge.py Mon Sep 25 16:45:31 2006 -0500 @@ -94,6 +94,77 @@ return action +def nonoverlap(d1, d2): + """ + Return list of elements in d1 not in d2 + """ + + l = [] + for d in d1: + if d not in d2: + l.append(d) + + l.sort() + return l + +def findold(fctx, limit): + """ + find files that path was copied from, back to linkrev limit + """ + + old = {} + orig = fctx.path() + visit = [fctx] + while visit: + fc = visit.pop() + if fc.rev() < limit: + continue + if fc.path() != orig and fc.path() not in old: + old[fc.path()] = 1 + visit += fc.parents() + + old = old.keys() + old.sort() + return old + +def findcopies(repo, m1, m2, limit): + """ + Find moves and copies between m1 and m2 back to limit linkrev + """ + + copy = {} + match = {} + u1 = nonoverlap(m1, m2) + u2 = nonoverlap(m2, m1) + ctx = util.cachefunc(lambda f,n: repo.filectx(f, fileid=n[:20])) + + def checkpair(c, f2, man): + ''' check if an apparent pair actually matches ''' + c2 = ctx(f2, man[f2]) + ca = c.ancestor(c2) + if ca: + copy[c.path()] = f2 + copy[f2] = c.path() + + for f in u1: + c = ctx(f, m1[f]) + for of in findold(c, limit): + if of in m2: + checkpair(c, of, m2) + else: + match.setdefault(of, []).append(f) + + for f in u2: + c = ctx(f, m2[f]) + for of in findold(c, limit): + if of in m1: + checkpair(c, of, m1) + elif of in match: + for mf in match[of]: + checkpair(c, mf, m1) + + return copy + def manifestmerge(ui, m1, m2, ma, overwrite, backwards, partial): """ Merge manifest m1 with m2 using ancestor ma and generate merge action list @@ -289,6 +360,11 @@ checkunknown(repo, m2, status) if not branchmerge: action += forgetremoved(m2, status) + + copy = {} + if not (backwards or overwrite): + copy = findcopies(repo, m1, m2, repo.changelog.rev(pa)) + action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial) del m1, m2, ma