From 0f49bfe0db104de99d4ae773f033cc7bc4d4e2b3 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Fri, 22 Nov 2019 08:48:44 -0800 Subject: [PATCH 1/3] Move hg sub-module updating to its own function, NFC This refactoring is in preparation to supporting Mercurial submodules which are git repositories. --- hg-fast-export.py | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/hg-fast-export.py b/hg-fast-export.py index f46d85e..ab9f60d 100755 --- a/hg-fast-export.py +++ b/hg-fast-export.py @@ -141,33 +141,37 @@ def remove_gitmodules(ctx): wr('D %s' % submodule) wr('D .gitmodules') +def refresh_hg_submodule(name,subrepo_info): + gitRepoLocation=submodule_mappings[name] + "/.git" + + # Populate the cache to map mercurial revision to git revision + if not name in subrepo_cache: + subrepo_cache[name]=(load_cache(gitRepoLocation+"/hg2git-mapping"), + load_cache(gitRepoLocation+"/hg2git-marks", + lambda s: int(s)-1)) + + (mapping_cache,marks_cache)=subrepo_cache[name] + subrepo_hash=subrepo_info[1] + if subrepo_hash in mapping_cache: + revnum=mapping_cache[subrepo_hash] + gitSha=marks_cache[int(revnum)] + wr('M 160000 %s %s' % (gitSha,name)) + sys.stderr.write("Adding/updating submodule %s, revision %s->%s\n" + % (name,subrepo_hash,gitSha)) + return '[submodule "%s"]\n\tpath = %s\n\turl = %s\n' % (name,name, + submodule_mappings[name]) + else: + sys.stderr.write("Warning: Could not find hg revision %s for %s in git %s\n" % + (subrepo_hash,name,gitRepoLocation)) + return '' + def refresh_gitmodules(ctx): """Updates list of ctx submodules according to .hgsubstate file""" remove_gitmodules(ctx) gitmodules="" # Create the .gitmodules file and all submodules for name,subrepo_info in ctx.substate.items(): - gitRepoLocation=submodule_mappings[name] + "/.git" - - # Populate the cache to map mercurial revision to git revision - if not name in subrepo_cache: - subrepo_cache[name]=(load_cache(gitRepoLocation+"/hg2git-mapping"), - load_cache(gitRepoLocation+"/hg2git-marks", - lambda s: int(s)-1)) - - (mapping_cache,marks_cache)=subrepo_cache[name] - subrepo_hash=subrepo_info[1] - if subrepo_hash in mapping_cache: - revnum=mapping_cache[subrepo_hash] - gitSha=marks_cache[int(revnum)] - wr('M 160000 %s %s' % (gitSha,name)) - sys.stderr.write("Adding/updating submodule %s, revision %s->%s\n" - % (name,subrepo_hash,gitSha)) - gitmodules+='[submodule "%s"]\n\tpath = %s\n\turl = %s\n' % (name,name, - submodule_mappings[name]) - else: - sys.stderr.write("Warning: Could not find hg revision %s for %s in git %s\n" % - (subrepo_hash,name,gitRepoLocation)) + gitmodules+=refresh_hg_submodule(name,subrepo_info) if len(gitmodules): wr('M 100644 inline .gitmodules') From acf93a80a9e1b07c9158220c22aef3fcb8a1dd11 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Sat, 7 Dec 2019 10:21:26 -0800 Subject: [PATCH 2/3] Only export submodules that exist in the submodule mapping. --- hg-fast-export.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hg-fast-export.py b/hg-fast-export.py index ab9f60d..b7becbc 100755 --- a/hg-fast-export.py +++ b/hg-fast-export.py @@ -171,7 +171,8 @@ def refresh_gitmodules(ctx): gitmodules="" # Create the .gitmodules file and all submodules for name,subrepo_info in ctx.substate.items(): - gitmodules+=refresh_hg_submodule(name,subrepo_info) + if name in submodule_mappings: + gitmodules+=refresh_hg_submodule(name,subrepo_info) if len(gitmodules): wr('M 100644 inline .gitmodules') From ab31fdcbaa930105bb784b61cf0af92657f49f8b Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Fri, 22 Nov 2019 08:52:43 -0800 Subject: [PATCH 3/3] Add support for git submodules Mercurial supports not only submodules which are Mercurial repositories, but also Git and Subversion repositories. This patch adds support for submodules which are Git repositories to hg-fast-export. As submodules which are Git repositories won't need a mapping file we trigger the submodule update only on the occurence of the `.hgsubstate` file and push the check for a valid `submodule_mappings` to `refresh_gitmodules(ctx)` --- README-SUBMODULES.md | 20 +++++++++++++++----- hg-fast-export.py | 13 +++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/README-SUBMODULES.md b/README-SUBMODULES.md index f55797a..412e513 100644 --- a/README-SUBMODULES.md +++ b/README-SUBMODULES.md @@ -2,11 +2,21 @@ ## Introduction -Subrepositories must first be converted in order for the conversion of -the super repository to know how hg commits map to git commits in the -sub repositories. When all subrepositories have been converted, a -mapping file that maps the mercurial subrepository path to a converted -git submodule path must be created. The format for this file is: +hg-fast-export supports migrating mercurial subrepositories in the +repository being converted into git submodules in the converted repository. + +Git submodules must be git repositories while mercurial's subrepositories can +be git, mercurial or subversion repositories. hg-fast-export will handle any +git subrepositories automatically, any other kinds must first be converted +to git repositories. Currently hg-fast-export does not support the conversion +of subversion subrepositories. The rest of this page covers the conversion of +mercurial subrepositories which require some manual steps: + +The first step for mercurial subrepositories involves converting the +subrepository into a git repository using hg-fast-export. When all +subrepositories have been converted, a mapping file that maps the mercurial +subrepository path to a converted git submodule path must be created. The +format for this file is: ""="" ""="" diff --git a/hg-fast-export.py b/hg-fast-export.py index b7becbc..8e3449a 100755 --- a/hg-fast-export.py +++ b/hg-fast-export.py @@ -141,6 +141,13 @@ def remove_gitmodules(ctx): wr('D %s' % submodule) wr('D .gitmodules') +def refresh_git_submodule(name,subrepo_info): + wr('M 160000 %s %s' % (subrepo_info[1],name)) + sys.stderr.write("Adding/updating submodule %s, revision %s\n" + % (name,subrepo_info[1])) + return '[submodule "%s"]\n\tpath = %s\n\turl = %s\n' % (name,name, + subrepo_info[0]) + def refresh_hg_submodule(name,subrepo_info): gitRepoLocation=submodule_mappings[name] + "/.git" @@ -171,7 +178,9 @@ def refresh_gitmodules(ctx): gitmodules="" # Create the .gitmodules file and all submodules for name,subrepo_info in ctx.substate.items(): - if name in submodule_mappings: + if subrepo_info[2]=='git': + gitmodules+=refresh_git_submodule(name,subrepo_info) + elif submodule_mappings and name in submodule_mappings: gitmodules+=refresh_hg_submodule(name,subrepo_info) if len(gitmodules): @@ -183,7 +192,7 @@ def export_file_contents(ctx,manifest,files,hgtags,encoding='',plugins={}): count=0 max=len(files) for file in files: - if submodule_mappings and file==".hgsubstate": + if file==".hgsubstate": refresh_gitmodules(ctx) # Skip .hgtags files. They only get us in trouble. if not hgtags and file == ".hgtags":