[PATCH 4 of 4] unbundler: separate delta and header parsing

Benoit Boissinot bboissin at gmail.com
Sun May 1 10:27:05 CDT 2011


# HG changeset patch
# User Benoit Boissinot <benoit.boissinot at ens-lyon.org>
# Date 1304182884 -7200
# Node ID 9762c75cd266ffdd7f59c517fb8f4d02f7a346d3
# Parent  9b91ea4c3d7c534d11a6730135328a26d20fc771
unbundler: separate delta and header parsing

Add header parsing for changelog and manifest (currently no headers might
change for next-gen bundle).

diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -34,7 +34,7 @@
         n = len(self)
         chain = None
         while 1:
-            chunkdata = bundle.parsechunk(chain)
+            chunkdata = bundle.deltachunk(chain)
             if not chunkdata:
                 break
             node = chunkdata['node']
@@ -197,6 +197,8 @@
 
     @util.propertycache
     def changelog(self):
+        # consume the header if it exists
+        self.bundle.changelogheader()
         c = bundlechangelog(self.sopener, self.bundle)
         self.manstart = self.bundle.tell()
         return c
@@ -204,6 +206,8 @@
     @util.propertycache
     def manifest(self):
         self.bundle.seek(self.manstart)
+        # consume the header if it exists
+        self.bundle.manifestheader()
         m = bundlemanifest(self.sopener, self.bundle, self.changelog.rev)
         self.filestart = self.bundle.tell()
         return m
@@ -225,12 +229,13 @@
         if not self.bundlefilespos:
             self.bundle.seek(self.filestart)
             while 1:
-                chunk = self.bundle.chunk()
-                if not chunk:
+                chunkdata = self.bundle.filelogheader()
+                if not chunkdata:
                     break
-                self.bundlefilespos[chunk] = self.bundle.tell()
+                fname = chunkdata['filename']
+                self.bundlefilespos[fname] = self.bundle.tell()
                 while 1:
-                    c = self.bundle.chunk()
+                    c = self.bundle.deltachunk(None)
                     if not c:
                         break
 
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -159,10 +159,21 @@
             self.callback()
         return l - 4
 
-    def chunk(self):
-        """return the next chunk from changegroup 'source' as a string"""
+    def changelogheader(self):
+        """v10 does not have a changelog header chunk"""
+        return {}
+
+    def manifestheader(self):
+        """v10 does not have a manifest header chunk"""
+        return {}
+
+    def filelogheader(self):
+        """return the header of the filelogs chunk, v10 only has the filename"""
         l = self.chunklength()
-        return readexactly(self._stream, l)
+        if not l:
+            return {}
+        fname = readexactly(self._stream, l)
+        return dict(filename=fname)
 
     def _deltaheader(self, headertuple, prevnode):
         node, p1, p2, cs = headertuple
@@ -172,7 +183,7 @@
             deltabase = prevnode
         return node, p1, p2, deltabase, cs
 
-    def parsechunk(self, prevnode):
+    def deltachunk(self, prevnode):
         l = self.chunklength()
         if not l:
             return {}
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1220,7 +1220,7 @@
                 ui.write("\n%s\n" % named)
                 chain = None
                 while 1:
-                    chunkdata = gen.parsechunk(chain)
+                    chunkdata = gen.deltachunk(chain)
                     if not chunkdata:
                         break
                     node = chunkdata['node']
@@ -1234,17 +1234,21 @@
                               hex(cs), hex(deltabase), len(delta)))
                     chain = node
 
+            chunkdata = gen.changelogheader()
             showchunks("changelog")
+            chunkdata = gen.manifestheader()
             showchunks("manifest")
             while 1:
-                fname = gen.chunk()
-                if not fname:
+                chunkdata = gen.filelogheader()
+                if not chunkdata:
                     break
+                fname = chunkdata['filename']
                 showchunks(fname)
         else:
+            chunkdata = gen.changelogheader()
             chain = None
             while 1:
-                chunkdata = gen.parsechunk(chain)
+                chunkdata = gen.deltachunk(chain)
                 if not chunkdata:
                     break
                 node = chunkdata['node']
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1712,6 +1712,7 @@
             pr = prog()
             source.callback = pr
 
+            source.changelogheader()
             if (cl.addgroup(source, csmap, trp) is None
                 and not emptyok):
                 raise util.Abort(_("received changelog group is empty"))
@@ -1731,6 +1732,7 @@
             # if the result of the merge of 1 and 2 is the same in 3 and 4,
             # no new manifest will be created and the manifest group will
             # be empty during the pull
+            source.manifestheader()
             self.manifest.addgroup(source, revmap, trp)
             self.ui.progress(_('manifests'), None)
 
@@ -1752,9 +1754,10 @@
             source.callback = None
 
             while 1:
-                f = source.chunk()
-                if not f:
+                chunkdata = source.filelogheader()
+                if not chunkdata:
                     break
+                f = chunkdata["filename"]
                 self.ui.debug("adding %s revisions\n" % f)
                 pr()
                 fl = self.file(f)
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -1122,7 +1122,7 @@
             # loop through our set of deltas
             chain = None
             while 1:
-                chunkdata = bundle.parsechunk(chain)
+                chunkdata = bundle.deltachunk(chain)
                 if not chunkdata:
                     break
                 node = chunkdata['node']


More information about the Mercurial-devel mailing list