##// END OF EJS Templates
changegroup.py: delay the loading of the bz2 and zlib modules
Alexis S. L. Carvalho -
r3762:b9d3e12d default
parent child Browse files
Show More
@@ -1,120 +1,120
1 1 """
2 2 changegroup.py - Mercurial changegroup manipulation functions
3 3
4 4 Copyright 2006 Matt Mackall <mpm@selenic.com>
5 5
6 6 This software may be used and distributed according to the terms
7 7 of the GNU General Public License, incorporated herein by reference.
8 8 """
9 9 from i18n import gettext as _
10 10 from demandload import *
11 11 demandload(globals(), "struct os bz2 zlib util tempfile")
12 12
13 13 def getchunk(source):
14 14 """get a chunk from a changegroup"""
15 15 d = source.read(4)
16 16 if not d:
17 17 return ""
18 18 l = struct.unpack(">l", d)[0]
19 19 if l <= 4:
20 20 return ""
21 21 d = source.read(l - 4)
22 22 if len(d) < l - 4:
23 23 raise util.Abort(_("premature EOF reading chunk"
24 24 " (got %d bytes, expected %d)")
25 25 % (len(d), l - 4))
26 26 return d
27 27
28 28 def chunkiter(source):
29 29 """iterate through the chunks in source"""
30 30 while 1:
31 31 c = getchunk(source)
32 32 if not c:
33 33 break
34 34 yield c
35 35
36 36 def genchunk(data):
37 37 """build a changegroup chunk"""
38 38 header = struct.pack(">l", len(data)+ 4)
39 39 return "%s%s" % (header, data)
40 40
41 41 def closechunk():
42 42 return struct.pack(">l", 0)
43 43
44 44 class nocompress(object):
45 45 def compress(self, x):
46 46 return x
47 47 def flush(self):
48 48 return ""
49 49
50 50 bundletypes = {
51 51 "": ("", nocompress),
52 52 "HG10UN": ("HG10UN", nocompress),
53 "HG10BZ": ("HG10", bz2.BZ2Compressor),
54 "HG10GZ": ("HG10GZ", zlib.compressobj),
53 "HG10BZ": ("HG10", lambda: bz2.BZ2Compressor()),
54 "HG10GZ": ("HG10GZ", lambda: zlib.compressobj()),
55 55 }
56 56
57 57 def writebundle(cg, filename, bundletype):
58 58 """Write a bundle file and return its filename.
59 59
60 60 Existing files will not be overwritten.
61 61 If no filename is specified, a temporary file is created.
62 62 bz2 compression can be turned off.
63 63 The bundle file will be deleted in case of errors.
64 64 """
65 65
66 66 fh = None
67 67 cleanup = None
68 68 try:
69 69 if filename:
70 70 if os.path.exists(filename):
71 71 raise util.Abort(_("file '%s' already exists") % filename)
72 72 fh = open(filename, "wb")
73 73 else:
74 74 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
75 75 fh = os.fdopen(fd, "wb")
76 76 cleanup = filename
77 77
78 78 header, compressor = bundletypes[bundletype]
79 79 fh.write(header)
80 80 z = compressor()
81 81
82 82 # parse the changegroup data, otherwise we will block
83 83 # in case of sshrepo because we don't know the end of the stream
84 84
85 85 # an empty chunkiter is the end of the changegroup
86 86 empty = False
87 87 while not empty:
88 88 empty = True
89 89 for chunk in chunkiter(cg):
90 90 empty = False
91 91 fh.write(z.compress(genchunk(chunk)))
92 92 fh.write(z.compress(closechunk()))
93 93 fh.write(z.flush())
94 94 cleanup = None
95 95 return filename
96 96 finally:
97 97 if fh is not None:
98 98 fh.close()
99 99 if cleanup is not None:
100 100 os.unlink(cleanup)
101 101
102 102 def readbundle(fh):
103 103 header = fh.read(6)
104 104 if not header.startswith("HG"):
105 105 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
106 106 elif not header.startswith("HG10"):
107 107 raise util.Abort(_("%s: unknown bundle version") % fname)
108 108
109 109 if header == "HG10BZ":
110 110 def generator(f):
111 111 zd = bz2.BZ2Decompressor()
112 112 zd.decompress("BZ")
113 113 for chunk in util.filechunkiter(f, 4096):
114 114 yield zd.decompress(chunk)
115 115 return util.chunkbuffer(generator(fh))
116 116 elif header == "HG10UN":
117 117 return fh
118 118
119 119 raise util.Abort(_("%s: unknown bundle compression type")
120 120 % fname)
General Comments 0
You need to be logged in to leave comments. Login now