treemanifest: allow hybrid repos to make treeonly commits

If a hybrid repo pulls in a treeonly commit from a treeonly client, it
previously couldn't commit on top of it because it tried to read the flat
manifest. This patch makes it possible for the hybrid repo to make a treeonly
commit if it is committing on top of a treeonly commit (i.e. where the manifest
only exists in the tree store, not in the flat manifest revlog).

This makes it easier for multiple types of repositories to interact, and to flip
back and forth between treeonly and non-treeonly as we migrate.

Differential Revision: https://phab.mercurial-scm.org/D1304
This commit is contained in:
Durham Goode 2017-11-07 09:06:24 -08:00
parent 7bc0614e4c
commit 579b7ba53d
2 changed files with 50 additions and 8 deletions

View File

@ -1016,11 +1016,19 @@ class manifestfactory(object):
return node
def ctxwrite(self, orig, mfctx, transaction, link, p1, p2, added, removed):
node = orig(mfctx, transaction, link, p1, p2, added, removed)
mfl = mfctx._manifestlog
treeenabled = self.ui.configbool("fastmanifest", "usetree")
if (supportsctree and treeenabled and
p1 not in mfl._revlog.nodemap and
not mfl.datastore.getmissing([('', p1)])):
# If p1 is not in the flat manifest but is in the tree store, then
# this is a commit on top of a tree only commit and we should then
# produce a treeonly commit.
node = None
else:
node = orig(mfctx, transaction, link, p1, p2, added, removed)
if supportsctree and treeenabled:
mfl = mfctx._manifestlog
datastore = mfl.datastore
opener = mfctx._revlog().opener
@ -1082,13 +1090,25 @@ class manifestfactory(object):
transaction.addabort('treepack', abort)
transaction.addpending('treepack', writepending)
dpack = treemanifest.InterceptedMutableDataPack(
transaction.treedatapack,
node, p1)
hpack = treemanifest.InterceptedMutableHistoryPack(
transaction.treehistpack, node, p1)
# If the manifest was already committed as a flat manifest, use
# its node.
if node is not None:
dpack = treemanifest.InterceptedMutableDataPack(
transaction.treedatapack,
node, p1)
hpack = treemanifest.InterceptedMutableHistoryPack(
transaction.treehistpack, node, p1)
else:
dpack = transaction.treedatapack
hpack = transaction.treehistpack
newtreeiter = newtree.finalize(tree)
for nname, nnode, ntext, np1text, np1, np2 in newtreeiter:
# If the node wasn't set by a flat manifest, use the tree
# root node.
if node is None and nname == '':
node = nnode
# Not using deltas, since there aren't any other trees in
# this pack it could delta against.
dpack.add(nname, nnode, revlog.nullid, ntext)

View File

@ -254,6 +254,28 @@ Test histedit treeonly commits
|
~
Test turning treeonly off and making sure we can still commit on top of treeonly
commits
$ echo >> subdir/x
$ hg debugindex -m --config treemanifest.treeonly=False | tail -1
2 102 51 -1 2 0427baa4e948 85b359fdb09e 000000000000
$ hg commit -m 'treeonly from hybrid repo' --config treemanifest.treeonly=False
$ hg log -r . -T '{desc}\n' --stat
treeonly from hybrid repo
subdir/x | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
$ hg log -r . -T '{desc}\n' --stat --config treemanifest.treeonly=False
treeonly from hybrid repo
subdir/x | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
$ hg debugindex -m --config treemanifest.treeonly=False | tail -1
2 102 51 -1 2 0427baa4e948 85b359fdb09e 000000000000
$ hg strip -r . --config fbamend.safestrip=False
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
saved backup bundle to $TESTTMP/client/.hg/strip-backup/87da9865954c-3cfa5389-backup.hg (glob)
Test peer-to-peer push/pull of tree only commits
$ cd ..
$ clearcache