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 |
|
|
50 | while 1: | |
|
34 | def chunkpositer(): | |
|
35 | for chunk in changegroup.chunkiter(bundlefile): | |
|
51 | 36 | pos = bundlefile.tell() |
|
52 |
chunk |
|
|
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 |
|
|
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 |
|
|
|
179 | f = changegroup.getchunk(self.bundlefile) | |
|
198 | 180 |
|
|
199 | 181 |
|
|
200 | 182 |
|
|
201 |
|
|
|
183 | for c in changegroup.chunkiter(self.bundlefile): | |
|
202 | 184 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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