diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -439,6 +439,29 @@ return self._changeset.date def files(self): return self._changeset.files + @propertycache + def _copies(self): + p1copies = {} + p2copies = {} + p1 = self.p1() + p2 = self.p2() + narrowmatch = self._repo.narrowmatch() + for dst in self.files(): + if not narrowmatch(dst) or dst not in self: + continue + copied = self[dst].renamed() + if not copied: + continue + src, srcnode = copied + if src in p1 and p1[src].filenode() == srcnode: + p1copies[dst] = src + elif src in p2 and p2[src].filenode() == srcnode: + p2copies[dst] = src + return p1copies, p2copies + def p1copies(self): + return self._copies[0] + def p2copies(self): + return self._copies[1] def description(self): return self._changeset.description def branch(self): @@ -1158,7 +1181,26 @@ def files(self): return sorted(self._status.modified + self._status.added + self._status.removed) - + @propertycache + def _copies(self): + p1copies = {} + p2copies = {} + parents = self._repo.dirstate.parents() + p1manifest = self._repo[parents[0]].manifest() + p2manifest = self._repo[parents[1]].manifest() + narrowmatch = self._repo.narrowmatch() + for dst, src in self._repo.dirstate.copies().items(): + if not narrowmatch(dst): + continue + if src in p1manifest: + p1copies[dst] = src + elif src in p2manifest: + p2copies[dst] = src + return p1copies, p2copies + def p1copies(self): + return self._copies[0] + def p2copies(self): + return self._copies[1] def modified(self): return self._status.modified def added(self): @@ -1810,6 +1852,30 @@ return [f for f in self._cache.keys() if not self._cache[f]['exists'] and self._existsinparent(f)] + def p1copies(self): + copies = self._repo._wrappedctx.p1copies().copy() + narrowmatch = self._repo.narrowmatch() + for f in self._cache.keys(): + if not narrowmatch(f): + continue + copies.pop(f, None) # delete if it exists + source = self._cache[f]['copied'] + if source: + copies[f] = source + return copies + + def p2copies(self): + copies = self._repo._wrappedctx.p2copies().copy() + narrowmatch = self._repo.narrowmatch() + for f in self._cache.keys(): + if not narrowmatch(f): + continue + copies.pop(f, None) # delete if it exists + source = self._cache[f]['copied'] + if source: + copies[f] = source + return copies + def isinmemory(self): return True diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -1741,6 +1741,28 @@ cmdutil.showmarker(fm, m, index=ind) fm.end() +@command('debugp1copies', + [('r', 'rev', '', _('revision to debug'), _('REV'))], + _('[-r REV]')) +def debugp1copies(ui, repo, **opts): + """dump copy information compared to p1""" + + opts = pycompat.byteskwargs(opts) + ctx = scmutil.revsingle(repo, opts.get('rev'), default=None) + for dst, src in ctx.p1copies().items(): + ui.write('%s -> %s\n' % (src, dst)) + +@command('debugp2copies', + [('r', 'rev', '', _('revision to debug'), _('REV'))], + _('[-r REV]')) +def debugp1copies(ui, repo, **opts): + """dump copy information compared to p2""" + + opts = pycompat.byteskwargs(opts) + ctx = scmutil.revsingle(repo, opts.get('rev'), default=None) + for dst, src in ctx.p2copies().items(): + ui.write('%s -> %s\n' % (src, dst)) + @command('debugpathcomplete', [('f', 'full', None, _('complete an entire path')), ('n', 'normal', None, _('show only normal files')), diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -103,6 +103,8 @@ debugmergestate debugnamecomplete debugobsolete + debugp1copies + debugp2copies debugpathcomplete debugpathcopies debugpeer @@ -280,6 +282,8 @@ debugmergestate: debugnamecomplete: debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template + debugp1copies: rev + debugp2copies: rev debugpathcomplete: full, normal, added, removed debugpathcopies: include, exclude debugpeer: diff --git a/tests/test-copies.t b/tests/test-copies.t --- a/tests/test-copies.t +++ b/tests/test-copies.t @@ -17,12 +17,17 @@ $ echo x > x $ hg ci -Aqm 'add x' $ hg mv x y + $ hg debugp1copies + x -> y + $ hg debugp2copies $ hg ci -m 'rename x to y' $ hg l @ 1 rename x to y | x y o 0 add x x + $ hg debugp1copies -r 1 + x -> y $ hg debugpathcopies 0 1 x -> y $ hg debugpathcopies 1 0 @@ -41,12 +46,17 @@ $ echo y > y $ hg ci -Aqm 'add x and y' $ hg cp -f x y + $ hg debugp1copies + x -> y + $ hg debugp2copies $ hg ci -m 'copy x onto y' $ hg l @ 1 copy x onto y | y o 0 add x and y x y + $ hg debugp1copies -r 1 + x -> y Incorrectly doesn't show the rename $ hg debugpathcopies 0 1 @@ -63,6 +73,8 @@ | x2 o 0 add x and x2 with same content x x2 + $ hg debugp1copies -r 1 + x -> x2 Incorrectly doesn't show the rename $ hg debugpathcopies 0 1 @@ -85,6 +97,8 @@ | y o 0 add x x + $ hg debugp1copies -r 3 + x -> y $ hg debugpathcopies 0 3 x -> y @@ -93,6 +107,9 @@ $ echo x > x $ hg ci -Aqm 'add x' $ hg mv x y + $ hg debugp1copies + x -> y + $ hg debugp2copies $ hg ci -m 'rename x to y' $ hg mv y z $ hg ci -m 'rename y to z' @@ -129,6 +146,7 @@ | x y o 0 add x x + $ hg debugp1copies -r 3 $ hg debugpathcopies 0 3 Copy x to z, then remove z, then copy x2 (same content as x) to z. With copy metadata in the @@ -153,6 +171,8 @@ | z o 0 add x and x2 with same content x x2 + $ hg debugp1copies -r 3 + x2 -> z $ hg debugpathcopies 0 3 x2 -> z @@ -225,6 +245,8 @@ $ echo z > z $ hg ci -Aqm 'add z' $ hg merge -q 1 + $ hg debugp1copies + $ hg debugp2copies $ hg ci -m 'merge rename from p2' $ hg l @ 3 merge rename from p2 @@ -237,6 +259,8 @@ x Perhaps we should indicate the rename here, but `hg status` is documented to be weird during merges, so... + $ hg debugp1copies -r 3 + $ hg debugp2copies -r 3 $ hg debugpathcopies 0 3 x -> y $ hg debugpathcopies 1 2 @@ -254,10 +278,16 @@ $ hg ci -Aqm 'add y' $ hg merge -q 0 $ hg cp y z + $ hg debugp1copies + y -> z + $ hg debugp2copies $ hg ci -m 'copy file from p1 in merge' $ hg co -q 1 $ hg merge -q 0 $ hg cp x z + $ hg debugp1copies + $ hg debugp2copies + x -> z $ hg ci -qm 'copy file from p2 in merge' $ hg l @ 3 copy file from p2 in merge @@ -268,9 +298,15 @@ | y o 0 add x x + $ hg debugp1copies -r 2 + y -> z + $ hg debugp2copies -r 2 $ hg debugpathcopies 1 2 y -> z $ hg debugpathcopies 0 2 + $ hg debugp1copies -r 3 + $ hg debugp2copies -r 3 + x -> z $ hg debugpathcopies 1 3 $ hg debugpathcopies 0 3 x -> z @@ -284,6 +320,9 @@ $ hg ci -Aqm 'add x on branch 2' $ hg merge -q 0 $ hg cp x z + $ hg debugp1copies + x -> z + $ hg debugp2copies $ hg ci -qm 'merge' $ hg l @ 2 merge @@ -292,6 +331,9 @@ | x o 0 add x on branch 1 x + $ hg debugp1copies -r 2 + x -> z + $ hg debugp2copies -r 2 It's a little weird that it shows up on both sides $ hg debugpathcopies 1 2 x -> z @@ -312,6 +354,9 @@ $ hg resolve -m x (no more unresolved files) $ hg cp x z + $ hg debugp1copies + x -> z + $ hg debugp2copies $ hg ci -qm 'merge' $ hg l @ 2 merge @@ -320,6 +365,9 @@ | x o 0 add x on branch 1 x + $ hg debugp1copies -r 2 + $ hg debugp2copies -r 2 + x -> z $ hg debugpathcopies 1 2 $ hg debugpathcopies 0 2 x -> z @@ -345,6 +393,8 @@ |/ y o 0 add x x + $ hg debugp1copies -r 3 + $ hg debugp2copies -r 3 $ hg debugpathcopies 2 3 x -> y $ hg debugpathcopies 1 3 @@ -375,6 +425,9 @@ |/ y o 0 add x x + $ hg debugp1copies -r 3 + y -> z + $ hg debugp2copies -r 3 $ hg debugpathcopies 2 3 y -> z $ hg debugpathcopies 1 3 diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -1011,6 +1011,10 @@ debugoptADV (no help text available) debugoptDEP (no help text available) debugoptEXP (no help text available) + debugp1copies + dump copy information compared to p1 + debugp2copies + dump copy information compared to p2 debugpathcomplete complete part or all of a tracked path debugpathcopies