77 if changedheads > 0: |
77 if changedheads > 0: |
78 result = 1 + changedheads |
78 result = 1 + changedheads |
79 elif changedheads < 0: |
79 elif changedheads < 0: |
80 result = -1 + changedheads |
80 result = -1 + changedheads |
81 return result |
81 return result |
82 |
|
83 bundletypes = { |
|
84 "": ("", None), # only when using unbundle on ssh and old http servers |
|
85 # since the unification ssh accepts a header but there |
|
86 # is no capability signaling it. |
|
87 "HG20": (), # special-cased below |
|
88 "HG10UN": ("HG10UN", None), |
|
89 "HG10BZ": ("HG10", 'BZ'), |
|
90 "HG10GZ": ("HG10GZ", 'GZ'), |
|
91 } |
|
92 |
|
93 # hgweb uses this list to communicate its preferred type |
|
94 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN'] |
|
95 |
82 |
96 def writechunks(ui, chunks, filename, vfs=None): |
83 def writechunks(ui, chunks, filename, vfs=None): |
97 """Write chunks to a file and return its filename. |
84 """Write chunks to a file and return its filename. |
98 |
85 |
99 The stream is assumed to be a bundle file. |
86 The stream is assumed to be a bundle file. |
122 if cleanup is not None: |
109 if cleanup is not None: |
123 if filename and vfs: |
110 if filename and vfs: |
124 vfs.unlink(cleanup) |
111 vfs.unlink(cleanup) |
125 else: |
112 else: |
126 os.unlink(cleanup) |
113 os.unlink(cleanup) |
127 |
|
128 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None): |
|
129 """Write a bundle file and return its filename. |
|
130 |
|
131 Existing files will not be overwritten. |
|
132 If no filename is specified, a temporary file is created. |
|
133 bz2 compression can be turned off. |
|
134 The bundle file will be deleted in case of errors. |
|
135 """ |
|
136 |
|
137 if bundletype == "HG20": |
|
138 from . import bundle2 |
|
139 bundle = bundle2.bundle20(ui) |
|
140 bundle.setcompression(compression) |
|
141 part = bundle.newpart('changegroup', data=cg.getchunks()) |
|
142 part.addparam('version', cg.version) |
|
143 chunkiter = bundle.getchunks() |
|
144 else: |
|
145 # compression argument is only for the bundle2 case |
|
146 assert compression is None |
|
147 if cg.version != '01': |
|
148 raise error.Abort(_('old bundle types only supports v1 ' |
|
149 'changegroups')) |
|
150 header, comp = bundletypes[bundletype] |
|
151 if comp not in util.compressors: |
|
152 raise error.Abort(_('unknown stream compression type: %s') |
|
153 % comp) |
|
154 z = util.compressors[comp]() |
|
155 subchunkiter = cg.getchunks() |
|
156 def chunkiter(): |
|
157 yield header |
|
158 for chunk in subchunkiter: |
|
159 yield z.compress(chunk) |
|
160 yield z.flush() |
|
161 chunkiter = chunkiter() |
|
162 |
|
163 # parse the changegroup data, otherwise we will block |
|
164 # in case of sshrepo because we don't know the end of the stream |
|
165 |
|
166 # an empty chunkgroup is the end of the changegroup |
|
167 # a changegroup has at least 2 chunkgroups (changelog and manifest). |
|
168 # after that, an empty chunkgroup is the end of the changegroup |
|
169 return writechunks(ui, chunkiter, filename, vfs=vfs) |
|
170 |
114 |
171 class cg1unpacker(object): |
115 class cg1unpacker(object): |
172 """Unpacker for cg1 changegroup streams. |
116 """Unpacker for cg1 changegroup streams. |
173 |
117 |
174 A changegroup unpacker handles the framing of the revision data in |
118 A changegroup unpacker handles the framing of the revision data in |