##// END OF EJS Templates
make incoming work via ssh (issue139); move chunk code into separate module....
Thomas Arendsen Hein -
r1981:736b6c96 default
parent child Browse files
Show More
@@ -0,0 +1,43 b''
1 """
2 changegroup.py - Mercurial changegroup manipulation functions
3
4 Copyright 2006 Matt Mackall <mpm@selenic.com>
5
6 This software may be used and distributed according to the terms
7 of the GNU General Public License, incorporated herein by reference.
8 """
9 import struct
10 from demandload import *
11 demandload(globals(), "util")
12
13 def getchunk(source):
14 """get a chunk from a changegroup"""
15 d = source.read(4)
16 if not d:
17 return ""
18 l = struct.unpack(">l", d)[0]
19 if l <= 4:
20 return ""
21 d = source.read(l - 4)
22 if len(d) < l - 4:
23 raise util.Abort(_("premature EOF reading chunk"
24 " (got %d bytes, expected %d)")
25 % (len(d), l - 4))
26 return d
27
28 def chunkiter(source):
29 """iterate through the chunks in source"""
30 while 1:
31 c = getchunk(source)
32 if not c:
33 break
34 yield c
35
36 def genchunk(data):
37 """build a changegroup chunk"""
38 header = struct.pack(">l", len(data)+ 4)
39 return "%s%s" % (header, data)
40
41 def closechunk():
42 return struct.pack(">l", 0)
43
@@ -13,25 +13,10 b' of the GNU General Public License, incor'
13 13 from node import *
14 14 from i18n import gettext as _
15 15 from demandload import demandload
16 demandload(globals(), "util os struct")
16 demandload(globals(), "changegroup util os struct")
17 17
18 18 import localrepo, changelog, manifest, filelog, revlog
19 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
35 20 class bundlerevlog(revlog.revlog):
36 21 def __init__(self, opener, indexfile, datafile, bundlefile,
37 22 linkmapper=None):
@@ -46,16 +31,13 b' class bundlerevlog(revlog.revlog):'
46 31 #
47 32 revlog.revlog.__init__(self, opener, indexfile, datafile)
48 33 self.bundlefile = bundlefile
49 def genchunk():
50 while 1:
34 def chunkpositer():
35 for chunk in changegroup.chunkiter(bundlefile):
51 36 pos = bundlefile.tell()
52 chunk = getchunk(bundlefile)
53 if not chunk:
54 break
55 yield chunk, pos + 4 # XXX struct.calcsize(">l") == 4
37 yield chunk, pos - len(chunk)
56 38 n = self.count()
57 39 prev = None
58 for chunk, start in genchunk():
40 for chunk, start in chunkpositer():
59 41 size = len(chunk)
60 42 if size < 80:
61 43 raise util.Abort("invalid changegroup")
@@ -194,11 +176,11 b' class bundlerepository(localrepo.localre'
194 176 # dict with the mapping 'filename' -> position in the bundle
195 177 self.bundlefilespos = {}
196 178 while 1:
197 f = getchunk(self.bundlefile)
179 f = changegroup.getchunk(self.bundlefile)
198 180 if not f:
199 181 break
200 182 self.bundlefilespos[f] = self.bundlefile.tell()
201 while getchunk(self.bundlefile):
183 for c in changegroup.chunkiter(self.bundlefile):
202 184 pass
203 185
204 186 def dev(self):
@@ -12,6 +12,7 b' demandload(globals(), "os re sys signal '
12 12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 13 demandload(globals(), "fnmatch hgweb mdiff random signal tempfile time")
14 14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
15 demandload(globals(), "changegroup")
15 16
16 17 class UnknownCommand(Exception):
17 18 """Exception raised if command is not in the command table."""
@@ -306,11 +307,17 b' def write_bundle(cg, filename=None, comp'
306 307 else:
307 308 fh.write("HG10UN")
308 309 z = nocompress()
309 while 1:
310 chunk = cg.read(4096)
311 if not chunk:
312 break
313 fh.write(z.compress(chunk))
310 # parse the changegroup data, otherwise we will block
311 # in case of sshrepo because we don't know the end of the stream
312
313 # an empty chunkiter is the end of the changegroup
314 empty = False
315 while not empty:
316 empty = True
317 for chunk in changegroup.chunkiter(cg):
318 empty = False
319 fh.write(z.compress(changegroup.genchunk(chunk)))
320 fh.write(z.compress(changegroup.closechunk()))
314 321 fh.write(z.flush())
315 322 cleanup = None
316 323 return filename
@@ -5,12 +5,13 b''
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 import struct, os, util
8 import os, util
9 9 import filelog, manifest, changelog, dirstate, repo
10 10 from node import *
11 11 from i18n import gettext as _
12 12 from demandload import *
13 13 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui")
14 demandload(globals(), "changegroup")
14 15
15 16 class localrepository(object):
16 17 def __del__(self):
@@ -1244,7 +1245,7 b' class localrepository(object):'
1244 1245 # If any filenodes are left, generate the group for them,
1245 1246 # otherwise don't bother.
1246 1247 if len(msng_filenode_lst) > 0:
1247 yield struct.pack(">l", len(fname) + 4) + fname
1248 yield changegroup.genchunk(fname)
1248 1249 # Sort the filenodes by their revision #
1249 1250 msng_filenode_lst.sort(cmp_by_rev_func(filerevlog))
1250 1251 # Create a group generator and only pass in a changenode
@@ -1258,7 +1259,7 b' class localrepository(object):'
1258 1259 # Don't need this anymore, toss it to free memory.
1259 1260 del msng_filenode_set[fname]
1260 1261 # Signal that no more groups are left.
1261 yield struct.pack(">l", 0)
1262 yield changegroup.closechunk()
1262 1263
1263 1264 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
1264 1265
@@ -1318,39 +1319,18 b' class localrepository(object):'
1318 1319 nodeiter = gennodelst(filerevlog)
1319 1320 nodeiter = list(nodeiter)
1320 1321 if nodeiter:
1321 yield struct.pack(">l", len(fname) + 4) + fname
1322 yield changegroup.genchunk(fname)
1322 1323 lookup = lookuprevlink_func(filerevlog)
1323 1324 for chnk in filerevlog.group(nodeiter, lookup):
1324 1325 yield chnk
1325 1326
1326 yield struct.pack(">l", 0)
1327 yield changegroup.closechunk()
1327 1328 self.hook('outgoing', node=hex(nodes[0]), source=source)
1328 1329
1329 1330 return util.chunkbuffer(gengroup())
1330 1331
1331 1332 def addchangegroup(self, source):
1332 1333
1333 def getchunk():
1334 d = source.read(4)
1335 if not d:
1336 return ""
1337 l = struct.unpack(">l", d)[0]
1338 if l <= 4:
1339 return ""
1340 d = source.read(l - 4)
1341 if len(d) < l - 4:
1342 raise repo.RepoError(_("premature EOF reading chunk"
1343 " (got %d bytes, expected %d)")
1344 % (len(d), l - 4))
1345 return d
1346
1347 def getgroup():
1348 while 1:
1349 c = getchunk()
1350 if not c:
1351 break
1352 yield c
1353
1354 1334 def csmap(x):
1355 1335 self.ui.debug(_("add changeset %s\n") % short(x))
1356 1336 return self.changelog.count()
@@ -1372,7 +1352,8 b' class localrepository(object):'
1372 1352 # pull off the changeset group
1373 1353 self.ui.status(_("adding changesets\n"))
1374 1354 co = self.changelog.tip()
1375 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique
1355 chunkiter = changegroup.chunkiter(source)
1356 cn = self.changelog.addgroup(chunkiter, csmap, tr, 1) # unique
1376 1357 cnr, cor = map(self.changelog.rev, (cn, co))
1377 1358 if cn == nullid:
1378 1359 cnr = cor
@@ -1381,18 +1362,20 b' class localrepository(object):'
1381 1362 # pull off the manifest group
1382 1363 self.ui.status(_("adding manifests\n"))
1383 1364 mm = self.manifest.tip()
1384 mo = self.manifest.addgroup(getgroup(), revmap, tr)
1365 chunkiter = changegroup.chunkiter(source)
1366 mo = self.manifest.addgroup(chunkiter, revmap, tr)
1385 1367
1386 1368 # process the files
1387 1369 self.ui.status(_("adding file changes\n"))
1388 1370 while 1:
1389 f = getchunk()
1371 f = changegroup.getchunk(source)
1390 1372 if not f:
1391 1373 break
1392 1374 self.ui.debug(_("adding %s revisions\n") % f)
1393 1375 fl = self.file(f)
1394 1376 o = fl.count()
1395 n = fl.addgroup(getgroup(), revmap, tr)
1377 chunkiter = changegroup.chunkiter(source)
1378 n = fl.addgroup(chunkiter, revmap, tr)
1396 1379 revisions += fl.count() - o
1397 1380 files += 1
1398 1381
@@ -13,7 +13,8 b' of the GNU General Public License, incor'
13 13 from node import *
14 14 from i18n import gettext as _
15 15 from demandload import demandload
16 demandload(globals(), "binascii errno heapq mdiff os sha struct zlib")
16 demandload(globals(), "binascii changegroup errno heapq mdiff os")
17 demandload(globals(), "sha struct zlib")
17 18
18 19 def hash(text, p1, p2):
19 20 """generate a hash from the given text and its parent hashes
@@ -708,7 +709,7 b' class revlog(object):'
708 709
709 710 # if we don't have any revisions touched by these changesets, bail
710 711 if not revs:
711 yield struct.pack(">l", 0)
712 yield changegroup.closechunk()
712 713 return
713 714
714 715 # add the parent of the first rev
@@ -726,12 +727,9 b' class revlog(object):'
726 727 d = self.revdiff(a, b)
727 728 p = self.parents(nb)
728 729 meta = nb + p[0] + p[1] + lookup(nb)
729 l = struct.pack(">l", len(meta) + len(d) + 4)
730 yield l
731 yield meta
732 yield d
730 yield changegroup.genchunk("%s%s" % (meta, d))
733 731
734 yield struct.pack(">l", 0)
732 yield changegroup.closechunk()
735 733
736 734 def addgroup(self, revs, linkmapper, transaction, unique=0):
737 735 """
General Comments 0
You need to be logged in to leave comments. Login now