3 # Copyright (c) 2007, 2008 Rocco Rutte <pdmef@gmx.net> and others.
4 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
7 if command -v greadlink
> /dev
/null
; then
8 READLINK
="greadlink" # Prefer greadlink over readlink
10 ROOT
="$(dirname "$
($READLINK -f "$(which "$0")")")"
18 PYTHON
=${PYTHON:-python}
20 USAGE
="[--quiet] [-r <repo>] [--force] [-m <max>] [-s] [--hgtags] [-A <file>] [-B <file>] [-T <file>] [-M <name>] [-o <name>] [--hg-hash] [-e <encoding>]"
21 LONG_USAGE
="Import hg repository <repo> up to either tip or <max>
22 If <repo> is omitted, use last hg repository as obtained from state file,
23 GIT_DIR/$PFX-$SFX_STATE by default.
25 Note: The argument order matters.
28 --quiet Passed to git-fast-import(1)
29 -r <repo> Mercurial repository to import
30 --force Ignore validation errors when converting, and pass --force
32 -m <max> Maximum revision to import
33 -s Enable parsing Signed-off-by lines
34 --hgtags Enable exporting .hgtags files
35 -A <file> Read author map from file
36 (Same as in git-svnimport(1) and git-cvsimport(1))
37 -B <file> Read branch map from file
38 -T <file> Read tags map from file
39 -M <name> Set the default branch name (defaults to 'master')
40 -o <name> Use <name> as branch namespace to track upstream (eg 'origin')
41 --hg-hash Annotate commits with the hg hash as git notes in the
43 -e <encoding> Assume commit and author strings retrieved from
44 Mercurial are encoded in <encoding>
45 --fe <filename_encoding> Assume filenames from Mercurial are encoded
46 in <filename_encoding>
50 echo "usage: $(basename "$0") $USAGE"
56 IS_BARE
=$
(git rev-parse
--is-bare-repository) \
57 ||
(echo "Could not find git repo" ; exit 1)
58 if test "z$IS_BARE" != ztrue
; then
59 # This is not a bare repo, cd to the toplevel
60 TOPLEVEL
=$
(git rev-parse
--show-toplevel) \
61 ||
(echo "Could not find git repo toplevel" ; exit 1)
62 cd $TOPLEVEL ||
exit 1
64 GIT_DIR
=$
(git rev-parse
--git-dir) ||
(echo "Could not find git repo" ; exit 1)
68 IGNORECASE
=`git config core.ignoreCase`
69 if [ "true" = "$IGNORECASE" ]; then
74 while case "$#" in 0) break ;; esac
77 -r|
--r|
--re|
--rep|
--repo)
81 --q|
--qu|
--qui|
--quie|
--quiet)
82 GFI_OPTS
="$GFI_OPTS --quiet"
85 # pass --force to git-fast-import and hg-fast-export.py
86 GFI_OPTS
="$GFI_OPTS --force"
91 # pass any other options down to hg2git.py
101 if [ ! -z "$IGNORECASEWARN" ]; then
102 echo "Error: The option core.ignoreCase is set to true in the git"
103 echo "repository. This will produce empty changesets for renames that just"
104 echo "change the case of the file name."
105 echo "Use --force to skip this check or change the option with"
106 echo "git config core.ignoreCase false"
110 # Make a backup copy of each state file
111 for i
in $SFX_STATE $SFX_MARKS $SFX_MAPPING $SFX_HEADS ; do
112 if [ -f "$GIT_DIR/$PFX-$i" ] ; then
113 cp "$GIT_DIR/$PFX-$i" "$GIT_DIR/$PFX-$i~"
117 # for convenience: get default repo from state file
118 if [ x
"$REPO" = x
-a -f "$GIT_DIR/$PFX-$SFX_STATE" ] ; then
119 REPO
="`grep '^:repo ' "$GIT_DIR/$PFX-$SFX_STATE" | cut -d ' ' -f 2`"
120 echo "Using last hg repository \"$REPO\""
123 if [ -z "$REPO" ]; then
124 echo "no repo given, use -r flag"
128 # make sure we have a marks cache
129 if [ ! -f "$GIT_DIR/$PFX-$SFX_MARKS" ] ; then
130 touch "$GIT_DIR/$PFX-$SFX_MARKS"
134 trap 'rm -f "$GIT_DIR/$PFX-$SFX_MARKS.old" "$GIT_DIR/$PFX-$SFX_MARKS.tmp"' 0
139 { read -r _err1 ||
:; read -r _err2 ||
:; } <<-EOT
141 exec 4>&3 3>&1 1>&4 4>&-
144 GIT_DIR="$GIT_DIR" $PYTHON "$ROOT/hg-fast-export.py" \
146 --marks "$GIT_DIR/$PFX-$SFX_MARKS" \
147 --mapping "$GIT_DIR/$PFX-$SFX_MAPPING" \
148 --heads "$GIT_DIR/$PFX-$SFX_HEADS" \
149 --status "$GIT_DIR/$PFX-$SFX_STATE" \
155 git fast-import $GFI_OPTS --export-marks="$GIT_DIR/$PFX-$SFX_MARKS.tmp" 3>&- || _e2=$?
161 [ "$_err1" = 0 -a "$_err2" = 0 ] ||
exit 1
163 # move recent marks cache out of the way...
164 if [ -f "$GIT_DIR/$PFX-$SFX_MARKS" ] ; then
165 mv "$GIT_DIR/$PFX-$SFX_MARKS" "$GIT_DIR/$PFX-$SFX_MARKS.old"
167 touch "$GIT_DIR/$PFX-$SFX_MARKS.old"
170 # ...to create a new merged one
171 cat "$GIT_DIR/$PFX-$SFX_MARKS.old" "$GIT_DIR/$PFX-$SFX_MARKS.tmp" \
172 |
uniq > "$GIT_DIR/$PFX-$SFX_MARKS"
174 # save SHA1s of current heads for incremental imports
175 # and connectivity (plus sanity checking)
176 for head in `git branch | sed 's#^..##'` ; do
177 id
="`git rev-parse refs/heads/$head`"
179 done > "$GIT_DIR/$PFX-$SFX_HEADS"
181 # check diff with color:
182 # ( for i in `find . -type f | grep -v '\.git'` ; do diff -u $i $REPO/$i ; done | cdiff ) | less -r