comparison mercurial/bundlerepo.py @ 1981:736b6c96bbbc

make incoming work via ssh (issue139); move chunk code into separate module. Incoming ssh needs to detect the end of the changegroup, otherwise it would block trying to read from the ssh pipe. This is done by parsing the changegroup chunks. bundlerepo.getchunk() already is identical to localrepo.addchangegroup.getchunk(), which is followed by getgroup which looks much like what you can re-use in bundlerepository.__init__() and in write_bundle(). bundlerevlog.__init__.genchunk() looks very similar, too, as do some while loops in localrepo.py. Applied patch from Benoit Boissinot to move duplicate/related code to mercurial/changegroup.py and use this to fix incoming ssh.
author Thomas Arendsen Hein <thomas@intevation.de>
date Tue, 21 Mar 2006 11:47:21 +0100
parents dfb796786337
children 01ee43dda681
comparison
equal deleted inserted replaced
1980:dfb796786337 1981:736b6c96bbbc
11 """ 11 """
12 12
13 from node import * 13 from node import *
14 from i18n import gettext as _ 14 from i18n import gettext as _
15 from demandload import demandload 15 from demandload import demandload
16 demandload(globals(), "util os struct") 16 demandload(globals(), "changegroup util os struct")
17 17
18 import localrepo, changelog, manifest, filelog, revlog 18 import localrepo, changelog, manifest, filelog, revlog
19
20 def getchunk(source):
21 """get a chunk from a group"""
22 d = source.read(4)
23 if not d:
24 return ""
25 l = struct.unpack(">l", d)[0]
26 if l <= 4:
27 return ""
28 d = source.read(l - 4)
29 if len(d) < l - 4:
30 raise util.Abort(_("premature EOF reading chunk"
31 " (got %d bytes, expected %d)")
32 % (len(d), l - 4))
33 return d
34 19
35 class bundlerevlog(revlog.revlog): 20 class bundlerevlog(revlog.revlog):
36 def __init__(self, opener, indexfile, datafile, bundlefile, 21 def __init__(self, opener, indexfile, datafile, bundlefile,
37 linkmapper=None): 22 linkmapper=None):
38 # How it works: 23 # How it works:
44 # len(index[r]). If the tuple is bigger than 7, it is a bundle 29 # len(index[r]). If the tuple is bigger than 7, it is a bundle
45 # (it is bigger since we store the node to which the delta is) 30 # (it is bigger since we store the node to which the delta is)
46 # 31 #
47 revlog.revlog.__init__(self, opener, indexfile, datafile) 32 revlog.revlog.__init__(self, opener, indexfile, datafile)
48 self.bundlefile = bundlefile 33 self.bundlefile = bundlefile
49 def genchunk(): 34 def chunkpositer():
50 while 1: 35 for chunk in changegroup.chunkiter(bundlefile):
51 pos = bundlefile.tell() 36 pos = bundlefile.tell()
52 chunk = getchunk(bundlefile) 37 yield chunk, pos - len(chunk)
53 if not chunk:
54 break
55 yield chunk, pos + 4 # XXX struct.calcsize(">l") == 4
56 n = self.count() 38 n = self.count()
57 prev = None 39 prev = None
58 for chunk, start in genchunk(): 40 for chunk, start in chunkpositer():
59 size = len(chunk) 41 size = len(chunk)
60 if size < 80: 42 if size < 80:
61 raise util.Abort("invalid changegroup") 43 raise util.Abort("invalid changegroup")
62 start += 80 44 start += 80
63 size -= 80 45 size -= 80
192 self.manifest = bundlemanifest(self.opener, self.bundlefile, 174 self.manifest = bundlemanifest(self.opener, self.bundlefile,
193 self.changelog.rev) 175 self.changelog.rev)
194 # dict with the mapping 'filename' -> position in the bundle 176 # dict with the mapping 'filename' -> position in the bundle
195 self.bundlefilespos = {} 177 self.bundlefilespos = {}
196 while 1: 178 while 1:
197 f = getchunk(self.bundlefile) 179 f = changegroup.getchunk(self.bundlefile)
198 if not f: 180 if not f:
199 break 181 break
200 self.bundlefilespos[f] = self.bundlefile.tell() 182 self.bundlefilespos[f] = self.bundlefile.tell()
201 while getchunk(self.bundlefile): 183 for c in changegroup.chunkiter(self.bundlefile):
202 pass 184 pass
203 185
204 def dev(self): 186 def dev(self):
205 return -1 187 return -1
206 188
207 def file(self, f): 189 def file(self, f):