From patchwork Fri Aug 5 17:23:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [9,of,9,v2] bundlerepo: add support for treemanifests in cg3 bundles From: Augie Fackler X-Patchwork-Id: 16129 Message-Id: <9fd3a481214d424286e3.1470417827@arthedain.pit.corp.google.com> To: mercurial-devel@mercurial-scm.org Date: Fri, 05 Aug 2016 13:23:47 -0400 # HG changeset patch # User Augie Fackler # Date 1470416891 14400 # Fri Aug 05 13:08:11 2016 -0400 # Node ID 9fd3a481214d424286e3c1b52dc16a3a894665a4 # Parent bf05e3655cb4239fa34e0b7e263aa33a7a2143bd bundlerepo: add support for treemanifests in cg3 bundles This is a little messier than I'd like, and I'll probably come back and do some more refactoring later, but as it is this unblocks narrowhg. An alternative approach (which I may do as part of the mentioned refactoring) would be to construct *all* dirlog instances up front, so that we don't have to keep track of the linkmapper method. This would avoid a reference cycle between the bundlemanifest and the bundlerepository, but I was hesitant to do all the work up front like that. diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -187,10 +187,12 @@ class bundlechangelog(bundlerevlog, chan self.filteredrevs = oldfilter class bundlemanifest(bundlerevlog, manifest.manifest): - def __init__(self, opener, bundle, linkmapper): - manifest.manifest.__init__(self, opener) + def __init__(self, opener, bundle, linkmapper, dirlogstarts, dir=''): + manifest.manifest.__init__(self, opener, dir=dir) bundlerevlog.__init__(self, opener, self.indexfile, bundle, linkmapper) + self._dirlogstarts = dirlogstarts + self.linkmapper = linkmapper def baserevision(self, nodeorrev): node = nodeorrev @@ -203,6 +205,14 @@ class bundlemanifest(bundlerevlog, manif result = manifest.manifest.revision(self, nodeorrev) return result + def dirlog(self, d): + if d in self._dirlogstarts: + self.bundle.seek(self._dirlogstarts[d]) + return bundlemanifest( + self.opener, self.bundle, self.linkmapper, + self._dirlogstarts, dir=d) + return super(bundlemanifest, self).dirlog(d) + class bundlefilelog(bundlerevlog, filelog.filelog): def __init__(self, opener, path, bundle, linkmapper): filelog.filelog.__init__(self, opener, path) @@ -304,6 +314,8 @@ class bundlerepository(localrepo.localre bundlename, self.vfs) + # map dirlog name to position in the bundle + self.bundledirstarts = {} # type: Dict[bytes, int] # dict with the mapping 'filename' -> position in the bundle self.bundlefilespos = {} @@ -329,11 +341,16 @@ class bundlerepository(localrepo.localre # consume the header if it exists self.bundle.manifestheader() linkmapper = self.unfiltered().changelog.rev - m = bundlemanifest(self.svfs, self.bundle, linkmapper) - # XXX: hack to work with changegroup3, but we still don't handle - # tree manifests correctly + dirlogstarts = {} + # Note slight spooky action here: we pass in the dirlogstarts + # dict and fill it in *after* running the constructor. This is + # horrible. + m = bundlemanifest(self.svfs, self.bundle, linkmapper, dirlogstarts) if self.bundle.version == "03": - self.bundle.filelogheader() + for dirheader in iter(self.bundle.filelogheader, {}): + d = dirheader["filename"] + dirlogstarts[d] = self.bundle.tell() + _discarddeltachunks(self.bundle) self.filestart = self.bundle.tell() return m diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -913,7 +913,7 @@ class manifest(revlog.revlog): self._usemanifestv2 = usemanifestv2 indexfile = "00manifest.i" if dir: - assert self._treeondisk + assert self._treeondisk, 'opts is %r' % opts if not dir.endswith('/'): dir = dir + '/' indexfile = "meta/" + dir + "00manifest.i" diff --git a/tests/test-treemanifest.t b/tests/test-treemanifest.t --- a/tests/test-treemanifest.t +++ b/tests/test-treemanifest.t @@ -326,6 +326,25 @@ Stripping and recovering changes should rev offset length delta linkrev nodeid p1 p2 0 0 127 -1 4 064927a0648a 000000000000 000000000000 1 127 111 0 5 25ecb8cb8618 000000000000 000000000000 + $ hg incoming --traceback .hg/strip-backup/* + comparing with .hg/strip-backup/*-backup.hg (glob) + searching for changes + changeset: 6:51cfd7b1e13b + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: modify dir1/a + + $ hg pull .hg/strip-backup/* + pulling from .hg/strip-backup/51cfd7b1e13b-78a2f3ed-backup.hg + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + (run 'hg update' to get a working copy) + $ hg --config extensions.strip= strip tip + saved backup bundle to $TESTTMP/repo-mixed/.hg/strip-backup/*-backup.hg (glob) $ hg unbundle -q .hg/strip-backup/* $ hg debugindex --dir dir1 rev offset length delta linkrev nodeid p1 p2