Mercurial > hg
annotate mercurial/changegroup.py @ 13102:2956945c3bee stable
archival: don't set gzip filename header when there's no filename
This mainly affects hgweb, which can generate tar.gz archives without
filenames. Without this change, the header would be set to ".gz",
which can confuse Safari into extracting the file and renaming it to
"gz" when "Open 'safe' files after downloading" is enabled.
file(1) before:
hg-crew-5e51254ad4d4.tar.gz: gzip compressed data, was ".gz", last modified: Thu Dec 2 11:46:20 2010, max compression
after:
hg-crew-5e51254ad4d4.tar.gz: gzip compressed data, last modified: Thu Dec 2 11:46:20 2010, max compression
author | Brodie Rao <brodie@bitheap.org> |
---|---|
date | Tue, 07 Dec 2010 19:47:53 +1100 |
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) |