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