G'day,
I modified that script to convert a number of our repositories in February. The version below worked for me at the time, but I'm not able to test it now as our BK license has expired. In particular I'm not sure if the bk_info.split line is correct; I had a reduced form of this line in the file which now looks obviously wrong.
The script is slow; most of the time is in the bk export for every revision. There are probably dumb things in there; I don't know python and I was just starting with git.
Changes from the version I downloaded from the web include:
- sundry changes to make it work for me
- separate committers file to translate user names to full names
- specify a git dir template
- copy tags from BK
- minimal conversion of ignore files
- increased recursion limit to handle large number of commits
I hope this is useful to someone.
regards, David.
--snip,snip-- # Convert a BK repository to GIT # usage: bk2git BK_REPO [GIT_REPO] # Single branch only.
import os import time import sys
sys.setrecursionlimit(10000);
templates_dir = "/tmp/bk2git/templates" committers_file = "/tmp/bk2git/committers" tmp_dir = "/tmp/bk-export%d" % os.getpid()
# Get repository locations.
if len(sys.argv) < 2 or len(sys.argv) > 3:
print "usage: bk2git BK_REPO [GIT_REPO]"
sys.exit(1);bk_dir = sys.argv[1]
if len(sys.argv) == 3:
git_dir = sys.argv[2]
else:
git_dir = bk_dir + ".git"print "BK " + bk_dir print "GIT " + git_dir
# Get committer names.
f = file(committers_file, "r")
committers = {}
for line in f:
[m,n] = line.split(" ",1)
committers[m] = n.strip();
f.close()# Get tree of commits.
f = os.popen("cd %s; bk prs -d':REV:\\t:PARENT:\\t:MPARENT:\\t\\n' ChangeSet" % bk_dir)
f.readline()
parents={}
for rev in f:
[n,p] = rev.rstrip().split("\t",1)
parents[n] = p.split("\t")
f.close()# Get tags.
f = os.popen("cd %s; bk changes -t -n -d':I:\\t:TAG:'" % bk_dir)
tags={}
for rev in f:
[n,t] = rev.rstrip().split("\t",1)
tags[n] = t
f.close()# Initialize git repository. os.system("mkdir %s" % git_dir) os.chdir(git_dir) os.system("git --bare init --template=%s" % templates_dir) os.system("git-config core.bare false")
unknown = {}
def get_name(email):
if committers.has_key(email):
return committers[email]
unknown[email] = True
return "*Unknown*"def git_commit(rev, p):
os.chdir(tmp_dir)
os.symlink(git_dir, "%s/.git" % tmp_dir)
# os.system("pwd; ls -AlR")
os.system("git-ls-files -z --deleted | xargs -0 git-update-index --remove")
os.system("git-ls-files -z --others | xargs -0 git-update-index --add")
os.system("git-ls-files -z | xargs -0 git-update-index")
treeid = os.popen("git-write-tree").read().rstrip()
print "wrote tree as %s" % treeid
os.chdir(git_dir)
os.system("rm -Rf %s" % tmp_dir) bk_info = os.popen("cd %s; bk prs -r%s -d':KEY:\\n:UTC:\\n:USER:@:HOST:\\n$each(:C:){:C\\n}\\n' ChangeSet | sed 1d" % (bk_dir, rev)).read() [key, date, user, comments] = bk_info.split("\n", 3)
# [key, date, user] = bk_info.split("\n", 2)
[name, machine] = user.split("@", 1);
f = file("/tmp/git-comments","w")
f.write(comments)
f.write("BK KEY: %s\n" % key)
f.close()
sdate = str(int(time.mktime(time.strptime(date+" UTC", "%Y%m%d%H%M%S %Z"))))
os.putenv("GIT_AUTHOR_DATE", sdate)
os.putenv("GIT_AUTHOR_EMAIL", user)
os.putenv("GIT_AUTHOR_NAME", get_name(name))
os.putenv("GIT_COMMITTER_DATE", sdate)
os.putenv("GIT_COMMITTER_EMAIL", user)
os.putenv("GIT_COMMITTER_NAME", get_name(name))
commitid = os.popen("git-commit-tree %s %s < /tmp/git-comments" % (treeid, " ".join(["-p "+a for a in p]))).read().rstrip()
print "committed %s as %s" % (rev, commitid) if tags.has_key(rev):
os.system("git-tag %s %s" % (tags[rev], commitid))
print "tagged %s" % tags[rev] return commitid
os.system("mkdir %s; touch %s/initial" % (tmp_dir, tmp_dir)) resolved = {'1.1': git_commit("1.1",[])}
def res(ver):
if resolved.has_key(ver):
return
for v in parents[ver]:
res(v) os.system("cd %s; bk export -r%s %s" % (bk_dir, ver, tmp_dir))
ignore = "%s/.gitignore" % tmp_dir
os.system("cd %s; bk co -kpq -r@%s BitKeeper/etc/ignore | sed '/^BitKeeper/d;/^PENDING/d' > %s" % (bk_dir, ver, ignore))
os.system("test -s %s || rm %s" % (ignore, ignore)) resolved[ver] = git_commit(ver, [resolved[v] for v in parents[ver]])
return resolved[ver]tot = os.popen("cd %s; bk prs -r+ -d':REV:' ChangeSet | tail -n 1" % bk_dir).read() print "Exporting bitkeeper up to version %s" % tot
HEAD = res(tot) print "HEAD: %s" % HEAD file("%s/refs/heads/master" % git_dir,"w").write(HEAD + "\n") os.system("git-config core.bare true") os.system("git gc") print unknown.keys() --snip,snip--