##// 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 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
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 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):
@@ -46,16 +31,13 b' class bundlerevlog(revlog.revlog):'
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")
@@ -194,12 +176,12 b' class bundlerepository(localrepo.localre'
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
@@ -12,6 +12,7 b' demandload(globals(), "os re sys signal '
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 demandload(globals(), "fnmatch hgweb mdiff random signal tempfile time")
13 demandload(globals(), "fnmatch hgweb mdiff random signal tempfile time")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
15 demandload(globals(), "changegroup")
15
16
16 class UnknownCommand(Exception):
17 class UnknownCommand(Exception):
17 """Exception raised if command is not in the command table."""
18 """Exception raised if command is not in the command table."""
@@ -306,11 +307,17 b' def write_bundle(cg, filename=None, comp'
306 else:
307 else:
307 fh.write("HG10UN")
308 fh.write("HG10UN")
308 z = nocompress()
309 z = nocompress()
309 while 1:
310 # parse the changegroup data, otherwise we will block
310 chunk = cg.read(4096)
311 # in case of sshrepo because we don't know the end of the stream
311 if not chunk:
312
312 break
313 # an empty chunkiter is the end of the changegroup
313 fh.write(z.compress(chunk))
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 fh.write(z.flush())
321 fh.write(z.flush())
315 cleanup = None
322 cleanup = None
316 return filename
323 return filename
@@ -5,12 +5,13 b''
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import struct, os, util
8 import os, util
9 import filelog, manifest, changelog, dirstate, repo
9 import filelog, manifest, changelog, dirstate, repo
10 from node import *
10 from node import *
11 from i18n import gettext as _
11 from i18n import gettext as _
12 from demandload import *
12 from demandload import *
13 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui")
13 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui")
14 demandload(globals(), "changegroup")
14
15
15 class localrepository(object):
16 class localrepository(object):
16 def __del__(self):
17 def __del__(self):
@@ -1244,7 +1245,7 b' class localrepository(object):'
1244 # If any filenodes are left, generate the group for them,
1245 # If any filenodes are left, generate the group for them,
1245 # otherwise don't bother.
1246 # otherwise don't bother.
1246 if len(msng_filenode_lst) > 0:
1247 if len(msng_filenode_lst) > 0:
1247 yield struct.pack(">l", len(fname) + 4) + fname
1248 yield changegroup.genchunk(fname)
1248 # Sort the filenodes by their revision #
1249 # Sort the filenodes by their revision #
1249 msng_filenode_lst.sort(cmp_by_rev_func(filerevlog))
1250 msng_filenode_lst.sort(cmp_by_rev_func(filerevlog))
1250 # Create a group generator and only pass in a changenode
1251 # Create a group generator and only pass in a changenode
@@ -1258,7 +1259,7 b' class localrepository(object):'
1258 # Don't need this anymore, toss it to free memory.
1259 # Don't need this anymore, toss it to free memory.
1259 del msng_filenode_set[fname]
1260 del msng_filenode_set[fname]
1260 # Signal that no more groups are left.
1261 # Signal that no more groups are left.
1261 yield struct.pack(">l", 0)
1262 yield changegroup.closechunk()
1262
1263
1263 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
1264 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
1264
1265
@@ -1318,39 +1319,18 b' class localrepository(object):'
1318 nodeiter = gennodelst(filerevlog)
1319 nodeiter = gennodelst(filerevlog)
1319 nodeiter = list(nodeiter)
1320 nodeiter = list(nodeiter)
1320 if nodeiter:
1321 if nodeiter:
1321 yield struct.pack(">l", len(fname) + 4) + fname
1322 yield changegroup.genchunk(fname)
1322 lookup = lookuprevlink_func(filerevlog)
1323 lookup = lookuprevlink_func(filerevlog)
1323 for chnk in filerevlog.group(nodeiter, lookup):
1324 for chnk in filerevlog.group(nodeiter, lookup):
1324 yield chnk
1325 yield chnk
1325
1326
1326 yield struct.pack(">l", 0)
1327 yield changegroup.closechunk()
1327 self.hook('outgoing', node=hex(nodes[0]), source=source)
1328 self.hook('outgoing', node=hex(nodes[0]), source=source)
1328
1329
1329 return util.chunkbuffer(gengroup())
1330 return util.chunkbuffer(gengroup())
1330
1331
1331 def addchangegroup(self, source):
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 def csmap(x):
1334 def csmap(x):
1355 self.ui.debug(_("add changeset %s\n") % short(x))
1335 self.ui.debug(_("add changeset %s\n") % short(x))
1356 return self.changelog.count()
1336 return self.changelog.count()
@@ -1372,7 +1352,8 b' class localrepository(object):'
1372 # pull off the changeset group
1352 # pull off the changeset group
1373 self.ui.status(_("adding changesets\n"))
1353 self.ui.status(_("adding changesets\n"))
1374 co = self.changelog.tip()
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 cnr, cor = map(self.changelog.rev, (cn, co))
1357 cnr, cor = map(self.changelog.rev, (cn, co))
1377 if cn == nullid:
1358 if cn == nullid:
1378 cnr = cor
1359 cnr = cor
@@ -1381,18 +1362,20 b' class localrepository(object):'
1381 # pull off the manifest group
1362 # pull off the manifest group
1382 self.ui.status(_("adding manifests\n"))
1363 self.ui.status(_("adding manifests\n"))
1383 mm = self.manifest.tip()
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 # process the files
1368 # process the files
1387 self.ui.status(_("adding file changes\n"))
1369 self.ui.status(_("adding file changes\n"))
1388 while 1:
1370 while 1:
1389 f = getchunk()
1371 f = changegroup.getchunk(source)
1390 if not f:
1372 if not f:
1391 break
1373 break
1392 self.ui.debug(_("adding %s revisions\n") % f)
1374 self.ui.debug(_("adding %s revisions\n") % f)
1393 fl = self.file(f)
1375 fl = self.file(f)
1394 o = fl.count()
1376 o = fl.count()
1395 n = fl.addgroup(getgroup(), revmap, tr)
1377 chunkiter = changegroup.chunkiter(source)
1378 n = fl.addgroup(chunkiter, revmap, tr)
1396 revisions += fl.count() - o
1379 revisions += fl.count() - o
1397 files += 1
1380 files += 1
1398
1381
@@ -13,7 +13,8 b' of the GNU General Public License, incor'
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(), "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 def hash(text, p1, p2):
19 def hash(text, p1, p2):
19 """generate a hash from the given text and its parent hashes
20 """generate a hash from the given text and its parent hashes
@@ -708,7 +709,7 b' class revlog(object):'
708
709
709 # if we don't have any revisions touched by these changesets, bail
710 # if we don't have any revisions touched by these changesets, bail
710 if not revs:
711 if not revs:
711 yield struct.pack(">l", 0)
712 yield changegroup.closechunk()
712 return
713 return
713
714
714 # add the parent of the first rev
715 # add the parent of the first rev
@@ -726,12 +727,9 b' class revlog(object):'
726 d = self.revdiff(a, b)
727 d = self.revdiff(a, b)
727 p = self.parents(nb)
728 p = self.parents(nb)
728 meta = nb + p[0] + p[1] + lookup(nb)
729 meta = nb + p[0] + p[1] + lookup(nb)
729 l = struct.pack(">l", len(meta) + len(d) + 4)
730 yield changegroup.genchunk("%s%s" % (meta, d))
730 yield l
731 yield meta
732 yield d
733
731
734 yield struct.pack(">l", 0)
732 yield changegroup.closechunk()
735
733
736 def addgroup(self, revs, linkmapper, transaction, unique=0):
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