Mercurial > hg-stable
annotate mercurial/changegroup.py @ 13382:d747774ca9da
Make sure bundlerepo doesn't leak temp files (issue2491)
Add empty repository.close() and call it in dispatch.
Remove bundlerepository.__del__(), merging it into bundlerepository.close(),
which overrides repository.close().
http://docs.python.org/reference/datamodel.html says:
"It is not guaranteed that __del__() methods are called for objects that
still exist when the interpreter exits."
author | Adrian Buehlmann <adrian@cadifra.com> |
---|---|
date | Sat, 12 Feb 2011 10:58:11 +0100 |
parents | 6277a9469dff |
children | ab3f4ee48adc |
rev | line source |
---|---|
8226
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
1 # changegroup.py - Mercurial changegroup manipulation functions |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
2 # |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
3 # Copyright 2006 Matt Mackall <mpm@selenic.com> |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
4 # |
8b2cd04a6e97
put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents:
8225
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
3859
diff
changeset
|
7 |
3891 | 8 from i18n import _ |
8312
b87a50b7125c
separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents:
8226
diff
changeset
|
9 import util |
b87a50b7125c
separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents:
8226
diff
changeset
|
10 import struct, os, bz2, zlib, tempfile |
1981
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
11 |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
12 def getchunk(source): |
9437
1c4e4004f3a6
Improve some docstrings relating to changegroups and prepush().
Greg Ward <greg-hg@gerg.ca>
parents:
9087
diff
changeset
|
13 """return the next chunk from changegroup 'source' as a string""" |
1981
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
14 d = source.read(4) |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
15 if not d: |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
16 return "" |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
17 l = struct.unpack(">l", d)[0] |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
18 if l <= 4: |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
19 return "" |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
20 d = source.read(l - 4) |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
21 if len(d) < l - 4: |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
22 raise util.Abort(_("premature EOF reading chunk" |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
23 " (got %d bytes, expected %d)") |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
24 % (len(d), l - 4)) |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
25 return d |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
26 |
5368
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
27 def chunkheader(length): |
9437
1c4e4004f3a6
Improve some docstrings relating to changegroups and prepush().
Greg Ward <greg-hg@gerg.ca>
parents:
9087
diff
changeset
|
28 """return a changegroup chunk header (string)""" |
5368
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
29 return struct.pack(">l", length + 4) |
1981
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
30 |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
31 def closechunk(): |
9437
1c4e4004f3a6
Improve some docstrings relating to changegroups and prepush().
Greg Ward <greg-hg@gerg.ca>
parents:
9087
diff
changeset
|
32 """return a changegroup chunk header (string) for a zero-length chunk""" |
1981
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
33 return struct.pack(">l", 0) |
736b6c96bbbc
make incoming work via ssh (issue139); move chunk code into separate module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff
changeset
|
34 |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
35 class nocompress(object): |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
36 def compress(self, x): |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
37 return x |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
38 def flush(self): |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
39 return "" |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
40 |
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3660
diff
changeset
|
41 bundletypes = { |
3704
9c1737a3e254
fix writebundle for bz2 bundles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3662
diff
changeset
|
42 "": ("", nocompress), |
9c1737a3e254
fix writebundle for bz2 bundles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3662
diff
changeset
|
43 "HG10UN": ("HG10UN", nocompress), |
3762
b9d3e12da485
changegroup.py: delay the loading of the bz2 and zlib modules
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3706
diff
changeset
|
44 "HG10BZ": ("HG10", lambda: bz2.BZ2Compressor()), |
b9d3e12da485
changegroup.py: delay the loading of the bz2 and zlib modules
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3706
diff
changeset
|
45 "HG10GZ": ("HG10GZ", lambda: zlib.compressobj()), |
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3660
diff
changeset
|
46 } |
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3660
diff
changeset
|
47 |
10356
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
48 def collector(cl, mmfs, files): |
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
49 # Gather information about changeset nodes going out in a bundle. |
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
50 # We want to gather manifests needed and filelogs affected. |
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
51 def collect(node): |
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
52 c = cl.read(node) |
11648
801533a52799
changegroup*(): use set instead of dict
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10430
diff
changeset
|
53 files.update(c[3]) |
10356
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
54 mmfs.setdefault(c[0], node) |
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
55 return collect |
bc2414948012
localrepo: unify changegroup and changegroupsubset code paths a bit
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10263
diff
changeset
|
56 |
9087 | 57 # hgweb uses this list to communicate its preferred type |
6152
c050548307a4
hgweb: use bundletypes from mercurial.changegroup
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5906
diff
changeset
|
58 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN'] |
c050548307a4
hgweb: use bundletypes from mercurial.changegroup
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5906
diff
changeset
|
59 |
3706
0d810798acb1
Use 'bundletype' instead of 'type' to not shadow built-in function.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3705
diff
changeset
|
60 def writebundle(cg, filename, bundletype): |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
61 """Write a bundle file and return its filename. |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
62 |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
63 Existing files will not be overwritten. |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
64 If no filename is specified, a temporary file is created. |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
65 bz2 compression can be turned off. |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
66 The bundle file will be deleted in case of errors. |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
67 """ |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
68 |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
69 fh = None |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
70 cleanup = None |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
71 try: |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
72 if filename: |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
73 fh = open(filename, "wb") |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
74 else: |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
75 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg") |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
76 fh = os.fdopen(fd, "wb") |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
77 cleanup = filename |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
78 |
3706
0d810798acb1
Use 'bundletype' instead of 'type' to not shadow built-in function.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3705
diff
changeset
|
79 header, compressor = bundletypes[bundletype] |
3704
9c1737a3e254
fix writebundle for bz2 bundles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3662
diff
changeset
|
80 fh.write(header) |
9c1737a3e254
fix writebundle for bz2 bundles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3662
diff
changeset
|
81 z = compressor() |
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3660
diff
changeset
|
82 |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
83 # parse the changegroup data, otherwise we will block |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
84 # in case of sshrepo because we don't know the end of the stream |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
85 |
12335
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
86 # an empty chunkgroup is the end of the changegroup |
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
87 # a changegroup has at least 2 chunkgroups (changelog and manifest). |
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
88 # after that, an empty chunkgroup is the end of the changegroup |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
89 empty = False |
5906
0136d7f58982
allow the creation of bundles with empty changelog/manifest chunks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5368
diff
changeset
|
90 count = 0 |
0136d7f58982
allow the creation of bundles with empty changelog/manifest chunks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5368
diff
changeset
|
91 while not empty or count <= 2: |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
92 empty = True |
5906
0136d7f58982
allow the creation of bundles with empty changelog/manifest chunks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5368
diff
changeset
|
93 count += 1 |
12335
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
94 while 1: |
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
95 chunk = getchunk(cg) |
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
96 if not chunk: |
e21fe9c5fb25
bundle: get rid of chunkiter
Matt Mackall <mpm@selenic.com>
parents:
12334
diff
changeset
|
97 break |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
98 empty = False |
5368
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
99 fh.write(z.compress(chunkheader(len(chunk)))) |
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
100 pos = 0 |
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
101 while pos < len(chunk): |
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
102 next = pos + 2**20 |
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
103 fh.write(z.compress(chunk[pos:next])) |
61462e7d62ed
changegroup: avoid large copies
Matt Mackall <mpm@selenic.com>
parents:
3932
diff
changeset
|
104 pos = next |
3659
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
105 fh.write(z.compress(closechunk())) |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
106 fh.write(z.flush()) |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
107 cleanup = None |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
108 return filename |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
109 finally: |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
110 if fh is not None: |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
111 fh.close() |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
112 if cleanup is not None: |
025f68f22ae2
move write_bundle to changegroup.py
Matt Mackall <mpm@selenic.com>
parents:
2470
diff
changeset
|
113 os.unlink(cleanup) |
3660
8500a13ec44b
create a readbundle function
Matt Mackall <mpm@selenic.com>
parents:
3659
diff
changeset
|
114 |
12041
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
115 def decompressor(fh, alg): |
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
116 if alg == 'UN': |
6154
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
117 return fh |
12041
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
118 elif alg == 'GZ': |
6154
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
119 def generator(f): |
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
120 zd = zlib.decompressobj() |
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
121 for chunk in f: |
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
122 yield zd.decompress(chunk) |
12041
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
123 elif alg == 'BZ': |
3660
8500a13ec44b
create a readbundle function
Matt Mackall <mpm@selenic.com>
parents:
3659
diff
changeset
|
124 def generator(f): |
8500a13ec44b
create a readbundle function
Matt Mackall <mpm@selenic.com>
parents:
3659
diff
changeset
|
125 zd = bz2.BZ2Decompressor() |
8500a13ec44b
create a readbundle function
Matt Mackall <mpm@selenic.com>
parents:
3659
diff
changeset
|
126 zd.decompress("BZ") |
8500a13ec44b
create a readbundle function
Matt Mackall <mpm@selenic.com>
parents:
3659
diff
changeset
|
127 for chunk in util.filechunkiter(f, 4096): |
8500a13ec44b
create a readbundle function
Matt Mackall <mpm@selenic.com>
parents:
3659
diff
changeset
|
128 yield zd.decompress(chunk) |
12041
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
129 else: |
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
130 raise util.Abort("unknown bundle compression '%s'" % alg) |
12329
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
131 return util.chunkbuffer(generator(fh)) |
12041
270fb4d39153
bundle: factor out decompressor
Matt Mackall <mpm@selenic.com>
parents:
11648
diff
changeset
|
132 |
12043
bef5effb3db0
bundle: introduce bundle class
Matt Mackall <mpm@selenic.com>
parents:
12042
diff
changeset
|
133 class unbundle10(object): |
bef5effb3db0
bundle: introduce bundle class
Matt Mackall <mpm@selenic.com>
parents:
12042
diff
changeset
|
134 def __init__(self, fh, alg): |
12329
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
135 self._stream = decompressor(fh, alg) |
12044
bcc7139521b7
bundlerepo: remove duplication of bundle decompressors
Matt Mackall <mpm@selenic.com>
parents:
12043
diff
changeset
|
136 self._type = alg |
12334
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
137 self.callback = None |
12044
bcc7139521b7
bundlerepo: remove duplication of bundle decompressors
Matt Mackall <mpm@selenic.com>
parents:
12043
diff
changeset
|
138 def compressed(self): |
bcc7139521b7
bundlerepo: remove duplication of bundle decompressors
Matt Mackall <mpm@selenic.com>
parents:
12043
diff
changeset
|
139 return self._type != 'UN' |
12043
bef5effb3db0
bundle: introduce bundle class
Matt Mackall <mpm@selenic.com>
parents:
12042
diff
changeset
|
140 def read(self, l): |
bef5effb3db0
bundle: introduce bundle class
Matt Mackall <mpm@selenic.com>
parents:
12042
diff
changeset
|
141 return self._stream.read(l) |
12330
e527b8635881
bundle: make unbundle object seekable
Matt Mackall <mpm@selenic.com>
parents:
12329
diff
changeset
|
142 def seek(self, pos): |
e527b8635881
bundle: make unbundle object seekable
Matt Mackall <mpm@selenic.com>
parents:
12329
diff
changeset
|
143 return self._stream.seek(pos) |
e527b8635881
bundle: make unbundle object seekable
Matt Mackall <mpm@selenic.com>
parents:
12329
diff
changeset
|
144 def tell(self): |
12332
680fe77ab5b8
bundlerepo: use bundle objects everywhere
Matt Mackall <mpm@selenic.com>
parents:
12330
diff
changeset
|
145 return self._stream.tell() |
12347
6277a9469dff
bundlerepo: restore close() method
Matt Mackall <mpm@selenic.com>
parents:
12336
diff
changeset
|
146 def close(self): |
6277a9469dff
bundlerepo: restore close() method
Matt Mackall <mpm@selenic.com>
parents:
12336
diff
changeset
|
147 return self._stream.close() |
12334
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
148 |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
149 def chunklength(self): |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
150 d = self.read(4) |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
151 if not d: |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
152 return 0 |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
153 l = max(0, struct.unpack(">l", d)[0] - 4) |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
154 if l and self.callback: |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
155 self.callback() |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
156 return l |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
157 |
12333
44c7dfc2f6a3
bundle: make getchunk() a method
Matt Mackall <mpm@selenic.com>
parents:
12332
diff
changeset
|
158 def chunk(self): |
12334
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
159 """return the next chunk from changegroup 'source' as a string""" |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
160 l = self.chunklength() |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
161 d = self.read(l) |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
162 if len(d) < l: |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
163 raise util.Abort(_("premature EOF reading chunk" |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
164 " (got %d bytes, expected %d)") |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
165 % (len(d), l)) |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
166 return d |
50946802593d
bundle: refactor progress callback
Matt Mackall <mpm@selenic.com>
parents:
12333
diff
changeset
|
167 |
12336
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
168 def parsechunk(self): |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
169 l = self.chunklength() |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
170 if not l: |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
171 return {} |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
172 h = self.read(80) |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
173 node, p1, p2, cs = struct.unpack("20s20s20s20s", h) |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
174 data = self.read(l - 80) |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
175 return dict(node=node, p1=p1, p2=p2, cs=cs, data=data) |
9d234f7d8a77
bundle: move chunk parsing into unbundle class
Matt Mackall <mpm@selenic.com>
parents:
12335
diff
changeset
|
176 |
12329
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
177 class headerlessfixup(object): |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
178 def __init__(self, fh, h): |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
179 self._h = h |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
180 self._fh = fh |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
181 def read(self, n): |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
182 if self._h: |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
183 d, self._h = self._h[:n], self._h[n:] |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
184 if len(d) < n: |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
185 d += self._fh.read(n - len(d)) |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
186 return d |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
187 return self._fh.read(n) |
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
188 |
6154
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
189 def readbundle(fh, fname): |
ef1c5a3b653d
improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6152
diff
changeset
|
190 header = fh.read(6) |
12042
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
191 |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
192 if not fname: |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
193 fname = "stream" |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
194 if not header.startswith('HG') and header.startswith('\0'): |
12329
7458de933f26
bundle: push chunkbuffer down into decompress
Matt Mackall <mpm@selenic.com>
parents:
12044
diff
changeset
|
195 fh = headerlessfixup(fh, header) |
12042
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
196 header = "HG10UN" |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
197 |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
198 magic, version, alg = header[0:2], header[2:4], header[4:6] |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
199 |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
200 if magic != 'HG': |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
201 raise util.Abort(_('%s: not a Mercurial bundle') % fname) |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
202 if version != '10': |
210049a8d16e
bundle: unify/refactor unbundle/readbundle
Matt Mackall <mpm@selenic.com>
parents:
12041
diff
changeset
|
203 raise util.Abort(_('%s: unknown bundle version %s') % (fname, version)) |
12043
bef5effb3db0
bundle: introduce bundle class
Matt Mackall <mpm@selenic.com>
parents:
12042
diff
changeset
|
204 return unbundle10(fh, alg) |