SVN to GIT conversion script
[racktables-contribs] / svn2git.sh
CommitLineData
6e3fd083
AA
1#!/bin/sh
2
3# this script converts Racktables SVN repository stored on SourceForge into git
4
5SVN_ROOT=/home/alan/dev/rt-root
6WRK_DIR=/home/alan/Downloads/rt-git
7GIT_ROOT=$WRK_DIR/rt3.git
8RESULT_DIR=$WRK_DIR/bare3
9
10# prepare working directories
11set -e
12test -d $SVN_ROOT || mkdir -p $SVN_ROOT
13test -d $GIT_ROOT || mkdir -p $GIT_ROOT
14cd $SVN_ROOT
15set +e
16
17svnsync sync file://`pwd` https://racktables.svn.sourceforge.net/svnroot/racktables
18svnsync sync file://`pwd` #pull latest changes
19
20cd `dirname $GIT_ROOT` || exit 1
21git svn init -s --ignore-paths='contribs' file://$SVN_ROOT `basename $GIT_ROOT`
22
23# prepare authors file
24cat <<\END >$WRK_DIR/authors-transform.txt
25adoom42 = Aaron Dummer <aaron@dummer.info>
26andriyanov = Alexey Andriyanov <alan@al-an.info>
27dyeldandi = Denis Yeldandi <dyeldandi@gmail.com>
28gwyden = Ryan Farrington <gwyden@dreamflyght.com>
29infrastation = Denis Ovsienko <infrastation@yandex.ru>
30jthurman42 = Jonathan Thurman <jthurman42@gmail.com>
31(no author) = (no author) <(no author)>
32END
33
34#pull latest SVN changes
35cd $GIT_ROOT || exit 1
36git svn fetch -A $WRK_DIR/authors-transform.txt
37
38unpack_refs() {
39 git show-ref | \
40 while read sha path; do
41 mkdir `dirname .git/$path` 2>/dev/null
42 echo $sha > .git/$path
43 done
44 rm -f .git/packed-refs
45}
46
47unpack_refs
48
49# turn tag heads into tags
50cp .git/refs/remotes/tags/* .git/refs/tags/
51git branch -a | grep tags/ | sed 's,.*remotes/,,' | xargs -n1 git branch -rd
52
53# prune empty commits
54git filter-branch --prune-empty -- --all
55
56# prepare commit message translation script
57cat <<\END >$WRK_DIR/msg.pl
58#!/usr/bin/perl
59
60my $inp = join '', <STDIN>;
61$inp =~ s/[\s\n\r]*^git-svn-id:[^\n]*?@(\d+).*/\n/sm;
62if (defined $1) {
63 $inp = "r$1 $inp";
64}
65print $inp;
66END
67chmod +x $WRK_DIR/msg.pl
68
69# cut git-svn-id lines and insert svn revno to the beginning of the first line
70git filter-branch --msg-filter $WRK_DIR/msg.pl -f -- --all
71
72# prepare parent translation script
73(
74 cat <<\END
75#!/usr/bin/perl
76
77# parent - tag
78my @a = qw(
79END
80
81 for t in `git tag -l`; do
82 id=`git show --format=oneline --quiet $t | awk '{print $1}'`
83 par=`git show --format=oneline --quiet $t^ | awk '{print $1}'`
84 echo "$par $id"
85 done
86
87 cat <<\END
88);
89my %map;
90while (@a) {
91 my ($parent, $tag) = splice @a, 0, 2;
92 $map{$parent} = $tag;
93}
94
95while(<STDIN>) {
96 if (/-p (\S{40})/) {
97 my $p = $1;
98 if (exists $map{$p} && $1 ne $map{$p}) {
99 s/\S{40}/$map{$p}/;
100 }
101 }
102 print;
103}
104END
105) >$WRK_DIR/parent.pl
106chmod +x $WRK_DIR/parent.pl
107
108# remove tag branches (reparent the following commits on the tagged ones)
109git filter-branch --parent-filter $WRK_DIR/parent.pl -f -- --all
110
111# all filter-branch loops are done, remove original refs
112git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
113
114# clean repo
115git reflog expire --expire=now --all
116git gc --prune=now
117
118# prepare for second refs manipulation
119unpack_refs
120
121# turn remotely-tracked branches into heads, remove unused refs
122rm -Rf .git/refs/remotes/{trunk,tags}
123mv .git/refs/remotes/* .git/refs/heads/
124rm -Rf .git/refs/{remotes,original}
125
126# set repo description
127echo "RackTables is a datacenter asset management system" > .git/description
128
129cd `dirname $RESULT_DIR`
130
131# make bare copy
132git clone --bare file://$GIT_ROOT `basename $RESULT_DIR`