mirror of
https://github.com/frej/fast-export.git
synced 2025-11-03 17:55:49 +01:00
Add support for mercurial subrepos
This adds a new command line option (--subrepo-map) that will map mercurial subrepos to git submodules. The --subrepo-map takes a mapping file as an argument that will be used to map a subrepo folder to a git submodule. For more information see the README-SUBMODULES.md. This commit is inspired by the changes made by daolis in PR#38 that was never merged. Closes: #51 Closes: #147
This commit is contained in:
committed by
Frej Drejhammar
parent
b51c58d3e0
commit
47d330de83
65
README-SUBMODULES.md
Normal file
65
README-SUBMODULES.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# How to convert Mercurial Repositories with subrepos
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
"<mercurial subrepo path>"="<git submodule path>"
|
||||||
|
"<mercurial subrepo path2>"="<git submodule path2>"
|
||||||
|
...
|
||||||
|
|
||||||
|
The path of this mapping file is then provided with the --subrepo-map
|
||||||
|
command line option.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Example mercurial repo folder structure (~/mercurial):
|
||||||
|
src/...
|
||||||
|
subrepo/subrepo1
|
||||||
|
subrepo/subrepo2
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
Create an empty new folder where all the converted git modules will be imported:
|
||||||
|
mkdir ~/imported-gits
|
||||||
|
cd ~/imported-gits
|
||||||
|
|
||||||
|
### Convert all submodules to git:
|
||||||
|
mkdir submodule1
|
||||||
|
cd submodule1
|
||||||
|
git init
|
||||||
|
hg-fast-export.sh -r ~/mercurial/subrepo1
|
||||||
|
cd ..
|
||||||
|
mkdir submodule2
|
||||||
|
cd submodule2
|
||||||
|
git init
|
||||||
|
hg-fast-export.sh -r ~/mercurial/subrepo2
|
||||||
|
|
||||||
|
### Create mapping file
|
||||||
|
cd ~/imported-gits
|
||||||
|
cat > submodule-mappings << EOF
|
||||||
|
"subrepo/subrepo1"="../submodule1"
|
||||||
|
"subrepo/subrepo2"="../submodule2"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
### Convert main repository
|
||||||
|
cd ~/imported-gits
|
||||||
|
mkdir git-main-repo
|
||||||
|
cd git-main-repo
|
||||||
|
git init
|
||||||
|
hg-fast-export.sh -r ~/mercurial --subrepo-map=../submodule-mappings
|
||||||
|
|
||||||
|
### Result
|
||||||
|
The resulting repository will now contain the subrepo/subrepo1 and
|
||||||
|
subrepo/subrepo1 submodules. The created .gitmodules file will look
|
||||||
|
like:
|
||||||
|
|
||||||
|
[submodule "subrepo/subrepo1"]
|
||||||
|
path = subrepo/subrepo1
|
||||||
|
url = ../submodule1
|
||||||
|
[submodule "subrepo/subrepo2"]
|
||||||
|
path = subrepo/subrepo2
|
||||||
|
url = ../submodule2
|
||||||
@@ -171,6 +171,11 @@ can be modified by any filter. `file_ctx` is the filecontext from the
|
|||||||
mercurial python library. After all filters have been run, the values
|
mercurial python library. After all filters have been run, the values
|
||||||
are used to add the file to the git commit.
|
are used to add the file to the git commit.
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
See README-SUBMODULES.md for how to convert subrepositories into git
|
||||||
|
submodules.
|
||||||
|
|
||||||
Notes/Limitations
|
Notes/Limitations
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ cfg_checkpoint_count=0
|
|||||||
# write some progress message every this many file contents written
|
# write some progress message every this many file contents written
|
||||||
cfg_export_boundary=1000
|
cfg_export_boundary=1000
|
||||||
|
|
||||||
|
subrepo_cache={}
|
||||||
|
submodule_mappings=None
|
||||||
|
|
||||||
def gitmode(flags):
|
def gitmode(flags):
|
||||||
return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
|
return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
|
||||||
|
|
||||||
@@ -128,6 +131,48 @@ def export_file_contents(ctx,manifest,files,hgtags,encoding='',plugins={}):
|
|||||||
count=0
|
count=0
|
||||||
max=len(files)
|
max=len(files)
|
||||||
for file in files:
|
for file in files:
|
||||||
|
if submodule_mappings and ctx.substate and file==".hgsubstate":
|
||||||
|
# Remove all submodules as we don't detect deleted submodules properly
|
||||||
|
# in any other way. We will add the ones not deleted back again below.
|
||||||
|
for module in submodule_mappings.keys():
|
||||||
|
wr('D %s' % module)
|
||||||
|
|
||||||
|
# Read .hgsubstate file in order to find the revision of each subrepo
|
||||||
|
data=ctx.filectx(file).data()
|
||||||
|
subHashes={}
|
||||||
|
for line in data.split('\n'):
|
||||||
|
if line.strip()=="":
|
||||||
|
continue
|
||||||
|
cols=line.split(' ')
|
||||||
|
subHashes[cols[1]]=cols[0]
|
||||||
|
|
||||||
|
gitmodules=""
|
||||||
|
# Create the .gitmodules file and all submodules
|
||||||
|
for name in ctx.substate:
|
||||||
|
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]
|
||||||
|
if subHashes[name] in mapping_cache:
|
||||||
|
revnum=mapping_cache[subHashes[name]]
|
||||||
|
gitSha=marks_cache[int(revnum)]
|
||||||
|
wr('M 160000 %s %s' % (gitSha, name))
|
||||||
|
sys.stderr.write("Adding submodule %s, revision %s->%s\n"
|
||||||
|
% (name,subHashes[name],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" % (subHashes[name],name,gitRepoLocation))
|
||||||
|
|
||||||
|
if len(gitmodules):
|
||||||
|
wr('M 100644 inline .gitmodules')
|
||||||
|
wr('data %d' % (len(gitmodules)+1))
|
||||||
|
wr(gitmodules)
|
||||||
|
|
||||||
# Skip .hgtags files. They only get us in trouble.
|
# Skip .hgtags files. They only get us in trouble.
|
||||||
if not hgtags and file == ".hgtags":
|
if not hgtags and file == ".hgtags":
|
||||||
sys.stderr.write('Skip %s\n' % (file))
|
sys.stderr.write('Skip %s\n' % (file))
|
||||||
@@ -443,6 +488,15 @@ def hg2git(repourl,m,marksfile,mappingfile,headsfile,tipfile,
|
|||||||
(revnode,_,_,_,_,_,_,_)=get_changeset(ui,repo,rev,authors)
|
(revnode,_,_,_,_,_,_,_)=get_changeset(ui,repo,rev,authors)
|
||||||
mapping_cache[revnode.encode('hex_codec')] = str(rev)
|
mapping_cache[revnode.encode('hex_codec')] = str(rev)
|
||||||
|
|
||||||
|
if submodule_mappings:
|
||||||
|
# Make sure that all submodules are registered in the submodule-mappings file
|
||||||
|
for rev in range(0,max):
|
||||||
|
ctx=revsymbol(repo,str(rev))
|
||||||
|
if ctx.substate:
|
||||||
|
for key in ctx.substate:
|
||||||
|
if key not in submodule_mappings:
|
||||||
|
sys.stderr.write("Error: %s not found in submodule-mappings\n" % (key))
|
||||||
|
return 1
|
||||||
|
|
||||||
c=0
|
c=0
|
||||||
brmap={}
|
brmap={}
|
||||||
@@ -515,6 +569,8 @@ if __name__=='__main__':
|
|||||||
help="Additional search path for plugins ")
|
help="Additional search path for plugins ")
|
||||||
parser.add_option("--plugin", action="append", type="string", dest="plugins",
|
parser.add_option("--plugin", action="append", type="string", dest="plugins",
|
||||||
help="Add a plugin with the given init string <name=init>")
|
help="Add a plugin with the given init string <name=init>")
|
||||||
|
parser.add_option("--subrepo-map", type="string", dest="subrepo_map",
|
||||||
|
help="Provide a mapping file between the subrepository name and the submodule name")
|
||||||
|
|
||||||
(options,args)=parser.parse_args()
|
(options,args)=parser.parse_args()
|
||||||
|
|
||||||
@@ -527,6 +583,14 @@ if __name__=='__main__':
|
|||||||
if options.statusfile==None: bail(parser,'--status')
|
if options.statusfile==None: bail(parser,'--status')
|
||||||
if options.repourl==None: bail(parser,'--repo')
|
if options.repourl==None: bail(parser,'--repo')
|
||||||
|
|
||||||
|
if options.subrepo_map:
|
||||||
|
if not os.path.exists(options.subrepo_map):
|
||||||
|
sys.stderr.write('Subrepo mapping file not found %s\n'
|
||||||
|
% options.subrepo_map)
|
||||||
|
sys.exit(1)
|
||||||
|
submodule_mappings=load_mapping('subrepo mappings',
|
||||||
|
options.subrepo_map,False)
|
||||||
|
|
||||||
a={}
|
a={}
|
||||||
if options.authorfile!=None:
|
if options.authorfile!=None:
|
||||||
a=load_mapping('authors', options.authorfile, options.raw_mappings)
|
a=load_mapping('authors', options.authorfile, options.raw_mappings)
|
||||||
|
|||||||
Reference in New Issue
Block a user