bundle: allow bundlerepo to support alternative manifest implementations
authorDurham Goode <durham@fb.com>
Tue, 07 Nov 2017 10:16:53 -0800
changeset 35011 a2dfc723b6b5
parent 35010 b81ad5b78a81
child 35012 d80380ba8e7d
bundle: allow bundlerepo to support alternative manifest implementations With our treemanifest logic, the manifests are no longer transported as part of the changegroup and are no longer stored in a revlog. This means the self.manifestlog line in bundlerepo.filestart no longer calls _constructmanifest, and therefore does not consume the manifest portion of the changegroup, which means filestart is not populated and we result in an infinite loop. The fix is to make filestart aware that self.manifestlog might not consume the changegroup part, and consume it manually if necessary. There's currently no way to test this in core, but our treemanifest extension has tests to cover this. Differential Revision: https://phab.mercurial-scm.org/D1329
mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py	Thu Oct 19 12:35:47 2017 +0200
+++ b/mercurial/bundlerepo.py	Tue Nov 07 10:16:53 2017 -0800
@@ -352,6 +352,15 @@
         self.filestart = self.bundle.tell()
         return m
 
+    def _consumemanifest(self):
+        """Consumes the manifest portion of the bundle, setting filestart so the
+        file portion can be read."""
+        self.bundle.seek(self.manstart)
+        self.bundle.manifestheader()
+        for delta in self.bundle.deltaiter():
+            pass
+        self.filestart = self.bundle.tell()
+
     @localrepo.unfilteredpropertycache
     def manstart(self):
         self.changelog
@@ -360,6 +369,14 @@
     @localrepo.unfilteredpropertycache
     def filestart(self):
         self.manifestlog
+
+        # If filestart was not set by self.manifestlog, that means the
+        # manifestlog implementation did not consume the manifests from the
+        # changegroup (ex: it might be consuming trees from a separate bundle2
+        # part instead). So we need to manually consume it.
+        if 'filestart' not in self.__dict__:
+            self._consumemanifest()
+
         return self.filestart
 
     def url(self):