Mercurial > hg-stable
changeset 20802:520df53ad26a
bundle2: a very first version of bundle2 unbundler
This changeset introduce an unbundler class to match the bundle2 bundler. It is
currently able to unbundle an empty bundle2 only and will gain more feature at
the same pace than the bundler.
It also comes with its special extension command in test.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Tue, 18 Mar 2014 14:28:42 -0700 |
parents | 9c5183cb9bca |
children | 88db3e615319 |
files | mercurial/bundle2.py tests/test-bundle2.t |
diffstat | 2 files changed, 64 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/bundle2.py Tue Mar 18 14:00:50 2014 -0700 +++ b/mercurial/bundle2.py Tue Mar 18 14:28:42 2014 -0700 @@ -60,6 +60,10 @@ Currently forced to 0 in the current state of the implementation """ +import util +import changegroup + + _magicstring = 'HG20' class bundle20(object): @@ -82,3 +86,48 @@ # to be obviously fixed soon. assert not self._parts yield '\0\0' + +class unbundle20(object): + """interpret a bundle2 stream + + (this will eventually yield parts)""" + + def __init__(self, fp): + # assume the magic string is ok and drop it + # to be obviously fixed soon. + self._fp = fp + self._readexact(4) + + def _unpack(self, format): + """unpack this struct format from the stream""" + data = self._readexact(struct.calcsize(format)) + return _unpack(format, data) + + def _readexact(self, size): + """read exactly <size> bytes from the stream""" + return changegroup.readexactly(self._fp, size) + + @util.propertycache + def params(self): + """dictionnary of stream level parameters""" + paramsize = self._readexact(2) + assert paramsize == '\0\0' + return {} + + def __iter__(self): + """yield all parts contained in the stream""" + # make sure param have been loaded + self.params + part = self._readpart() + while part is not None: + yield part + part = self._readpart() + + def _readpart(self): + """return None when an end of stream markers is reach""" + headersize = self._readexact(2) + assert headersize == '\0\0' + return None + + +
--- a/tests/test-bundle2.t Tue Mar 18 14:00:50 2014 -0700 +++ b/tests/test-bundle2.t Tue Mar 18 14:28:42 2014 -0700 @@ -8,6 +8,7 @@ > code. We still need to be able to test it while it grow up. > """ > + > import sys > from mercurial import cmdutil > from mercurial import bundle2 > cmdtable = {} @@ -19,6 +20,14 @@ > bundle = bundle2.bundle20() > for chunk in bundle.getchunks(): > ui.write(chunk) + > + > @command('unbundle2', [], '') + > def cmdunbundle2(ui, repo): + > """read a bundle2 container from standard input""" + > unbundler = bundle2.unbundle20(sys.stdin) + > ui.write('options count: %i\n' % len(unbundler.params)) + > parts = list(unbundler) + > ui.write('parts count: %i\n' % len(parts)) > EOF $ cat >> $HGRCPATH << EOF > [extensions] @@ -34,3 +43,9 @@ $ hg bundle2 HG20\x00\x00\x00\x00 (no-eol) (esc) + +Test parsing of an empty bundle + + $ hg bundle2 | hg unbundle2 + options count: 0 + parts count: 0