# HG changeset patch # User mpm@selenic.com # Date 1126168045 25200 # Node ID cde6818e082ac823f13d769cd39854cf1d97261b # Parent f1895785c79e4156715ce5a19884c2cf50c8c21b Add preliminary support for the bundle and unbundle commands diff -r f1895785c79e -r cde6818e082a doc/hg.1.txt --- a/doc/hg.1.txt Thu Sep 08 00:13:52 2005 -0700 +++ b/doc/hg.1.txt Thu Sep 08 01:27:25 2005 -0700 @@ -106,6 +106,21 @@ -c, --changeset list the changeset -n, --number list the revision number (default) +bundle :: + (EXPERIMENTAL) + + Generate a compressed changegroup file collecting all changesets + not found in the other repository. + + This file can then be transferred using conventional means and + applied to another repository with the unbundle command. This is + useful when native push and pull are not available or when + exporting an entire repository is undesirable. The standard file + extension is ".hg". + + Unlike import/export, this exactly preserves all changeset + contents including permissions, rename data, and revision history. + cat [revision]:: Output to stdout the given revision for the specified file. @@ -512,6 +527,12 @@ tip:: Show the tip revision. +unbundle :: + (EXPERIMENTAL) + + Apply a compressed changegroup file generated by the bundle + command. + undo:: Undo the last commit or pull transaction. diff -r f1895785c79e -r cde6818e082a mercurial/commands.py --- a/mercurial/commands.py Thu Sep 08 00:13:52 2005 -0700 +++ b/mercurial/commands.py Thu Sep 08 01:27:25 2005 -0700 @@ -7,10 +7,10 @@ from demandload import demandload from node import * -demandload(globals(), "os re sys signal shutil imp") +demandload(globals(), "os re sys signal shutil imp urllib") demandload(globals(), "fancyopts ui hg util lock revlog") demandload(globals(), "fnmatch hgweb mdiff random signal time traceback") -demandload(globals(), "errno socket version struct atexit sets") +demandload(globals(), "errno socket version struct atexit sets bz2") class UnknownCommand(Exception): """Exception raised if command is not in the command table.""" @@ -549,6 +549,26 @@ for p, l in zip(zip(*pieces), lines): ui.write("%s: %s" % (" ".join(p), l[1])) +def bundle(ui, repo, fname, dest="default-push", **opts): + """create a changegroup file""" + f = open(fname, "wb") + dest = ui.expandpath(dest) + other = hg.repository(ui, dest) + o = repo.findoutgoing(other) + cg = repo.changegroup(o) + + try: + f.write("HG10") + z = bz2.BZ2Compressor(9) + while 1: + chunk = cg.read(4096) + if not chunk: + break + f.write(z.compress(chunk)) + f.write(z.flush()) + except: + os.unlink(fname) + def cat(ui, repo, file1, rev=None, **opts): """output the latest or given revision of a file""" r = repo.file(relpath(repo, [file1])[0]) @@ -1534,6 +1554,30 @@ n = repo.changelog.tip() show_changeset(ui, repo, changenode=n) +def unbundle(ui, repo, fname): + f = urllib.urlopen(fname) + + if f.read(4) != "HG10": + ui.warn("abort: not a Mercurial bundle file!\n") + return -1 + + class bzread: + def __init__(self, f): + self.zd = bz2.BZ2Decompressor() + self.f = f + self.buf = "" + def read(self, l): + while l > len(self.buf): + r = self.f.read(4096) + if r: + self.buf += self.zd.decompress(r) + else: + break + d, self.buf = self.buf[:l], self.buf[l:] + return d + + repo.addchangegroup(bzread(f)) + def undo(ui, repo): """undo the last commit or pull @@ -1610,6 +1654,10 @@ ('I', 'include', [], 'include path in search'), ('X', 'exclude', [], 'exclude path from search')], 'hg annotate [OPTION]... FILE...'), + "bundle": + (bundle, + [], + 'hg bundle FILE DEST'), "cat": (cat, [('o', 'output', "", 'output to file')], @@ -1776,6 +1824,10 @@ 'hg tag [OPTION]... NAME [REV]'), "tags": (tags, [], 'hg tags'), "tip": (tip, [], 'hg tip'), + "unbundle": + (unbundle, + [], + 'hg unbundle FILE'), "undo": (undo, [], 'hg undo'), "^update|up|checkout|co": (update, diff -r f1895785c79e -r cde6818e082a mercurial/revlog.py --- a/mercurial/revlog.py Thu Sep 08 00:13:52 2005 -0700 +++ b/mercurial/revlog.py Thu Sep 08 01:27:25 2005 -0700 @@ -604,8 +604,8 @@ link = linkmapper(cs) if node in self.nodemap: # this can happen if two branches make the same change - if unique: - raise RevlogError("already have %s" % hex(node[:4])) + # if unique: + # raise RevlogError("already have %s" % hex(node[:4])) chain = node continue delta = chunk[80:]