Skip to content

Instantly share code, notes, and snippets.

@minux
Last active August 29, 2015 14:11
Show Gist options
  • Save minux/d62517ba8096c241fdd8 to your computer and use it in GitHub Desktop.
Save minux/d62517ba8096c241fdd8 to your computer and use it in GitHub Desktop.
convert Go repository from hg to git
Apply this to git-2.2.0 release.
--- git-2.2.0/fast-import.c 2014-11-26 17:39:03.000000000 -0500
+++ git-2.2.0-go/fast-import.c 2014-12-09 03:18:31.522938005 -0500
@@ -2673,6 +2673,7 @@
struct branch *b;
char *author = NULL;
char *committer = NULL;
+ char *golang_hg = NULL;
struct hash_list *merge_list = NULL;
unsigned int merge_count;
unsigned char prev_fanout, new_fanout;
@@ -2692,6 +2693,10 @@
committer = parse_ident(v);
read_next_command();
}
+ if (skip_prefix(command_buf.buf, "golang-hg ", &v)) {
+ golang_hg = strdup(v);
+ read_next_command();
+ }
if (!committer)
die("Expected committer but didn't get one");
parse_data(&msg, 0, NULL);
@@ -2754,11 +2759,15 @@
strbuf_addf(&new_data,
"author %s\n"
"committer %s\n"
- "\n",
+ ,//"\n",
author ? author : committer, committer);
+ if (golang_hg != NULL)
+ strbuf_addf(&new_data, "golang-hg %s\n", golang_hg);
+ strbuf_addf(&new_data, "\n");
strbuf_addbuf(&new_data, &msg);
free(author);
free(committer);
+ free(golang_hg);
if (!store_object(OBJ_COMMIT, &new_data, NULL, b->sha1, next_mark))
b->pack_id = pack_id;
Apply this to git://repo.or.cz/fast-export.git
diff --git a/hg-fast-export.py b/hg-fast-export.py
index 0c683c5..d80663d 100755
--- a/hg-fast-export.py
+++ b/hg-fast-export.py
@@ -163,7 +163,7 @@ def sanitize_name(name,what="branch"):
sys.stderr.write('Warning: sanitized %s [%s] to [%s]\n' % (what,name,n))
return n
-def export_commit(ui,repo,revision,old_marks,max,count,authors,sob,brmap,hgtags,notes,encoding=''):
+def export_commit(ui,repo,revision,old_marks,max,count,authors,sob,brmap,hgtags,notes,encoding='',isMainRepo=True):
def get_branchname(name):
if brmap.has_key(name):
return brmap[name]
@@ -182,9 +182,27 @@ def export_commit(ui,repo,revision,old_marks,max,count,authors,sob,brmap,hgtags,
wr('commit refs/heads/%s' % branch)
wr('mark :%d' % (revision+1))
- if sob:
- wr('author %s %d %s' % (get_author(desc,user,authors),time,timezone))
+ #if sob:
+ # wr('author %s %d %s' % (get_author(desc,user,authors),time,timezone))
+ # extract committer and remove '\nCommitter: xxxx <xxx@...>'
+ wr('author %s %d %s' % (user,time,timezone))
+ lastnl = desc.rfind('\nCommitter: ')
+ if lastnl >= 0:
+ end = desc[lastnl+12:].find('\n')
+ if end < 0:
+ user = desc[lastnl+12:]
+ else:
+ user = desc[lastnl+12:lastnl+12+end]
+ desc = re.sub('\nCommitter: ([^\n]*)', '', desc)
+ if desc[-1] == '\n': desc = desc[:-1]
wr('committer %s %d %s' % (user,time,timezone))
+ golang_hg = ''.join(map(lambda x: '%02x' % ord(x), revnode)); wr('golang-hg %s' % golang_hg)
+ # replace "^\s*[fF]ixes/Updates? [Ii]ssue %d" with "\s*[fF]ixes #%d"
+ desc = re.sub(r'^((?:\s*[fF]ixes)|(?:\s*[Uu]pdates?)) [Ii]ssue ([0-9]+)', (r'\1 #\2' if isMainRepo else r'\1 golang/go#\2'), desc, 0, re.MULTILINE)
+ # replace "https?://codereview.appspot.com/" with "https://golang.org/cl/"
+ desc = re.sub(r'https?://codereview.appspot.com/', r'https://golang.org/cl/', desc, 0, re.MULTILINE)
+ # replace "\n\n\n+" with "\n\n"
+ desc = re.sub('\n\n\n+', '\n\n', desc)
wr('data %d' % (len(desc)+1)) # wtf?
wr(desc)
wr()
@@ -357,11 +375,16 @@ def hg2git(repourl,m,marksfile,mappingfile,headsfile,tipfile,authors={},sob=Fals
(revnode,_,_,_,_,_,_,_)=get_changeset(ui,repo,rev,authors)
mapping_cache[revnode.encode('hex_codec')] = str(rev)
+ isMainRepo = False
+ l=repo.tagslist()
+ for tag,node in l:
+ if tag == 'weekly.2009-11-10.1': isMainRepo = True
+ sys.stderr.write("isMainRepo = %s" % isMainRepo)
c=0
brmap={}
for rev in range(min,max):
- c=export_commit(ui,repo,rev,old_marks,max,c,authors,sob,brmap,hgtags,notes,encoding)
+ c=export_commit(ui,repo,rev,old_marks,max,c,authors,sob,brmap,hgtags,notes,encoding,isMainRepo)
state_cache['tip']=max
state_cache['repo']=repourl
diff --git a/hg-fast-export.sh b/hg-fast-export.sh
index 05bbec9..d365ef7 100755
--- a/hg-fast-export.sh
+++ b/hg-fast-export.sh
@@ -111,7 +111,7 @@ $(
} | \
{
_e2=0
- git fast-import $GFI_OPTS --export-marks="$GIT_DIR/$PFX-$SFX_MARKS.tmp" 3>&- || _e2=$?
+ git-fast-import $GFI_OPTS --export-marks="$GIT_DIR/$PFX-$SFX_MARKS.tmp" 3>&- || _e2=$?
echo $_e2 >&3
}
)
diff --git a/hg2git.py b/hg2git.py
index c58cade..04f287a 100755
--- a/hg2git.py
+++ b/hg2git.py
@@ -13,7 +13,7 @@ cfg_master='master'
# default origin name
origin_name=''
# silly regex to see if user field has email address
-user_re=re.compile('([^<]+) (<[^>]*>)$')
+user_re=re.compile('([^<]*[^ <]) ?(<[^>]*>)$')
# silly regex to clean out user names
user_clean_re=re.compile('^["]([^"]+)["]$')
assume the patched git is in git-2.2.0/, patched fast-export is at fast-export/ (git://repo.or.cz/fast-export.git)
The conversion command line is:
mkdir target
cd target
git init
PATH=../git-2.2.0:$PATH ../fast-export/hg-fast-export.sh -r /path/to/hg/repo --hgtags # --hgtags is very important.
Caveats:
Because during the history of go, there used to exist these two files:
lib/godoc/dirlist.html and lib/godoc/dirList.html
Please do NOT do the conversion on a case-insensitive file system (e.g. default HFS+ on OS X).
Otherwise you won't be able to get git commit 5de21eb1e93393cb5f07f5f5f0c32ac76c33d135 right.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment