Skip to content

Instantly share code, notes, and snippets.

@neilmayhew
Forked from matiasgarciaisaia/hg-to-git.sh
Last active February 27, 2020 19:16
Show Gist options
  • Save neilmayhew/7016023 to your computer and use it in GitHub Desktop.
Save neilmayhew/7016023 to your computer and use it in GitHub Desktop.
Script to convert from hg to git that wraps hg-fast-export and performs some additional fixups
#!/bin/bash
USAGE="Usage: $(basename "$0" .sh) SOURCE-HG DEST-GIT"
SRC=${1?$USAGE} || exit 1
DST=${2?$USAGE} || exit 1
SANITIZE=$(dirname "$0")/sanitize.py
(cd "$SRC" &&
hg branches --closed) |
(cd "$DST" &&
sed -n '/(closed)/s/ *[0-9]*:.*//p' |
"$SANITIZE" |
while read branch
do
git rev-parse "$branch" &>/dev/null &&
git tag -am "Mercurial branch that was closed" "closed/$branch" "$branch" &&
git branch -D "$branch"
done
)
#!/bin/bash -e
# Adapted from http://www.manas.com.ar/mgarcia/2013/10/09/introducing-hg-to-git/
usage()
{
exec >&2
echo "Usage: $(basename $0) [OPTIONS] /path/to/hg/repo /path/to/new/repo"
echo ""
echo "OPTIONS:"
echo " -a, --authors=FILE File of author mappings"
echo " -f, --force Passed on to hg-fast-export"
echo " -h, --help Display this help"
exit ${1-0}
}
abort()
{
exec >&2
echo "$1"
echo ""
usage 1
}
abs()
{
readlink -f "$1"
}
# Use getopt to parse options into a manageable form
PROGNAME=$(basename "$0")
PARSEDARGS=$(getopt -n "$PROGNAME" \
-o a:fh --long authors:,force,help \
-- "$@") || usage $?
eval set -- "$PARSEDARGS"
# Process options
AUTHORS=
while true
do
case "$1" in
-a|--authors) AUTHORS=$(abs $2); shift 2;;
-f|--force) FORCE=--force; shift;;
--help) usage;;
--) shift; break;;
*) echo "Internal error: option '$1' not handled"; exit 1;;
esac
done
if [ $# -ne 2 ]
then
echo "Incorrect number of arguments:" "$@" >&2
echo "" >&2
usage 1
fi
[ -d "$1" ] || abort "$1 should be an existing hg repository"
[ -d "$1/.hg" ] || abort "$1 should be an existing hg repository ($1/.hg must be a directory)"
[ -d "$2" ] && abort "$2 should not exist"
SOURCE=$(cd "$1" && pwd)
git init "$2" && cd "$2"
LOG=$(mktemp)
SANITIZE=$(mktemp)
trap "rm -f $LOG $SANITIZE" 0
hg-fast-export ${AUTHORS:+--authors=$AUTHORS} $FORCE -r "$SOURCE" |& tee "$LOG"
git checkout
sed -n '/Warning: sanitized branch/s/.*\[\([^]]*\)\] to \[\([^]]*\)\].*/s@^\1$@\2@/p' "$LOG" |
sort -u -o "$SANITIZE"
(cd "$SOURCE" && hg branches --closed) |
sed -n '/(closed)/s/ *[0-9]*:.*//p' |
sed -f "$SANITIZE" |
while read branch
do
git tag -am "Mercurial branch that was closed" "closed/$branch" "$branch" &&
git branch -D "$branch"
done
#!/usr/bin/env python
# Copied from hg-fast-export.py
import sys
import re
def sanitize_name(name,what="branch"):
"""Sanitize input roughly according to git-check-ref-format(1)"""
def dot(name):
if name[0] == '.': return '_'+name[1:]
return name
n=name
p=re.compile('([[ ~^:?*]|\.\.)')
n=p.sub('_', n)
if n[-1] in ('/', '.'): n=n[:-1]+'_'
n='/'.join(map(dot,n.split('/')))
p=re.compile('_+')
n=p.sub('_', n)
#if n!=name:
# sys.stderr.write('Warning: sanitized %s [%s] to [%s]\n' % (what,name,n))
return n
def main():
for name in sys.stdin:
name = name.rstrip("\n")
print sanitize_name(name)
if __name__ == "__main__":
main()
@nathanielcook
Copy link

Very helpful fork; thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment