diff --git a/mercurial/changelog.py b/mercurial/changelog.py --- a/mercurial/changelog.py +++ b/mercurial/changelog.py @@ -27,6 +27,8 @@ from .utils import ( stringutil, ) +from .revlogutils import sidedata as sidedatamod + _defaultextra = {b'branch': b'default'} @@ -676,6 +678,7 @@ class changelog(revlog.revlog): _(b'the name \'%s\' is reserved') % branch ) sortedfiles = sorted(files) + sidedata = None if extra is not None: for name in ( b'p1copies', @@ -704,13 +707,25 @@ class changelog(revlog.revlog): extra[b'filesadded'] = filesadded if filesremoved is not None: extra[b'filesremoved'] = filesremoved + elif self._copiesstorage == b'changeset-sidedata': + sidedata = {} + if p1copies is not None: + sidedata[sidedatamod.SD_P1COPIES] = p1copies + if p2copies is not None: + sidedata[sidedatamod.SD_P2COPIES] = p2copies + if filesadded is not None: + sidedata[sidedatamod.SD_FILESADDED] = filesadded + if filesremoved is not None: + sidedata[sidedatamod.SD_FILESREMOVED] = filesremoved if extra: extra = encodeextra(extra) parseddate = b"%s %s" % (parseddate, extra) l = [hex(manifest), user, parseddate] + sortedfiles + [b"", desc] text = b"\n".join(l) - return self.addrevision(text, transaction, len(self), p1, p2) + return self.addrevision( + text, transaction, len(self), p1, p2, sidedata=sidedata + ) def branchinfo(self, rev): """return the branch name and open/close state of a revision diff --git a/mercurial/interfaces/repository.py b/mercurial/interfaces/repository.py --- a/mercurial/interfaces/repository.py +++ b/mercurial/interfaces/repository.py @@ -1547,6 +1547,10 @@ class ilocalrepositorymain(interfaceutil names = interfaceutil.Attribute("""A ``namespaces`` instance.""") + filecopiesmode = interfaceutil.Attribute( + """The way files copies should be dealt with in this repo.""" + ) + def close(): """Close the handle on this repository.""" diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -825,10 +825,13 @@ def resolvestorevfsoptions(ui, requireme else: # explicitly mark repo as using revlogv0 options[b'revlogv0'] = True - writecopiesto = ui.config(b'experimental', b'copies.write-to') - copiesextramode = (b'changeset-only', b'compatibility') - if writecopiesto in copiesextramode: - options[b'copies-storage'] = b'extra' + if COPIESSDC_REQUIREMENT in requirements: + options[b'copies-storage'] = b'changeset-sidedata' + else: + writecopiesto = ui.config(b'experimental', b'copies.write-to') + copiesextramode = (b'changeset-only', b'compatibility') + if writecopiesto in copiesextramode: + options[b'copies-storage'] = b'extra' return options @@ -1182,6 +1185,10 @@ class localrepository(object): self._extrafilterid = repoview.extrafilter(ui) + self.filecopiesmode = None + if COPIESSDC_REQUIREMENT in self.requirements: + self.filecopiesmode = b'changeset-sidedata' + def _getvfsward(self, origfunc): """build a ward for self.vfs""" rref = weakref.ref(self) @@ -2949,12 +2956,17 @@ class localrepository(object): p1, p2 = ctx.p1(), ctx.p2() user = ctx.user() - writecopiesto = self.ui.config(b'experimental', b'copies.write-to') - writefilecopymeta = writecopiesto != b'changeset-only' - writechangesetcopy = writecopiesto in ( - b'changeset-only', - b'compatibility', - ) + if self.filecopiesmode == b'changeset-sidedata': + writechangesetcopy = True + writefilecopymeta = True + writecopiesto = None + else: + writecopiesto = self.ui.config(b'experimental', b'copies.write-to') + writefilecopymeta = writecopiesto != b'changeset-only' + writechangesetcopy = writecopiesto in ( + b'changeset-only', + b'compatibility', + ) p1copies, p2copies = None, None if writechangesetcopy: p1copies = ctx.p1copies() diff --git a/mercurial/revlogutils/sidedata.py b/mercurial/revlogutils/sidedata.py --- a/mercurial/revlogutils/sidedata.py +++ b/mercurial/revlogutils/sidedata.py @@ -48,6 +48,12 @@ SD_TEST5 = 5 SD_TEST6 = 6 SD_TEST7 = 7 +# key to store copies related information +SD_P1COPIES = 8 +SD_P2COPIES = 9 +SD_FILESADDED = 10 +SD_FILESREMOVED = 11 + # internal format constant SIDEDATA_HEADER = struct.Struct(r'>H') SIDEDATA_ENTRY = struct.Struct(r'>HL20s') 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 @@ -75,7 +75,17 @@ Check that copies are recorded correctly p1copies: 0\x00a (esc) 1\x00a (esc) 2\x00a (esc) - +#else + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 11 + '0\x00a\n1\x00a\n2\x00a' + entry-0011 size 0 + '' + entry-0012 size 5 + '0\n1\n2' + entry-0013 size 0 + '' #endif $ hg showcopies @@ -107,6 +117,17 @@ Check that renames are recorded correctl p1copies: 1\x00b (esc) +#else + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 3 + '1\x00b' + entry-0011 size 0 + '' + entry-0012 size 1 + '1' + entry-0013 size 1 + '0' #endif $ hg showcopies @@ -145,6 +166,17 @@ even though there is no filelog entry. p1copies: 0\x00b2 (esc) +#else + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 4 + '0\x00b2' + entry-0011 size 0 + '' + entry-0012 size 0 + '' + entry-0013 size 0 + '' #endif $ hg showcopies @@ -197,6 +229,17 @@ File 'f' exists only in p1, so 'i' shoul 2\x00f (esc) p2copies: 1\x00d (esc) +#else + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 7 + '0\x00a\n2\x00f' + entry-0011 size 3 + '1\x00d' + entry-0012 size 5 + '0\n1\n2' + entry-0013 size 0 + '' #endif $ hg showcopies @@ -218,6 +261,16 @@ Test writing to both changeset and filel p2copies: #else $ hg ci -m 'copy a to j' + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 3 + '0\x00a' + entry-0011 size 0 + '' + entry-0012 size 1 + '0' + entry-0013 size 0 + '' #endif $ hg debugdata j 0 \x01 (esc) @@ -243,6 +296,16 @@ copy information on to the filelog #else $ hg ci --amend -m 'copy a to j, v2' saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob) + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 3 + '0\x00a' + entry-0011 size 0 + '' + entry-0012 size 1 + '0' + entry-0013 size 0 + '' #endif $ hg showcopies --config experimental.copies.read-from=filelog-only a -> j @@ -260,6 +323,16 @@ won't have to fall back to reading from p2copies: #else $ hg ci -m 'modify j' + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 0 + '' + entry-0011 size 0 + '' + entry-0012 size 0 + '' + entry-0013 size 0 + '' #endif Test writing only to filelog @@ -273,6 +346,16 @@ Test writing only to filelog #else $ hg ci -m 'copy a to k' + $ hg debugsidedata -c -v -- -1 + 4 sidedata entries + entry-0010 size 3 + '0\x00a' + entry-0011 size 0 + '' + entry-0012 size 1 + '0' + entry-0013 size 0 + '' #endif $ hg debugdata k 0