Mercurial > hg-stable
changeset 3952:32c1653b7dad
merge with crew
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Fri, 22 Dec 2006 22:53:16 +0100 |
parents | cb66641cdee3 (current diff) 6257030134f4 (diff) |
children | fad134931327 a8eb050c6489 |
files | |
diffstat | 1 files changed, 87 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/convert-repo Fri Dec 22 22:51:39 2006 +0100 +++ b/contrib/convert-repo Fri Dec 22 22:53:16 2006 +0100 @@ -3,29 +3,41 @@ # This is a generalized framework for converting between SCM # repository formats. # -# In its current form, it's hardcoded to convert incrementally between -# git and Mercurial. -# # To use, run: # -# convert-repo <git-dir> <hg-dir> <mapfile> +# convert-repo <source> [<dest> [<mapfile>]] # -# (don't forget to create the <hg-dir> repository beforehand) +# Currently accepted source formats: git +# Currently accepted destination formats: hg # -# The <mapfile> is a simple text file that maps a git commit hash to -# the hash in Mercurial for that version, like so: +# If destination isn't given, a new Mercurial repo named <src>-hg will +# be created. If <mapfile> isn't given, it will be put in a default +# location (<dest>/.hg/shamap by default) # -# <git hash> <mercurial hash> +# The <mapfile> is a simple text file that maps each source commit ID to +# the destination ID for that revision, like so: +# +# <source ID> <destination ID> # # If the file doesn't exist, it's automatically created. It's updated # on each commit copied, so convert-repo can be interrupted and can # 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 +50,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 +126,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 +192,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 +202,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 +307,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 +337,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")