diff --git a/mercurial/changelog.py b/mercurial/changelog.py --- a/mercurial/changelog.py +++ b/mercurial/changelog.py @@ -99,6 +99,14 @@ # used different syntax for the value. return None +def encodefileindices(files, subset): + subset = set(subset) + indices = [] + for i, f in enumerate(files): + if f in subset: + indices.append('%d' % i) + return '\0'.join(indices) + def stripdesc(desc): """strip trailing whitespace and leading and trailing empty lines""" return '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n') @@ -564,7 +572,8 @@ return l[3:] def add(self, manifest, files, desc, transaction, p1, p2, - user, date=None, extra=None, p1copies=None, p2copies=None): + user, date=None, extra=None, p1copies=None, p2copies=None, + filesadded=None, filesremoved=None): # Convert to UTF-8 encoded bytestrings as the very first # thing: calling any method on a localstr object will turn it # into a str object and the cached UTF-8 string is thus lost. @@ -593,17 +602,23 @@ elif branch in (".", "null", "tip"): raise error.StorageError(_('the name \'%s\' is reserved') % branch) - if (p1copies is not None or p2copies is not None) and extra is None: + extrasentries = p1copies, p2copies, filesadded, filesremoved + if extra is None and any(x is not None for x in extrasentries): extra = {} if p1copies is not None: extra['p1copies'] = encodecopies(p1copies) if p2copies is not None: extra['p2copies'] = encodecopies(p2copies) + sortedfiles = sorted(files) + if filesadded is not None: + extra['filesadded'] = encodefileindices(sortedfiles, filesadded) + if filesremoved is not None: + extra['filesremoved'] = encodefileindices(sortedfiles, filesremoved) if extra: extra = encodeextra(extra) parseddate = "%s %s" % (parseddate, extra) - l = [hex(manifest), user, parseddate] + sorted(files) + ["", desc] + l = [hex(manifest), user, parseddate] + sortedfiles + ["", desc] text = "\n".join(l) return self.addrevision(text, transaction, len(self), p1, p2) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2589,10 +2589,13 @@ writecopiesto = self.ui.config('experimental', 'copies.write-to') writefilecopymeta = writecopiesto != 'changeset-only' + writechangesetcopy = (writecopiesto in + ('changeset-only', 'compatibility')) p1copies, p2copies = None, None - if writecopiesto in ('changeset-only', 'compatibility'): + if writechangesetcopy: p1copies = ctx.p1copies() p2copies = ctx.p2copies() + filesadded, filesremoved = None, None with self.lock(), self.transaction("commit") as tr: trp = weakref.proxy(tr) @@ -2601,6 +2604,9 @@ self.ui.debug('reusing known manifest\n') mn = ctx.manifestnode() files = ctx.files() + if writechangesetcopy: + filesadded = ctx.filesadded() + filesremoved = ctx.filesremoved() elif ctx.files(): m1ctx = p1.manifestctx() m2ctx = p2.manifestctx() @@ -2667,6 +2673,11 @@ mn = mctx.write(trp, linkrev, p1.manifestnode(), p2.manifestnode(), added, drop, match=self.narrowmatch()) + + if writechangesetcopy: + filesadded = [f for f in changed + if not (f in m1 or f in m2)] + filesremoved = removed else: self.ui.debug('reusing manifest from p1 (listed files ' 'actually unchanged)\n') @@ -2683,6 +2694,8 @@ # filelogs. p1copies = p1copies or None p2copies = p2copies or None + filesadded = filesadded or None + filesremoved = filesremoved or None # update changelog self.ui.note(_("committing changelog\n")) @@ -2690,7 +2703,7 @@ n = self.changelog.add(mn, files, ctx.description(), trp, p1.node(), p2.node(), user, ctx.date(), ctx.extra().copy(), - p1copies, p2copies) + p1copies, p2copies, filesadded, filesremoved) xp1, xp2 = p1.hex(), p2 and p2.hex() or '' self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2) diff --git a/tests/test-copies-in-changeset.t b/tests/test-copies-in-changeset.t --- a/tests/test-copies-in-changeset.t +++ b/tests/test-copies-in-changeset.t @@ -5,6 +5,7 @@ > copies.read-from=changeset-only > [alias] > changesetcopies = log -r . -T 'files: {files} + > {extras % "{ifcontains("files", key, "{key}: {value}\n")}"} > {extras % "{ifcontains("copies", key, "{key}: {value}\n")}"}' > showcopies = log -r . -T '{file_copies % "{source} -> {name}\n"}' > [extensions] @@ -24,6 +25,8 @@ $ hg ci -m 'copy a to b, c, and d' $ hg changesetcopies files: b c d + filesadded: 0\x001\x002 (esc) + p1copies: b\x00a (esc) c\x00a (esc) d\x00a (esc) @@ -43,6 +46,9 @@ $ hg ci -m 'rename b to b2' $ hg changesetcopies files: b b2 + filesadded: 1 + filesremoved: 0 + p1copies: b2\x00b (esc) $ hg showcopies b -> b2 @@ -60,6 +66,7 @@ $ hg ci -m 'move b onto d' $ hg changesetcopies files: c + p1copies: c\x00b2 (esc) $ hg showcopies b2 -> c @@ -88,6 +95,8 @@ $ hg ci -m 'merge' $ hg changesetcopies files: g h i + filesadded: 0\x001\x002 (esc) + p1copies: g\x00a (esc) i\x00f (esc) p2copies: h\x00d (esc) @@ -102,6 +111,9 @@ $ hg ci -m 'copy a to j' --config experimental.copies.write-to=compatibility $ hg changesetcopies files: j + filesadded: 0 + filesremoved: + p1copies: j\x00a (esc) p2copies: $ hg debugdata j 0 @@ -122,6 +134,9 @@ $ hg ci -m 'modify j' --config experimental.copies.write-to=compatibility $ hg changesetcopies files: j + filesadded: + filesremoved: + p1copies: p2copies: @@ -131,6 +146,7 @@ $ hg ci -m 'copy a to k' --config experimental.copies.write-to=filelog-only $ hg changesetcopies files: k + $ hg debugdata k 0 \x01 (esc) copy: a @@ -157,9 +173,9 @@ $ hg mv a b $ hg ci -qm 'rename a to b' $ hg rebase -d 1 --config rebase.experimental.inmemory=yes - rebasing 2:55d0b405c1b2 "rename a to b" (tip) + rebasing 2:acfc33f3aa6d "rename a to b" (tip) merging a and b to b - saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/55d0b405c1b2-78df867e-rebase.hg + saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/acfc33f3aa6d-81d0180d-rebase.hg $ hg st --change . --copies A b a diff --git a/tests/test-copies.t b/tests/test-copies.t --- a/tests/test-copies.t +++ b/tests/test-copies.t @@ -551,14 +551,15 @@ $ hg up 2 -q $ hg graft -r 4 --base 3 --hidden - grafting 4:af28412ec03c "added d, modified b" (tip) + grafting 4:af28412ec03c "added d, modified b" (tip) (no-changeset !) + grafting 4:6325ca0b7a1c "added d, modified b" (tip) (changeset !) merging b1 and b to b1 $ hg l -l1 -p @ 5 added d, modified b | b1 ~ diff -r 5a4825cc2926 -r 94a2f1a0e8e2 b1 (no-changeset !) - ~ diff -r f5474f5023a8 -r ef7c02d69f3d b1 (changeset !) + ~ diff -r df722b7fe2d5 -r ba3ddbbdfd96 b1 (changeset !) --- a/b1 Thu Jan 01 00:00:00 1970 +0000 +++ b/b1 Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +1,2 @@ @@ -618,7 +619,8 @@ a $ hg rebase -r . -d 2 -t :other - rebasing 5:5018b1509e94 "added willconflict and d" (tip) + rebasing 5:5018b1509e94 "added willconflict and d" (tip) (no-changeset !) + rebasing 5:619047c26bf8 "added willconflict and d" (tip) (changeset !) $ hg up 3 -q $ hg l --hidden @@ -641,4 +643,5 @@ neither of the merging csets will be a descendant of the base revision: $ hg graft -r 6 --base 4 --hidden -t :other - grafting 6:99802e4f1e46 "added willconflict and d" (tip) + grafting 6:99802e4f1e46 "added willconflict and d" (tip) (no-changeset !) + grafting 6:9ddc6fb3b691 "added willconflict and d" (tip) (changeset !)