6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
7 |
7 |
8 from i18n import _ |
8 from i18n import _ |
9 import util |
9 import util |
10 import struct, os, bz2, zlib, tempfile |
10 import struct, os, bz2, zlib, tempfile |
|
11 |
|
12 _BUNDLE10_DELTA_HEADER = "20s20s20s20s" |
11 |
13 |
12 def readexactly(stream, n): |
14 def readexactly(stream, n): |
13 '''read n bytes from stream.read and abort if less was available''' |
15 '''read n bytes from stream.read and abort if less was available''' |
14 s = stream.read(n) |
16 s = stream.read(n) |
15 if len(s) < n: |
17 if len(s) < n: |
126 else: |
128 else: |
127 raise util.Abort("unknown bundle compression '%s'" % alg) |
129 raise util.Abort("unknown bundle compression '%s'" % alg) |
128 return util.chunkbuffer(generator(fh)) |
130 return util.chunkbuffer(generator(fh)) |
129 |
131 |
130 class unbundle10(object): |
132 class unbundle10(object): |
|
133 deltaheader = _BUNDLE10_DELTA_HEADER |
|
134 deltaheadersize = struct.calcsize(deltaheader) |
131 def __init__(self, fh, alg): |
135 def __init__(self, fh, alg): |
132 self._stream = decompressor(fh, alg) |
136 self._stream = decompressor(fh, alg) |
133 self._type = alg |
137 self._type = alg |
134 self.callback = None |
138 self.callback = None |
135 def compressed(self): |
139 def compressed(self): |
157 def chunk(self): |
161 def chunk(self): |
158 """return the next chunk from changegroup 'source' as a string""" |
162 """return the next chunk from changegroup 'source' as a string""" |
159 l = self.chunklength() |
163 l = self.chunklength() |
160 return readexactly(self._stream, l) |
164 return readexactly(self._stream, l) |
161 |
165 |
162 def parsechunk(self): |
166 def _deltaheader(self, headertuple, prevnode): |
|
167 node, p1, p2, cs = headertuple |
|
168 if prevnode is None: |
|
169 deltabase = p1 |
|
170 else: |
|
171 deltabase = prevnode |
|
172 return node, p1, p2, deltabase, cs |
|
173 |
|
174 def parsechunk(self, prevnode): |
163 l = self.chunklength() |
175 l = self.chunklength() |
164 if not l: |
176 if not l: |
165 return {} |
177 return {} |
166 h = readexactly(self._stream, 80) |
178 headerdata = readexactly(self._stream, self.deltaheadersize) |
167 node, p1, p2, cs = struct.unpack("20s20s20s20s", h) |
179 header = struct.unpack(self.deltaheader, headerdata) |
168 data = readexactly(self._stream, l - 80) |
180 delta = readexactly(self._stream, l - self.deltaheadersize) |
169 return dict(node=node, p1=p1, p2=p2, cs=cs, data=data) |
181 node, p1, p2, deltabase, cs = self._deltaheader(header, prevnode) |
|
182 return dict(node=node, p1=p1, p2=p2, cs=cs, |
|
183 deltabase=deltabase, delta=delta) |
170 |
184 |
171 class headerlessfixup(object): |
185 class headerlessfixup(object): |
172 def __init__(self, fh, h): |
186 def __init__(self, fh, h): |
173 self._h = h |
187 self._h = h |
174 self._fh = fh |
188 self._fh = fh |