4 # |
4 # |
5 # This software may be used and distributed according to the terms of the |
5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
7 |
7 |
8 from i18n import _ |
8 from i18n import _ |
9 from node import nullrev |
9 from node import nullrev, hex |
10 import mdiff, util, dagutil |
10 import mdiff, util, dagutil |
11 import struct, os, bz2, zlib, tempfile |
11 import struct, os, bz2, zlib, tempfile |
12 |
12 |
13 _BUNDLE10_DELTA_HEADER = "20s20s20s20s" |
13 _BUNDLE10_DELTA_HEADER = "20s20s20s20s" |
14 |
14 |
223 raise util.Abort(_('%s: unknown bundle version %s') % (fname, version)) |
223 raise util.Abort(_('%s: unknown bundle version %s') % (fname, version)) |
224 return unbundle10(fh, alg) |
224 return unbundle10(fh, alg) |
225 |
225 |
226 class bundle10(object): |
226 class bundle10(object): |
227 deltaheader = _BUNDLE10_DELTA_HEADER |
227 deltaheader = _BUNDLE10_DELTA_HEADER |
228 def __init__(self, bundlecaps=None): |
228 def __init__(self, repo, bundlecaps=None): |
|
229 """Given a source repo, construct a bundler. |
|
230 |
|
231 bundlecaps is optional and can be used to specify the set of |
|
232 capabilities which can be used to build the bundle. |
|
233 """ |
229 # Set of capabilities we can use to build the bundle. |
234 # Set of capabilities we can use to build the bundle. |
230 if bundlecaps is None: |
235 if bundlecaps is None: |
231 bundlecaps = set() |
236 bundlecaps = set() |
232 self._bundlecaps = bundlecaps |
237 self._bundlecaps = bundlecaps |
|
238 self._changelog = repo.changelog |
|
239 self._manifest = repo.manifest |
|
240 reorder = repo.ui.config('bundle', 'reorder', 'auto') |
|
241 if reorder == 'auto': |
|
242 reorder = None |
|
243 else: |
|
244 reorder = util.parsebool(reorder) |
|
245 self._repo = repo |
|
246 self._reorder = reorder |
|
247 self.count = [0, 0] |
233 def start(self, lookup): |
248 def start(self, lookup): |
234 self._lookup = lookup |
249 self._lookup = lookup |
235 def close(self): |
250 def close(self): |
236 return closechunk() |
251 return closechunk() |
237 |
252 |
274 for c in self.revchunk(revlog, curr, prev): |
289 for c in self.revchunk(revlog, curr, prev): |
275 yield c |
290 yield c |
276 |
291 |
277 yield self.close() |
292 yield self.close() |
278 |
293 |
|
294 def generate(self, clnodes, getmfnodes, getfiles, getfilenodes, source): |
|
295 '''yield a sequence of changegroup chunks (strings)''' |
|
296 repo = self._repo |
|
297 cl = self._changelog |
|
298 mf = self._manifest |
|
299 reorder = self._reorder |
|
300 progress = repo.ui.progress |
|
301 count = self.count |
|
302 _bundling = _('bundling') |
|
303 |
|
304 count[:] = [0, len(clnodes)] |
|
305 for chunk in self.group(clnodes, cl, reorder=reorder): |
|
306 yield chunk |
|
307 progress(_bundling, None) |
|
308 |
|
309 for chunk in self.group(getmfnodes(), mf, reorder=reorder): |
|
310 yield chunk |
|
311 progress(_bundling, None) |
|
312 |
|
313 changedfiles = getfiles() |
|
314 count[:] = [0, len(changedfiles)] |
|
315 for fname in sorted(changedfiles): |
|
316 filerevlog = repo.file(fname) |
|
317 if not len(filerevlog): |
|
318 raise util.Abort(_("empty or missing revlog for %s") |
|
319 % fname) |
|
320 nodelist = getfilenodes(fname, filerevlog) |
|
321 if nodelist: |
|
322 count[0] += 1 |
|
323 yield self.fileheader(fname) |
|
324 for chunk in self.group(nodelist, filerevlog, reorder): |
|
325 yield chunk |
|
326 yield self.close() |
|
327 progress(_bundling, None) |
|
328 |
|
329 if clnodes: |
|
330 repo.hook('outgoing', node=hex(clnodes[0]), source=source) |
279 |
331 |
280 def revchunk(self, revlog, rev, prev): |
332 def revchunk(self, revlog, rev, prev): |
281 node = revlog.node(rev) |
333 node = revlog.node(rev) |
282 p1, p2 = revlog.parentrevs(rev) |
334 p1, p2 = revlog.parentrevs(rev) |
283 base = prev |
335 base = prev |