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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
#!/bin/bash
NEWSVNURL="file:///home/colin/svn-git/soft"
NEWSVNUUID=$(svn info $NEWSVNURL | grep "^Repository UUID: " | cut -d' ' -f3)
SOFTWARE=$1
if [ -z $SOFTWARE ]; then
echo "Missing software to convert..."
exit 1
fi
if [ -d $SOFTWARE-origin ]; then
echo "It seems the svn-git repository already exists ($SOFTWARE-origin)"
exit 1
fi
if [ -d $SOFTWARE.git ]; then
echo "It seems the converted git repository already exists ($SOFTWARE.git)"
exit 1
fi
skiprevisions=
skiprevisionsx="$2"
if [ -n "$skiprevisionsx" ]; then
for rev in $skiprevisionsx; do
rev=$(echo $rev | sed 's/r//g')
rev=$(( $rev + 0 ))
if [ $rev -gt 0 ]; then
skiprevisions="$skiprevisions $rev"
fi
done
fi
echo "Identified software name: $SOFTWARE"
echo "SVN Revisions to skip: $skiprevisions"
echo
git svn init $NEWSVNURL/$SOFTWARE --no-metadata --stdlayout $SOFTWARE-origin
cd $SOFTWARE-origin
revision=0
if [ -n "$skiprevisions" ]; then
for rev in $skiprevisions; do
git svn fetch -A ../authors-transform.txt -r $(( $revision + 1 )):$(( $rev - 1 ))
revision=$rev
done
fi
git svn fetch -A ../authors-transform.txt -r $(( $revision + 1 )):HEAD
git reset --hard trunk
echo
echo "done"
echo
echo "Now creating bare git repository"
git init --bare ../$SOFTWARE.git
git remote rm origin
git remote add origin ../$SOFTWARE.git
#git push --set-upstream master
git push origin master 'refs/remotes/*:refs/heads/*'
pushd ../$SOFTWARE.git
git branch -D trunk
git branch -D origin/master 2>/dev/null
# Tagging logic inspired by https://github.com/nothingmuch/git-svn-abandon/blob/master/git-svn-abandon-fix-refs
# Keep a map of tags and their original sha1 for the SQL database cerated below
declare -A tagmap
tags=$(git for-each-ref --format='%(refname)' refs/heads/tags | cut -d / -f 4)
for tag in $tags; do
ref="refs/heads/tags/$tag"
refsha1=$(git rev-parse "$ref")
reftreesha1=$(git rev-parse "$ref":)
# Find the oldest ancestor for which the tree is the same
parentref="$ref"
while [ $(git rev-parse --quiet --verify "$parentref"^:) = "$reftreesha1" ]; do
parentref="$parentref"^
done
parent=$(git rev-parse "$parentref")
# If this ancestor is in master then we can just tag it
# otherwise the tag has diverged from master and it's actually more like a
# branch than a tag
merge=$(git merge-base master $parent)
if [ "$merge" = "$parent" ]; then
targetref=$parent
else
targetref=$refsha1
fi
tagmap[$refsha1]=$tag
# create an annotated tag based on the last commit in the tag, and delete the "branchy" ref for the tag
git show -s --pretty='format:%s%n%n%b' "$ref" | \
env GIT_COMMITTER_NAME="$(git show -s --pretty='format:%an' "$ref")" \
GIT_COMMITTER_EMAIL="$(git show -s --pretty='format:%ae' "$ref")" \
GIT_COMMITTER_DATE="$(git show -s --pretty='format:%ad' "$ref")" \
GIT_AUTHOR_NAME="$(git show -s --pretty='format:%an' "$ref")" \
GIT_AUTHOR_EMAIL="$(git show -s --pretty='format:%ae' "$ref")" \
GIT_AUTHOR_DATE="$(git show -s --pretty='format:%ad' "$ref")" \
git tag -a -F - "$tag" "$targetref"
git update-ref -d "$ref"
done
# Implement a branch name policy
# 1. Branches matching ([1-3]) are renamed to distro/mga\1
# 2. Branches matching (20[0-9\.]+) are renamed to distro/mdv\1
# 3. Branches matching (mes[0-9].*) are renamed to distro/\1
# 4. All other branches are renamed to topic/\1 (excl. master)
branches=$(git for-each-ref --format='%(refname)' refs/heads | cut -d / -f 3-)
for branch in $branches; do
ref="refs/heads/$branch"
refsha1=$(git rev-parse "$ref")
reftreesha1=$(git rev-parse "$ref":)
# Find the oldest ancestor for which the tree is the same
parentref="$ref"
while [ $(git rev-parse --quiet --verify "$parentref"^:) = "$reftreesha1" ]; do
parentref="$parentref"^
done
parent=$(git rev-parse "$parentref")
# If this ancestor is in master then we can just squash it
# otherwise the branch has diverged from master and it's actually a proper
# branch
merge=$(git merge-base master $parent)
if [ "$merge" = "$parent" ]; then
git update-ref "$ref" $parent $refsha1
fi
if (echo $branch | grep -qE '^[0-3]$'); then
git branch -m $branch distro/mga$branch
elif (echo $branch | grep -qE '^20[0-9\.]+$'); then
git branch -m $branch distro/mdv$branch
elif (echo $branch | grep -qE '^mes[0-9].*$'); then
git branch -m $branch distro/$branch
elif [ "$branch" != "master" ]; then
git branch -m $branch topic/$branch
fi
done
git gc --aggressive
popd
# And finally we create some SQL for creating a nice revision map database
# CREATE TABLE refs (distro char(3) NOT NULL, soft varchar(255) NOT NULL, revision int(10) unsigned NOT NULL, sha1 char(40) NOT NULL, head varchar(255) NOT NULL);
# Parse a git-svn revmap file into SQL
# $1 = Name of revmap file
# $2 = Distro ('mdv' or 'mga')
# $3 = head name i.e. branch or tag name (only used when not processing trunk/master)
# $4 = Special SHA1 (last sha1 to look for if 'mdv', fake sha1 commit if 'mga')
parsesvnrevmap()
{
if [ ! -f "$1" ]; then
echo "No such file '$1'" >&2
exit 1
fi
for map in $(cat "$1" | xxd -c24 -g24 | cut -b 10-57); do
sha1=$(echo $map | cut -b 9-)
if [ "$sha1" = "0000000000000000000000000000000000000000" ]; then
continue
fi
if [ -n "$4" -a "$2" = "mga" -a "$sha1" = "$4" ]; then
continue
fi
rev=$(printf "%d" 0x$(echo $map | cut -b 1-8))
if [ -n "${tagmap[$sha1]}" ]; then
echo "INSERT INTO refs VALUES('$2', '$SOFTWARE', $rev, '', '${tagmap[$sha1]}');"
else
branch=$3
if [ -n "$branch" ]; then
if (echo $branch | grep -qE '^[0-3]$'); then
branch=distro/mga$branch
elif (echo $branch | grep -qE '^20[0-9\.]+$'); then
branch=distro/mdv$branch
elif (echo $branch | grep -qE '^mes[0-9].*$'); then
branch=distro/$branch
elif [ "$branch" != "master" ]; then
branch=topic/$branch
fi
fi
echo "INSERT INTO refs VALUES('$2', '$SOFTWARE', $rev, '$sha1', '$branch');"
fi
# Exit if we've reached our reset sha1 as any future revisions are not used
# by Mageia
if [ -n "$4" -a "$2" = "mdv" -a "$sha1" = "$4" ]; then
break
fi
done
}
echo
echo -n "Creating revision -> sha1 map SQL... "
sql="../$SOFTWARE-revmap.sql"
rm -f "$sql" "$sql".xz
# Mageia commits
revmap=".git/svn/refs/remotes/trunk/.rev_map.$NEWSVNUUID"
if [ -f "$revmap" ]; then
parsesvnrevmap "$revmap" "mga" "" $fakesha1 >>"$sql"
fi
for revmap in $(find .git/svn/refs/remotes/tags -name .rev_map.$NEWSVNUUID 2>/dev/null); do
# Note, still pass in the tag name in case the tag is really more of a branch...
parsesvnrevmap "$revmap" "mga" "$(echo $revmap | cut -d'/' -f6)" >>"$sql"
done
for revmap in $(find .git/svn/refs/remotes -maxdepth 2 -not -iwholename ".git/svn/refs/remotes/trunk/.rev_map.*" -name .rev_map.$NEWSVNUUID 2>/dev/null); do
parsesvnrevmap "$revmap" "mga" "$(echo $revmap | cut -d'/' -f5)" >>"$sql"
done
xz "$sql"
cd ..
echo "done"
|