# HG changeset patch # User Pierre-Yves David # Date 2019-10-07 03:36:51 # Node ID beed7ce6168130d5d9bd115a8350f3d7d58a02cd # Parent 52781d57313d512efb7150603104bea3ca11d0eb sidedatacopies: write copies information in sidedata when applicable If the format of the repository indicate it stores copies information into changeset's sidedata, then we actually write that information into sidedata at commit time. It will be put to use in later changesets. Currently, we store all field unconditionally, but that is likely to change in the future for the sake of efficiency. Differential Revision: https://phab.mercurial-scm.org/D6950 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