Fix TypeError when using -M command line argument
[fast-export.git] / hg-fast-export.sh
blob6533452286cdda9d5d3d11c9431b94d85771065e
1 #!/bin/sh
3 # Copyright (c) 2007, 2008 Rocco Rutte <pdmef@gmx.net> and others.
4 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
6 READLINK="readlink"
7 if command -v greadlink > /dev/null; then
8 READLINK="greadlink" # Prefer greadlink over readlink
9 fi
11 if ! $READLINK -f "$(which "$0")" > /dev/null 2>&1 ; then
12 ROOT="$(dirname "$(which "$0")")"
13 if [ ! -f "$ROOT/hg-fast-export.py" ] ; then
14 echo "hg-fast-exports requires a readlink implementation which knows" \
15 " how to canonicalize paths in order to be called via a symlink."
16 exit 1
18 else
19 ROOT="$(dirname "$($READLINK -f "$(which "$0")")")"
22 REPO=""
23 PFX="hg2git"
24 SFX_MAPPING="mapping"
25 SFX_MARKS="marks"
26 SFX_HEADS="heads"
27 SFX_STATE="state"
28 GFI_OPTS=""
30 if [ -z "${PYTHON}" ]; then
31 # $PYTHON is not set, so we try to find a working python with mercurial:
32 for python_cmd in python2 python python3; do
33 if command -v $python_cmd > /dev/null; then
34 $python_cmd -c 'from mercurial.scmutil import revsymbol' 2> /dev/null
35 if [ $? -eq 0 ]; then
36 PYTHON=$python_cmd
37 break
40 done
42 if [ -z "${PYTHON}" ]; then
43 echo "Could not find a python interpreter with the mercurial module >= 4.6 available. " \
44 "Please use the 'PYTHON' environment variable to specify the interpreter to use."
45 exit 1
48 USAGE="[--quiet] [-r <repo>] [--force] [-m <max>] [-s] [--hgtags] [-A <file>] [-B <file>] [-T <file>] [-M <name>] [-o <name>] [--hg-hash] [-e <encoding>]"
49 LONG_USAGE="Import hg repository <repo> up to either tip or <max>
50 If <repo> is omitted, use last hg repository as obtained from state file,
51 GIT_DIR/$PFX-$SFX_STATE by default.
53 Note: The argument order matters.
55 Options:
56 --quiet Passed to git-fast-import(1)
57 -r <repo> Mercurial repository to import
58 --force Ignore validation errors when converting, and pass --force
59 to git-fast-import(1)
60 -m <max> Maximum revision to import
61 -s Enable parsing Signed-off-by lines
62 --hgtags Enable exporting .hgtags files
63 -A <file> Read author map from file
64 (Same as in git-svnimport(1) and git-cvsimport(1))
65 -B <file> Read branch map from file
66 -T <file> Read tags map from file
67 -M <name> Set the default branch name (defaults to 'master')
68 -n Do not perform built-in (broken in many cases) sanitizing
69 of branch/tag names.
70 -o <name> Use <name> as branch namespace to track upstream (eg 'origin')
71 --hg-hash Annotate commits with the hg hash as git notes in the
72 hg namespace.
73 -e <encoding> Assume commit and author strings retrieved from
74 Mercurial are encoded in <encoding>
75 --fe <filename_encoding> Assume filenames from Mercurial are encoded
76 in <filename_encoding>
77 --mappings-are-raw Assume mappings are raw <key>=<value> lines
78 --filter-contents <cmd> Pipe contents of each exported file through <cmd>
79 with <file-path> <hg-hash> <is-binary> as arguments
80 --plugin <plugin=init> Add a plugin with the given init string (repeatable)
81 --plugin-path <plugin-path> Add an additional plugin lookup path
83 case "$1" in
84 -h|--help)
85 echo "usage: $(basename "$0") $USAGE"
86 echo ""
87 echo "$LONG_USAGE"
88 exit 0
89 esac
91 IS_BARE=$(git rev-parse --is-bare-repository) \
92 || (echo "Could not find git repo" ; exit 1)
93 if test "z$IS_BARE" != ztrue; then
94 # This is not a bare repo, cd to the toplevel
95 TOPLEVEL=$(git rev-parse --show-toplevel) \
96 || (echo "Could not find git repo toplevel" ; exit 1)
97 cd "$TOPLEVEL" || exit 1
99 GIT_DIR=$(git rev-parse --git-dir) || (echo "Could not find git repo" ; exit 1)
102 IGNORECASEWARN=""
103 IGNORECASE=`git config core.ignoreCase`
104 if [ "true" = "$IGNORECASE" ]; then
105 IGNORECASEWARN="true"
109 while case "$#" in 0) break ;; esac
111 case "$1" in
112 -r|--r|--re|--rep|--repo)
113 shift
114 REPO="$1"
116 --q|--qu|--qui|--quie|--quiet)
117 GFI_OPTS="$GFI_OPTS --quiet"
119 --force)
120 # pass --force to git-fast-import and hg-fast-export.py
121 GFI_OPTS="$GFI_OPTS --force"
122 IGNORECASEWARN="";
123 break
126 # pass any other options down to hg2git.py
127 break
130 break
132 esac
133 shift
134 done
136 if [ ! -z "$IGNORECASEWARN" ]; then
137 echo "Error: The option core.ignoreCase is set to true in the git"
138 echo "repository. This will produce empty changesets for renames that just"
139 echo "change the case of the file name."
140 echo "Use --force to skip this check or change the option with"
141 echo "git config core.ignoreCase false"
142 exit 1
145 # Make a backup copy of each state file
146 for i in $SFX_STATE $SFX_MARKS $SFX_MAPPING $SFX_HEADS ; do
147 if [ -f "$GIT_DIR/$PFX-$i" ] ; then
148 cp "$GIT_DIR/$PFX-$i" "$GIT_DIR/$PFX-$i~"
150 done
152 # for convenience: get default repo from state file
153 if [ x"$REPO" = x -a -f "$GIT_DIR/$PFX-$SFX_STATE" ] ; then
154 REPO="`grep '^:repo ' "$GIT_DIR/$PFX-$SFX_STATE" | cut -d ' ' -f 2`"
155 echo "Using last hg repository \"$REPO\""
158 if [ -z "$REPO" ]; then
159 echo "no repo given, use -r flag"
160 exit 1
163 # make sure we have a marks cache
164 if [ ! -f "$GIT_DIR/$PFX-$SFX_MARKS" ] ; then
165 touch "$GIT_DIR/$PFX-$SFX_MARKS"
168 # cleanup on exit
169 trap 'rm -f "$GIT_DIR/$PFX-$SFX_MARKS.old" "$GIT_DIR/$PFX-$SFX_MARKS.tmp"' 0
171 _err1=
172 _err2=
173 exec 3>&1
174 { read -r _err1 || :; read -r _err2 || :; } <<-EOT
176 exec 4>&3 3>&1 1>&4 4>&-
178 _e1=0
179 GIT_DIR="$GIT_DIR" "$PYTHON" "$ROOT/hg-fast-export.py" \
180 --repo "$REPO" \
181 --marks "$GIT_DIR/$PFX-$SFX_MARKS" \
182 --mapping "$GIT_DIR/$PFX-$SFX_MAPPING" \
183 --heads "$GIT_DIR/$PFX-$SFX_HEADS" \
184 --status "$GIT_DIR/$PFX-$SFX_STATE" \
185 "$@" 3>&- || _e1=$?
186 echo $_e1 >&3
187 } | \
189 _e2=0
190 git fast-import $GFI_OPTS --export-marks="$GIT_DIR/$PFX-$SFX_MARKS.tmp" 3>&- || _e2=$?
191 echo $_e2 >&3
195 exec 3>&-
196 [ "$_err1" = 0 -a "$_err2" = 0 ] || exit 1
198 # move recent marks cache out of the way...
199 if [ -f "$GIT_DIR/$PFX-$SFX_MARKS" ] ; then
200 mv "$GIT_DIR/$PFX-$SFX_MARKS" "$GIT_DIR/$PFX-$SFX_MARKS.old"
201 else
202 touch "$GIT_DIR/$PFX-$SFX_MARKS.old"
205 # ...to create a new merged one
206 cat "$GIT_DIR/$PFX-$SFX_MARKS.old" "$GIT_DIR/$PFX-$SFX_MARKS.tmp" \
207 | uniq > "$GIT_DIR/$PFX-$SFX_MARKS"
209 # save SHA1s of current heads for incremental imports
210 # and connectivity (plus sanity checking)
211 for head in `git branch | sed 's#^..##'` ; do
212 id="`git rev-parse refs/heads/$head`"
213 echo ":$head $id"
214 done > "$GIT_DIR/$PFX-$SFX_HEADS"
216 # check diff with color:
217 # ( for i in `find . -type f | grep -v '\.git'` ; do diff -u $i $REPO/$i ; done | cdiff ) | less -r