initial
This commit is contained in:
208
svn-to-git
Executable file
208
svn-to-git
Executable file
@@ -0,0 +1,208 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
############################################################################ begin logging
|
||||||
|
# check if stdout is a terminal...
|
||||||
|
if test -t 1; then
|
||||||
|
|
||||||
|
# see if it supports colors...
|
||||||
|
ncolors=$(tput colors)
|
||||||
|
|
||||||
|
if test -n "$ncolors" && test $ncolors -ge 8; then
|
||||||
|
bold="$(tput bold)"
|
||||||
|
underline="$(tput smul)"
|
||||||
|
standout="$(tput smso)"
|
||||||
|
normal="$(tput sgr0)"
|
||||||
|
black="$(tput setaf 0)"
|
||||||
|
red="$(tput setaf 1)"
|
||||||
|
green="$(tput setaf 2)"
|
||||||
|
yellow="$(tput setaf 3)"
|
||||||
|
blue="$(tput setaf 4)"
|
||||||
|
magenta="$(tput setaf 5)"
|
||||||
|
cyan="$(tput setaf 6)"
|
||||||
|
white="$(tput setaf 7)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
append_msg() {
|
||||||
|
if test $# -ne 0; then
|
||||||
|
echo -n ": ${bold}$*"
|
||||||
|
fi
|
||||||
|
echo "${normal}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# write a message
|
||||||
|
message() {
|
||||||
|
if test $# -eq 0; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "${bold}${white}$*${normal}" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# write a success message
|
||||||
|
success() {
|
||||||
|
echo -n "${bold}${green}success" 1>&2
|
||||||
|
append_msg $* 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# write a notice
|
||||||
|
notice() {
|
||||||
|
echo -n "${bold}${yellow}notice" 1>&2
|
||||||
|
append_msg $* 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# write a warning message
|
||||||
|
warning() {
|
||||||
|
echo -en "${bold}${red}warning" 1>&2
|
||||||
|
append_msg $* 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# write error message
|
||||||
|
error() {
|
||||||
|
echo -en "${bold}${red}error" 1>&2
|
||||||
|
append_msg $* 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# run a command, print the result and abort in case of error
|
||||||
|
# option: --ignore: ignore the result, continue in case of error
|
||||||
|
run() {
|
||||||
|
ignore=1
|
||||||
|
while test $# -gt 0; do
|
||||||
|
case "$1" in
|
||||||
|
(--ignore) ignore=0;;
|
||||||
|
(*) break;;
|
||||||
|
esac
|
||||||
|
shift;
|
||||||
|
done
|
||||||
|
echo -n "${bold}${yellow}running:${white} $*${normal} … "
|
||||||
|
set +e
|
||||||
|
result=$($* 2>&1)
|
||||||
|
res=$?
|
||||||
|
set -e
|
||||||
|
if test $res -ne 0; then
|
||||||
|
if test $ignore -eq 1; then
|
||||||
|
error "failed with return code: $res"
|
||||||
|
if test -n "$result"; then
|
||||||
|
echo "$result"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
warning "ignored return code: $res"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
success
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
############################################################################ error handler
|
||||||
|
function traperror() {
|
||||||
|
set +x
|
||||||
|
local err=($1) # error status
|
||||||
|
local line="$2" # LINENO
|
||||||
|
local linecallfunc="$3"
|
||||||
|
local command="$4"
|
||||||
|
local funcstack="$5"
|
||||||
|
IFS=" "
|
||||||
|
for e in ${err[@]}; do
|
||||||
|
if test -n "$e" -a "$e" != "0"; then
|
||||||
|
error "line $line - command '$command' exited with status: $e (${err[@]})"
|
||||||
|
if [ "${funcstack}" != "main" -o "$linecallfunc" != "0" ]; then
|
||||||
|
echo -n " ... error at ${funcstack} " 1>&2
|
||||||
|
if [ "$linecallfunc" != "" ]; then
|
||||||
|
echo -n "called at line $linecallfunc" 1>&2
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
exit $e
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
success
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# catch errors
|
||||||
|
trap 'traperror "$? ${PIPESTATUS[@]}" $LINENO $BASH_LINENO "$BASH_COMMAND" "${FUNCNAME[@]}" "${FUNCTION}"' ERR SIGINT INT TERM EXIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
######################################################### commandline parameter evaluation
|
||||||
|
while test $# -gt 0; do
|
||||||
|
case "$1" in
|
||||||
|
(--help|-h) less <<EOF
|
||||||
|
SYNOPSIS
|
||||||
|
|
||||||
|
$0 [OPTIONS]
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
|
||||||
|
--help, -h show this help
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit;;
|
||||||
|
(*) error "unknow option $1, try $0 --help"; exit 1;;
|
||||||
|
esac
|
||||||
|
if test $# -eq 0; then
|
||||||
|
error "missing parameter, try $0 --help"; exit 1
|
||||||
|
fi
|
||||||
|
shift;
|
||||||
|
done
|
||||||
|
|
||||||
|
##################################################################################### Main
|
||||||
|
|
||||||
|
function createusers() {
|
||||||
|
tmpdir="/tmp/old-svn-${gittarget}"
|
||||||
|
svn co "$svnurl" "$tmpdir"
|
||||||
|
cd "$tmpdir"
|
||||||
|
svn log -q | \
|
||||||
|
awk -F '|' \
|
||||||
|
'/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | \
|
||||||
|
sort -u > "$users"
|
||||||
|
cd -
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
users=users.txt
|
||||||
|
options=("--authors-file=$users" "--no-metadata" "--prefix" "" "-s")
|
||||||
|
svnurl="$1"
|
||||||
|
giturl="$2"
|
||||||
|
gittarget="${svnurl##*/}"
|
||||||
|
if ! test -f "$users"; then
|
||||||
|
createusers
|
||||||
|
fi
|
||||||
|
|
||||||
|
# migration according to
|
||||||
|
# https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git
|
||||||
|
|
||||||
|
# one-way clone subversion repository
|
||||||
|
run git svn clone "${options[@]}" "$svnurl" "$gittarget"
|
||||||
|
cd "$gittarget"
|
||||||
|
|
||||||
|
# move the tags to be proper git tags
|
||||||
|
for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do
|
||||||
|
run git tag ${t/tags\//} $t && git branch -D -r $t
|
||||||
|
done
|
||||||
|
|
||||||
|
# move the rest of the references under refs/remotes to be local branches
|
||||||
|
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do
|
||||||
|
run git branch $b refs/remotes/$b && git branch -D -r $b
|
||||||
|
done
|
||||||
|
|
||||||
|
# remove peg-revisions
|
||||||
|
for p in $(git for-each-ref --format='%(refname:short)' | grep @); do
|
||||||
|
run git branch -D $p
|
||||||
|
done
|
||||||
|
|
||||||
|
# remove extra trunk branch
|
||||||
|
run git branch -d trunk
|
||||||
|
|
||||||
|
# add new remote repository
|
||||||
|
run git remote add origin "$giturl"
|
||||||
|
|
||||||
|
run git push origin --all
|
||||||
|
run git push origin --tags
|
||||||
|
|
||||||
|
# checkout fresh git repository
|
||||||
|
cd -
|
||||||
|
run rm -rf "$gittarget"
|
||||||
|
run git clone "$giturl" "$gittarget"
|
Reference in New Issue
Block a user