[PATCH 3 of 3] bundlerepo: Add basic bundle2 support

Eric Sumner ericsumner at fb.com
Thu Feb 5 13:10:31 CST 2015


# HG changeset patch
# User Eric Sumner <ericsumner at fb.com>
# Date 1421358976 28800
#      Thu Jan 15 13:56:16 2015 -0800
# Node ID 881132ed1e3b99dbf24ba097a573b3dbac5bef03
# Parent  cacd3119be7dd5681f6bf05a167115d0cba01236
bundlerepo: Add basic bundle2 support

This will use the highest-version changegroup part from the bundle2 file for
the bundlerepo.  Over time, handlers can be added for additional parts, like
pushkeys.

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -497,7 +497,7 @@
         """read exactly <size> bytes from the stream"""
         return changegroup.readexactly(self._fp, size)
 
-    def seek(self, offset, whence):
+    def seek(self, offset, whence=0):
         """move the underlying file pointer"""
         if self._seekable:
             return self._fp.seek(offset, whence)
@@ -607,6 +607,9 @@
             return self._readexact(headersize)
         return None
 
+    def compressed(self):
+        return False
+
 
 class bundlepart(object):
     """A bundle2 part contains application level payload
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -15,7 +15,7 @@
 from i18n import _
 import os, tempfile, shutil
 import changegroup, util, mdiff, discovery, cmdutil, scmutil, exchange
-import localrepo, changelog, manifest, filelog, revlog, error, phases
+import localrepo, changelog, manifest, filelog, revlog, error, phases, bundle2
 
 class bundlerevlog(revlog.revlog):
     def __init__(self, opener, indexfile, bundle, linkmapper):
@@ -216,7 +216,7 @@
 
         self.tempfile = None
         f = util.posixfile(bundlename, "rb")
-        self.bundle = exchange.readbundle(ui, f, bundlename)
+        self.bundlefile = self.bundle = exchange.readbundle(ui, f, bundlename)
         if self.bundle.compressed():
             fdtemp, temp = self.vfs.mkstemp(prefix="hg-bundle-",
                                             suffix=".hg10un")
@@ -236,6 +236,23 @@
             f = self.vfs.open(self.tempfile, mode="rb")
             self.bundle = exchange.readbundle(ui, f, bundlename, self.vfs)
 
+        if isinstance(self.bundle, bundle2.unbundle20):
+            cgparts = [part for part in self.bundle.iterparts()
+                       if (part.type == 'b2x:changegroup')
+                       and (part.params.get('version', '01')
+                            in changegroup.packermap)]
+
+            if not cgparts:
+                raise util.Abort('No changegroups found')
+            version = cgparts[0].params.get('version', '01')
+            cgparts = [p for p in cgparts
+                       if p.params.get('version', '01') == version]
+            if len(cgparts) > 1:
+                raise NotImplementedError("Can't process multiple changegroups")
+            part = cgparts[0]
+
+            part.seek(0)
+            self.bundle = changegroup.packermap[version][1](part, 'UN')
         # dict with the mapping 'filename' -> position in the bundle
         self.bundlefilespos = {}
 
@@ -300,7 +317,7 @@
 
     def close(self):
         """Close assigned bundle file immediately."""
-        self.bundle.close()
+        self.bundlefile.close()
         if self.tempfile is not None:
             self.vfs.unlink(self.tempfile)
         if self._tempparent:
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1220,6 +1220,9 @@
 
         return ''.join(buf)
 
+    def close(self):
+        pass
+
 def filechunkiter(f, size=65536, limit=None):
     """Create a generator that produces the data in the file size
     (default 65536) bytes at a time, up to optional limit (default is
diff --git a/tests/test-bundle2-format.t b/tests/test-bundle2-format.t
--- a/tests/test-bundle2-format.t
+++ b/tests/test-bundle2-format.t
@@ -206,6 +206,7 @@
   $ cat >> $HGRCPATH << EOF
   > [extensions]
   > bundle2=$TESTTMP/bundle2.py
+  > strip=
   > [experimental]
   > bundle2-exp=True
   > evolution=createmarkers
@@ -768,6 +769,47 @@
   adding file changes
   added 0 changesets with 0 changes to 3 files
 
+  $ hg strip --rev '8+7+5+4'
+  saved backup bundle to $TESTTMP/main/.hg/strip-backup/9520eea781bc-backup.hg (glob)
+  $ hg incoming ../rev.hg2 -G
+  comparing with ../rev.hg2
+  searching for changes
+  o  8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits at gmail.com>  H
+  
+  o  7:eea13746799a draft Nicolas Dumazet <nicdumz.commits at gmail.com>  G
+  |
+  o  6:9520eea781bc draft Nicolas Dumazet <nicdumz.commits at gmail.com>  E
+  
+  o  5:32af7686d403 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  D
+  
+  $ hg pull ../rev.hg2
+  pulling from ../rev.hg2
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 3 changes to 3 files (+1 heads)
+  (run 'hg heads .' to see heads, 'hg merge' to merge)
+  $ hg log -G
+  o  8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits at gmail.com>  H
+  |
+  | o  7:eea13746799a draft Nicolas Dumazet <nicdumz.commits at gmail.com>  G
+  |/|
+  | o  6:9520eea781bc draft Nicolas Dumazet <nicdumz.commits at gmail.com>  E
+  | |
+  | | o  5:32af7686d403 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  D
+  | | |
+  o | |  4:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits at gmail.com>  F
+  |/ /
+  | o  3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  C
+  | |
+  | o  2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  B
+  |/
+  o  1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  A
+  
+  @  0:3903775176ed draft test  a
+  
+
 with reply
 
   $ hg bundle2 --rev '8+7+5+4' --reply ../rev-rr.hg2


More information about the Mercurial-devel mailing list