Mercurial > hg
diff contrib/convert-repo @ 3938:0fab73b3f453
convert-repo: add some smarts
autodetect source and destination repo types
autodetect read and write capabilities of converters
default destination directory (<src>-hg)
default map file (<dest>/.hg/shamap)
more verbose by default
add a -q switch
add IO functions
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 20 Dec 2006 16:31:46 -0600 |
parents | 645e1dd4b8ae |
children | b58c1681d23b |
line wrap: on
line diff
--- a/contrib/convert-repo Wed Dec 20 13:11:35 2006 -0600 +++ b/contrib/convert-repo Wed Dec 20 16:31:46 2006 -0600 @@ -22,10 +22,20 @@ # be run repeatedly to copy new commits. import sys, os, zlib, sha, time +os.environ["HGENCODING"] = "utf-8" +from mercurial import hg, ui, util, fancyopts -os.environ["HGENCODING"] = "utf-8" +class Abort(Exception): pass + +quiet = 0 +def status(msg): + if not quiet: sys.stdout.write(str(msg)) -from mercurial import hg, ui, util +def warn(msg): + sys.stderr.write(str(msg)) + +def abort(msg): + raise Abort(msg) def recode(s): try: @@ -38,7 +48,11 @@ class convert_git: def __init__(self, path): + if os.path.isdir(path + "/.git"): + path += "/.git" self.path = path + if not os.path.exists(path + "/HEAD"): + raise TypeError("couldn't open GIT repo %s" % path) def getheads(self): fh = os.popen("GIT_DIR=%s git-rev-parse --verify HEAD" % self.path) @@ -110,7 +124,13 @@ def __init__(self, path): self.path = path u = ui.ui() - self.repo = hg.repository(u, path) + try: + self.repo = hg.repository(u, path) + except: + raise TypeError("could open hg repo %s" % path) + + def mapfile(self): + return os.path.join(self.path, ".hg", "shamap") def getheads(self): h = self.repo.changelog.heads() @@ -170,7 +190,7 @@ newlines.sort() if newlines != oldlines: - #print "updating tags" + status("updating tags\n") f = self.repo.wfile(".hgtags", "w") f.write("".join(newlines)) f.close() @@ -180,8 +200,21 @@ date, self.repo.changelog.tip(), hg.nullid) return hg.hex(self.repo.changelog.tip()) +converters = [convert_git, convert_mercurial] + +def converter(path): + if not os.path.isdir(path): + abort("%s: not a directory\n" % path) + for c in converters: + try: + return c(path) + except TypeError: + pass + abort("%s: unknown repository type\n" % path) + class convert: def __init__(self, source, dest, mapfile): + self.source = source self.dest = dest self.mapfile = mapfile @@ -272,17 +305,20 @@ file(self.mapfile, "a").write("%s %s\n" % (rev, self.map[rev])) def convert(self): + status("scanning source...\n") heads = self.source.getheads() parents = self.walktree(heads) + status("sorting...\n") t = self.toposort(parents) t = [n for n in t if n not in self.map] num = len(t) c = None + status("converting...\n") for c in t: num -= 1 desc = self.commitcache[c][3].splitlines()[0] - #print num, desc + status("%d %s\n" % (num, desc)) self.copy(c) tags = self.source.gettags() @@ -299,9 +335,40 @@ if nrev: file(self.mapfile, "a").write("%s %s\n" % (c, nrev)) -gitpath, hgpath, mapfile = sys.argv[1:] -if os.path.isdir(gitpath + "/.git"): - gitpath += "/.git" +def command(src, dest=None, mapfile=None, **opts): + srcc = converter(src) + if not hasattr(srcc, "getcommit"): + abort("%s: can't read from this repo type\n" % src) + + if not dest: + dest = src + "-hg" + status("assuming destination %s\n" % dest) + if not os.path.isdir(dest): + status("creating repository %s\n" % dest) + os.system("hg init " + dest) + destc = converter(dest) + if not hasattr(destc, "putcommit"): + abort("%s: can't write to this repo type\n" % src) -c = convert(convert_git(gitpath), convert_mercurial(hgpath), mapfile) -c.convert() + if not mapfile: + try: + mapfile = destc.mapfile() + except: + mapfile = os.path.join(destc, "map") + + c = convert(srcc, destc, mapfile) + c.convert() + +options = [('q', 'quiet', None, 'suppress output')] +opts = {} +args = fancyopts.fancyopts(sys.argv[1:], options, opts) + +if opts['quiet']: + quiet = 1 + +try: + command(*args, **opts) +except Abort, inst: + warn(inst) +except KeyboardInterrupt: + status("interrupted\n")