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