mercurial/changegroup.py
changeset 14141 bd1cbfe5db5c
parent 14060 aaa9a5989405
child 14143 da635d3c5620
equal deleted inserted replaced
14140:82f0412ef7de 14141:bd1cbfe5db5c
     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