CI: Remove run-tests script
[fast-export.git] / hg-fast-export.sh
blob7d6d7b7994654acda6cb781240320d2aa48630e0
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 python3 python; 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 "${PYTHON}" -c 'import sys; exit(sys.version_info.major==3 and sys.version_info.minor >= 7)'
50 if [ $? -eq 0 ]; then
51 echo "Could not find an interpreter for a supported Python version (>= 3.7)" \
52 "Please use the 'PYTHON' environment variable to specify the interpreter to use."
53 exit 1
56 USAGE="[--quiet] [-r <repo>] [--force] [--ignore-unnamed-heads] [-m <max>] [-s] [--hgtags] [-A <file>] [-B <file>] [-T <file>] [-M <name>] [-o <name>] [--hg-hash] [-e <encoding>]"
57 LONG_USAGE="Import hg repository <repo> up to either tip or <max>
58 If <repo> is omitted, use last hg repository as obtained from state file,
59 GIT_DIR/$PFX-$SFX_STATE by default.
61 Note: The argument order matters.
63 Options:
64 --quiet Passed to git-fast-import(1)
65 -r <repo> Mercurial repository to import
66 --force Ignore validation errors when converting, and pass --force
67 to git-fast-import(1)
68 -m <max> Maximum revision to import
69 -s Enable parsing Signed-off-by lines
70 --hgtags Enable exporting .hgtags files
71 -A <file> Read author map from file
72 (Same as in git-svnimport(1) and git-cvsimport(1))
73 -B <file> Read branch map from file
74 -T <file> Read tags map from file
75 -M <name> Set the default branch name (defaults to 'master')
76 -n Do not perform built-in (broken in many cases) sanitizing
77 of branch/tag names.
78 -o <name> Use <name> as branch namespace to track upstream (eg 'origin')
79 --hg-hash Annotate commits with the hg hash as git notes in the
80 hg namespace.
81 -e <encoding> Assume commit and author strings retrieved from
82 Mercurial are encoded in <encoding>
83 --fe <filename_encoding> Assume filenames from Mercurial are encoded
84 in <filename_encoding>
85 --mappings-are-raw Assume mappings are raw <key>=<value> lines
86 --filter-contents <cmd> Pipe contents of each exported file through <cmd>
87 with <file-path> <hg-hash> <is-binary> as arguments
88 --plugin <plugin=init> Add a plugin with the given init string (repeatable)
89 --plugin-path <plugin-path> Add an additional plugin lookup path
91 case "$1" in
92 -h|--help)
93 echo "usage: $(basename "$0") $USAGE"
94 echo ""
95 echo "$LONG_USAGE"
96 exit 0
99 --debug)
100 echo -n "Using Python: "
101 "${PYTHON}" --version
102 echo -n "Using Mercurial: "
103 hg --version
104 exit 0
105 esac
107 IS_BARE=$(git rev-parse --is-bare-repository) \
108 || (echo "Could not find git repo" ; exit 1)
109 if test "z$IS_BARE" != ztrue; then
110 # This is not a bare repo, cd to the toplevel
111 TOPLEVEL=$(git rev-parse --show-toplevel) \
112 || (echo "Could not find git repo toplevel" ; exit 1)
113 cd "$TOPLEVEL" || exit 1
115 GIT_DIR=$(git rev-parse --git-dir) || (echo "Could not find git repo" ; exit 1)
118 IGNORECASEWARN=""
119 IGNORECASE=`git config core.ignoreCase`
120 if [ "true" = "$IGNORECASE" ]; then
121 IGNORECASEWARN="true"
125 while case "$#" in 0) break ;; esac
127 case "$1" in
128 -r|--r|--re|--rep|--repo)
129 shift
130 REPO="$1"
132 --q|--qu|--qui|--quie|--quiet)
133 GFI_OPTS="$GFI_OPTS --quiet"
135 --force)
136 # pass --force to git-fast-import and hg-fast-export.py
137 GFI_OPTS="$GFI_OPTS --force"
138 IGNORECASEWARN="";
139 break
142 # pass any other options down to hg2git.py
143 break
146 break
148 esac
149 shift
150 done
152 if [ ! -z "$IGNORECASEWARN" ]; then
153 echo "Error: The option core.ignoreCase is set to true in the git"
154 echo "repository. This will produce empty changesets for renames that just"
155 echo "change the case of the file name."
156 echo "Use --force to skip this check or change the option with"
157 echo "git config core.ignoreCase false"
158 exit 1
161 # Make a backup copy of each state file
162 for i in $SFX_STATE $SFX_MARKS $SFX_MAPPING $SFX_HEADS ; do
163 if [ -f "$GIT_DIR/$PFX-$i" ] ; then
164 cp "$GIT_DIR/$PFX-$i" "$GIT_DIR/$PFX-$i~"
166 done
168 # for convenience: get default repo from state file
169 if [ x"$REPO" = x -a -f "$GIT_DIR/$PFX-$SFX_STATE" ] ; then
170 REPO="`grep '^:repo ' "$GIT_DIR/$PFX-$SFX_STATE" | cut -d ' ' -f 2`"
171 echo "Using last hg repository \"$REPO\""
174 if [ -z "$REPO" ]; then
175 echo "no repo given, use -r flag"
176 exit 1
179 # make sure we have a marks cache
180 if [ ! -f "$GIT_DIR/$PFX-$SFX_MARKS" ] ; then
181 touch "$GIT_DIR/$PFX-$SFX_MARKS"
184 # cleanup on exit
185 trap 'rm -f "$GIT_DIR/$PFX-$SFX_MARKS.old" "$GIT_DIR/$PFX-$SFX_MARKS.tmp"' 0
187 _err1=
188 _err2=
189 exec 3>&1
190 { read -r _err1 || :; read -r _err2 || :; } <<-EOT
192 exec 4>&3 3>&1 1>&4 4>&-
194 _e1=0
195 GIT_DIR="$GIT_DIR" "$PYTHON" "$ROOT/hg-fast-export.py" \
196 --repo "$REPO" \
197 --marks "$GIT_DIR/$PFX-$SFX_MARKS" \
198 --mapping "$GIT_DIR/$PFX-$SFX_MAPPING" \
199 --heads "$GIT_DIR/$PFX-$SFX_HEADS" \
200 --status "$GIT_DIR/$PFX-$SFX_STATE" \
201 "$@" 3>&- || _e1=$?
202 echo $_e1 >&3
203 } | \
205 _e2=0
206 git fast-import $GFI_OPTS --export-marks="$GIT_DIR/$PFX-$SFX_MARKS.tmp" 3>&- || _e2=$?
207 echo $_e2 >&3
211 exec 3>&-
212 [ "$_err1" = 0 -a "$_err2" = 0 ] || exit 1
214 # move recent marks cache out of the way...
215 if [ -f "$GIT_DIR/$PFX-$SFX_MARKS" ] ; then
216 mv "$GIT_DIR/$PFX-$SFX_MARKS" "$GIT_DIR/$PFX-$SFX_MARKS.old"
217 else
218 touch "$GIT_DIR/$PFX-$SFX_MARKS.old"
221 # ...to create a new merged one
222 cat "$GIT_DIR/$PFX-$SFX_MARKS.old" "$GIT_DIR/$PFX-$SFX_MARKS.tmp" \
223 | uniq > "$GIT_DIR/$PFX-$SFX_MARKS"
225 # save SHA1s of current heads for incremental imports
226 # and connectivity (plus sanity checking)
227 for head in `git branch | sed 's#^..##'` ; do
228 id="`git rev-parse refs/heads/$head`"
229 echo ":$head $id"
230 done > "$GIT_DIR/$PFX-$SFX_HEADS"
232 # check diff with color:
233 # ( for i in `find . -type f | grep -v '\.git'` ; do diff -u $i $REPO/$i ; done | cdiff ) | less -r