mirror of
https://github.com/frej/fast-export.git
synced 2026-05-07 02:26:51 +02:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19aa906308 | ||
|
|
50dc10770b | ||
|
|
90483e02e5 | ||
|
|
cc8fefe008 | ||
|
|
e174c2a0b7 | ||
|
|
2536f87544 | ||
|
|
17c8a22066 | ||
|
|
7aa82e8234 | ||
|
|
02bb982dd9 |
15
README.md
15
README.md
@@ -33,7 +33,8 @@ Using hg-fast-export is quite simple for a mercurial repository <repo>:
|
|||||||
mkdir repo-git # or whatever
|
mkdir repo-git # or whatever
|
||||||
cd repo-git
|
cd repo-git
|
||||||
git init
|
git init
|
||||||
hg-fast-export.sh -r <repo>
|
hg-fast-export.sh -r <local-repo>
|
||||||
|
git checkout HEAD
|
||||||
```
|
```
|
||||||
|
|
||||||
Please note that hg-fast-export does not automatically check out the
|
Please note that hg-fast-export does not automatically check out the
|
||||||
@@ -65,12 +66,18 @@ As mercurial appears to be much less picky about the syntax of the
|
|||||||
author information than git, an author mapping file can be given to
|
author information than git, an author mapping file can be given to
|
||||||
hg-fast-export to fix up malformed author strings. The file is
|
hg-fast-export to fix up malformed author strings. The file is
|
||||||
specified using the -A option. The file should contain lines of the
|
specified using the -A option. The file should contain lines of the
|
||||||
form `FromAuthor=ToAuthor`. The example authors.map below will
|
form `"<key>"="<value>"`. Inside the key and value strings, all escape
|
||||||
translate `User <garbage<user@example.com>` to `User <user@example.com>`.
|
sequences understood by the python `string_escape` encoding are
|
||||||
|
supported. (Versions of fast-export prior to v171002 had a different
|
||||||
|
syntax, the old syntax can be enabled by the flag
|
||||||
|
`--mappings-are-raw`.)
|
||||||
|
|
||||||
|
The example authors.map below will translate `User
|
||||||
|
<garbage<tab><user@example.com>` to `User <user@example.com>`.
|
||||||
|
|
||||||
```
|
```
|
||||||
-- Start of authors.map --
|
-- Start of authors.map --
|
||||||
User <garbage<user@example.com>=User <user@example.com>
|
"User <garbage\t<user@example.com>"="User <user@example.com>"
|
||||||
-- End of authors.map --
|
-- End of authors.map --
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -153,9 +153,13 @@ def sanitize_name(name,what="branch", mapping={}):
|
|||||||
# modifying names which previously were not touched it will break
|
# modifying names which previously were not touched it will break
|
||||||
# preexisting setups which are doing incremental imports.
|
# preexisting setups which are doing incremental imports.
|
||||||
#
|
#
|
||||||
# Use the -B and -T options to mangle branch and tag names
|
# Fast-export tries to not inflict arbitrary naming policy on the
|
||||||
# instead. If you have a source repository where this is too much
|
# user, instead it aims to provide mechanisms allowing the user to
|
||||||
# work to do manually, write a tool that does it for you.
|
# apply their own policy. Therefore do not add a transform which can
|
||||||
|
# already be implemented with the -B and -T options to mangle branch
|
||||||
|
# and tag names. If you have a source repository where this is too
|
||||||
|
# much work to do manually, write a tool that does it for you.
|
||||||
|
#
|
||||||
|
|
||||||
def dot(name):
|
def dot(name):
|
||||||
if not name: return name
|
if not name: return name
|
||||||
@@ -294,7 +298,24 @@ def export_tags(ui,repo,old_marks,mapping_cache,count,authors,tagsmap):
|
|||||||
count=checkpoint(count)
|
count=checkpoint(count)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
def load_mapping(name, filename):
|
def load_mapping(name, filename, mapping_is_raw):
|
||||||
|
raw_regexp=re.compile('^([^=]+)[ ]*=[ ]*(.+)$')
|
||||||
|
string_regexp='"(((\\.)|(\\")|[^"])*)"'
|
||||||
|
quoted_regexp=re.compile('^'+string_regexp+'[ ]*=[ ]*'+string_regexp+'$')
|
||||||
|
|
||||||
|
def parse_raw_line(line):
|
||||||
|
m=raw_regexp.match(line)
|
||||||
|
if m==None:
|
||||||
|
return None
|
||||||
|
return (m.group(1).strip(), m.group(2).strip())
|
||||||
|
|
||||||
|
def parse_quoted_line(line):
|
||||||
|
m=quoted_regexp.match(line)
|
||||||
|
if m==None:
|
||||||
|
return None
|
||||||
|
return (m.group(1).decode('string_escape'),
|
||||||
|
m.group(5).decode('string_escape'))
|
||||||
|
|
||||||
cache={}
|
cache={}
|
||||||
if not os.path.exists(filename):
|
if not os.path.exists(filename):
|
||||||
sys.stderr.write('Could not open mapping file [%s]\n' % (filename))
|
sys.stderr.write('Could not open mapping file [%s]\n' % (filename))
|
||||||
@@ -302,18 +323,19 @@ def load_mapping(name, filename):
|
|||||||
f=open(filename,'r')
|
f=open(filename,'r')
|
||||||
l=0
|
l=0
|
||||||
a=0
|
a=0
|
||||||
lre=re.compile('^([^=]+)[ ]*=[ ]*(.+)$')
|
|
||||||
for line in f.readlines():
|
for line in f.readlines():
|
||||||
l+=1
|
l+=1
|
||||||
line=line.strip()
|
line=line.strip()
|
||||||
if line=='' or line[0]=='#':
|
if l==1 and line[0]=='#' and line=='# quoted-escaped-strings':
|
||||||
continue
|
continue
|
||||||
m=lre.match(line)
|
elif line=='' or line[0]=='#':
|
||||||
|
continue
|
||||||
|
m=parse_raw_line(line) if mapping_is_raw else parse_quoted_line(line)
|
||||||
if m==None:
|
if m==None:
|
||||||
sys.stderr.write('Invalid file format in [%s], line %d\n' % (filename,l))
|
sys.stderr.write('Invalid file format in [%s], line %d\n' % (filename,l))
|
||||||
continue
|
continue
|
||||||
# put key:value in cache, key without ^:
|
# put key:value in cache, key without ^:
|
||||||
cache[m.group(1).strip()]=m.group(2).strip()
|
cache[m[0]]=m[1]
|
||||||
a+=1
|
a+=1
|
||||||
f.close()
|
f.close()
|
||||||
sys.stderr.write('Loaded %d %s\n' % (a, name))
|
sys.stderr.write('Loaded %d %s\n' % (a, name))
|
||||||
@@ -460,6 +482,8 @@ if __name__=='__main__':
|
|||||||
help="Assume commit and author strings retrieved from Mercurial are encoded in <encoding>")
|
help="Assume commit and author strings retrieved from Mercurial are encoded in <encoding>")
|
||||||
parser.add_option("--fe",dest="fn_encoding",
|
parser.add_option("--fe",dest="fn_encoding",
|
||||||
help="Assume file names from Mercurial are encoded in <filename_encoding>")
|
help="Assume file names from Mercurial are encoded in <filename_encoding>")
|
||||||
|
parser.add_option("--mappings-are-raw",dest="raw_mappings", default=False,
|
||||||
|
help="Assume mappings are raw <key>=<value> lines")
|
||||||
|
|
||||||
(options,args)=parser.parse_args()
|
(options,args)=parser.parse_args()
|
||||||
|
|
||||||
@@ -474,15 +498,15 @@ if __name__=='__main__':
|
|||||||
|
|
||||||
a={}
|
a={}
|
||||||
if options.authorfile!=None:
|
if options.authorfile!=None:
|
||||||
a=load_mapping('authors', options.authorfile)
|
a=load_mapping('authors', options.authorfile, options.raw_mappings)
|
||||||
|
|
||||||
b={}
|
b={}
|
||||||
if options.branchesfile!=None:
|
if options.branchesfile!=None:
|
||||||
b=load_mapping('branches', options.branchesfile)
|
b=load_mapping('branches', options.branchesfile, options.raw_mappings)
|
||||||
|
|
||||||
t={}
|
t={}
|
||||||
if options.tagsfile!=None:
|
if options.tagsfile!=None:
|
||||||
t=load_mapping('tags', options.tagsfile)
|
t=load_mapping('tags', options.tagsfile, True)
|
||||||
|
|
||||||
if options.default_branch!=None:
|
if options.default_branch!=None:
|
||||||
set_default_branch(options.default_branch)
|
set_default_branch(options.default_branch)
|
||||||
|
|||||||
@@ -7,7 +7,18 @@ READLINK="readlink"
|
|||||||
if command -v greadlink > /dev/null; then
|
if command -v greadlink > /dev/null; then
|
||||||
READLINK="greadlink" # Prefer greadlink over readlink
|
READLINK="greadlink" # Prefer greadlink over readlink
|
||||||
fi
|
fi
|
||||||
ROOT="$(dirname "$($READLINK -f "$(which "$0")")")"
|
|
||||||
|
if ! $READLINK -f "$(which "$0")" > /dev/null 2>&1 ; then
|
||||||
|
ROOT="$(dirname "$(which "$0")")"
|
||||||
|
if [ ! -f "$ROOT/hg-fast-export.py" ] ; then
|
||||||
|
echo "hg-fast-exports requires a readlink implementation which knows" \
|
||||||
|
" how to canonicalize paths in order to be called via a symlink."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
ROOT="$(dirname "$($READLINK -f "$(which "$0")")")"
|
||||||
|
fi
|
||||||
|
|
||||||
REPO=""
|
REPO=""
|
||||||
PFX="hg2git"
|
PFX="hg2git"
|
||||||
SFX_MAPPING="mapping"
|
SFX_MAPPING="mapping"
|
||||||
@@ -44,6 +55,7 @@ Options:
|
|||||||
Mercurial are encoded in <encoding>
|
Mercurial are encoded in <encoding>
|
||||||
--fe <filename_encoding> Assume filenames from Mercurial are encoded
|
--fe <filename_encoding> Assume filenames from Mercurial are encoded
|
||||||
in <filename_encoding>
|
in <filename_encoding>
|
||||||
|
--mappings-are-raw Assume mappings are raw <key>=<value> lines
|
||||||
"
|
"
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
@@ -59,7 +71,7 @@ if test "z$IS_BARE" != ztrue; then
|
|||||||
# This is not a bare repo, cd to the toplevel
|
# This is not a bare repo, cd to the toplevel
|
||||||
TOPLEVEL=$(git rev-parse --show-toplevel) \
|
TOPLEVEL=$(git rev-parse --show-toplevel) \
|
||||||
|| (echo "Could not find git repo toplevel" ; exit 1)
|
|| (echo "Could not find git repo toplevel" ; exit 1)
|
||||||
cd $TOPLEVEL || exit 1
|
cd "$TOPLEVEL" || exit 1
|
||||||
fi
|
fi
|
||||||
GIT_DIR=$(git rev-parse --git-dir) || (echo "Could not find git repo" ; exit 1)
|
GIT_DIR=$(git rev-parse --git-dir) || (echo "Could not find git repo" ; exit 1)
|
||||||
|
|
||||||
@@ -141,7 +153,7 @@ $(
|
|||||||
exec 4>&3 3>&1 1>&4 4>&-
|
exec 4>&3 3>&1 1>&4 4>&-
|
||||||
{
|
{
|
||||||
_e1=0
|
_e1=0
|
||||||
GIT_DIR="$GIT_DIR" $PYTHON "$ROOT/hg-fast-export.py" \
|
GIT_DIR="$GIT_DIR" "$PYTHON" "$ROOT/hg-fast-export.py" \
|
||||||
--repo "$REPO" \
|
--repo "$REPO" \
|
||||||
--marks "$GIT_DIR/$PFX-$SFX_MARKS" \
|
--marks "$GIT_DIR/$PFX-$SFX_MARKS" \
|
||||||
--mapping "$GIT_DIR/$PFX-$SFX_MAPPING" \
|
--mapping "$GIT_DIR/$PFX-$SFX_MAPPING" \
|
||||||
|
|||||||
Reference in New Issue
Block a user