[PATCH 2 of 4] bundle2: support unbundling empty part
pierre-yves.david at ens-lyon.org
pierre-yves.david at ens-lyon.org
Thu Mar 27 02:19:43 UTC 2014
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1395295443 25200
# Wed Mar 19 23:04:03 2014 -0700
# Node ID 436781b585ec855d099181ee7c45787b4975a784
# Parent 447f461fcdc476a60412f7e91b29e38d5b46de22
bundle2: support unbundling empty part
We augment the unbundler to make it able to unbundle the empty part we are now
able to bundle.
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -237,23 +237,44 @@ class unbundle20(object):
part = self._readpart()
self.ui.debug('end of bundle2 stream\n')
def _readpart(self):
"""return None when an end of stream markers is reach"""
- headersize = self._readexact(2)
- assert headersize == '\0\0'
- return None
+
+ headersize = self._unpack(_fpartheadersize)[0]
+ self.ui.debug('part header size: %i\n' % headersize)
+ if not headersize:
+ return None
+ headerblock = self._readexact(headersize)
+ # some utility to help reading from the header bloc
+ def fromheader(size, _offset=[0]):
+ """return the next <size> byte from the header"""
+ offset = _offset[0] #small hack to make this mutable
+ data = headerblock[offset:(offset + size)]
+ _offset[0] = offset + size
+ return data
+ typesize = _unpack(_fparttypesize, fromheader(1))[0]
+ parttype = fromheader(typesize)
+ self.ui.debug('part type: "%s"\n' % parttype)
+ current = part(parttype)
+ assert fromheader(2) == '\0\0' # no option for now
+ self.ui.debug('part parameters: 0\n')
+ assert self._readexact(4) == '\0\0\0\0' #empty payload
+ self.ui.debug('payload chunk size: 0\n')
+ return current
+
class part(object):
"""A bundle2 part contains actual application level payload
The part have `type` used to route it to proper application level object
that interpret its content.
"""
- def __init__(self, parttype):
+ def __init__(self, parttype, data=''):
self.type = parttype
+ self.data = data
def getchunks(self):
### header
header = [_pack(_fparttypesize, len(self.type)),
self.type,
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -58,10 +58,12 @@ Create an extension to test bundle2 API
> value = params[key]
> if value is not None:
> ui.write(' %s\n' % value)
> parts = list(unbundler)
> ui.write('parts count: %i\n' % len(parts))
+ > for p in parts:
+ > ui.write(' :%s:\n' % p.type)
> EOF
$ cat >> $HGRCPATH << EOF
> [extensions]
> bundle2=$TESTTMP/bundle2.py
> EOF
@@ -204,10 +206,11 @@ unbundling debug
options count: 2
- e|! 7/
babar%#==tutu
- simple
start extraction of bundle2 parts
+ part header size: 0
end of bundle2 stream
parts count: 0
Test buggy input
@@ -241,5 +244,29 @@ Test part
HG20\x00\x00\x00\r (esc)
test:empty\x00\x00\x00\x00\x00\x00\x00\r (esc)
test:empty\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
+ $ hg unbundle2 < ../parts.hg2
+ options count: 0
+ parts count: 2
+ :test:empty:
+ :test:empty:
+
+ $ hg unbundle2 --debug < ../parts.hg2
+ start processing of HG20 stream
+ reading bundle2 stream parameters
+ options count: 0
+ start extraction of bundle2 parts
+ part header size: 13
+ part type: "test:empty"
+ part parameters: 0
+ payload chunk size: 0
+ part header size: 13
+ part type: "test:empty"
+ part parameters: 0
+ payload chunk size: 0
+ part header size: 0
+ end of bundle2 stream
+ parts count: 2
+ :test:empty:
+ :test:empty:
More information about the Mercurial-devel
mailing list