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