-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathbuild-git
executable file
·444 lines (407 loc) · 12.6 KB
/
build-git
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#!/usr/bin/env bash
#=======================================================================
# build-git
# File ID: 7075da30-98d2-11de-b3de-00248cd5cf1e
#
# Compile and install git(1).
#
# Author: Øyvind A. Holm <[email protected]>
# License: GNU General Public License version 2 or later.
#=======================================================================
progname=build-git
VERSION=0.4.0
ARGS="$(getopt -o "\
h\
q\
v\
" -l "\
help,\
no-net,\
quiet,\
verbose,\
version,\
" -n "$progname" -- "$@")"
test "$?" = "0" || exit 1
eval set -- "$ARGS"
opt_help=0
opt_no_net=0
opt_quiet=0
opt_verbose=0
while :; do
case "$1" in
-h|--help) opt_help=1; shift ;;
--no-net) opt_no_net=1; shift ;;
-q|--quiet) opt_quiet=$(($opt_quiet + 1)); shift ;;
-v|--verbose) opt_verbose=$(($opt_verbose + 1)); shift ;;
--version) echo $progname $VERSION; exit 0 ;;
--) shift; break ;;
*) echo $progname: Internal error >&2; exit 1 ;;
esac
done
opt_verbose=$(($opt_verbose - $opt_quiet))
if test "$opt_help" = "1"; then
test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
cat <<END
Compile and install git(1). Default action is to build from the newest
revision on 'master'. Another branch or tag can be specified as first
argument.
Usage: $progname [options] [branch]
Options:
-h, --help
Show this help.
--no-net
Don't fetch or push, use what's present in the local repo.
-q, --quiet
Be more quiet. Can be repeated to increase silence.
-v, --verbose
Increase level of verbosity. Can be repeated.
--version
Print version information.
END
exit 0
fi
lockdir=$HOME/.Build-git.LOCK
myexit() {
rmdir $lockdir || echo $progname: $lockdir: Cannot remove lockdir >&2
exit $1
}
trap "myexit 1" INT TERM
mkdir $lockdir || {
echo $progname: $lockdir: Cannot create lockdir >&2
exit 1
}
rcfile=$HOME/.build-gitrc
origin_url=git://git.kernel.org/pub/scm/git/git.git
# Directory where the git build happens
builddir=$HOME/src/other/git/build-git
# Prefix to directory tree where git will be installed. You can change
# it to for example $HOME/local if you don’t have root access.
pref=/usr/local
# If you don’t have sudo rights or you don’t need it at the location in
# the file system, clear the value of the $sudo variable
sudo=sudo
# Local name of remote master
local_master=master
# Name of remote master
remote_master=origin/master
# Set to 0 to skip ./configure and use Makefile in git.git instead
use_configure=1
configure_opts=
makeflags=
make_doc=1
make_info=1
run_tests=1
hname=$(hostname)
[ -e $rcfile ] && . $rcfile
if [ -n "$1" ]; then
local_master=$1
fi
is_official_branch() {
echo -n $1 | grep -Eq '^(master|maint|next|pu|todo)$' &&
return 0 || return 1
}
fetch_remotes() {
git remote | grep -q '^origin$' || git remote add origin $origin_url
git remote | grep -q '^kernelorg$' ||
git remote add kernelorg git://git.kernel.org/pub/scm/git/git.git
git remote | grep -q '^gitster$' || {
git remote add gitster git://github.com/gitster/git.git
git config --add remote.gitster.fetch +refs/notes/*:refs/notes/*
}
git remote | grep -q '^gitlab$' ||
git remote add gitlab [email protected]:sunny256/git.git
git remote | grep -q '^peff$' ||
git remote add peff git://github.com/peff/git.git
git remote | grep -q '^sunbase$' ||
git remote add sunbase \
[email protected]:/home/sunny/repos/Git-other/git.git
if test "$opt_no_net" = "0"; then
echo ================= git fetch =================
echo ===== origin =====
until git fetch origin; do
echo $progname: Fetch error from origin, retrying >&2
sleep 2
done
# git fetch --all arrived in v1.6.6, and that’s too recent to use.
for f in $(git remote | grep -v '^origin$'); do
echo ===== $f =====
git fetch $f
done
for f in maint master next pu todo; do
git branch | cut -c 3- | grep -q ^$f\$ || git branch $f origin/$f
done
fi
}
commit_tree() {
git log --color --graph --pretty=format:'%Cred%h %Cblue%p%Creset '\
'-%C(yellow)%d%Creset %s %Cgreen(%cd %Cblue%an%Cgreen)%Creset' \
--abbrev-commit $1
}
enable_sudo() {
until $sudo echo Password OK | grep -q "Password OK"; do
:
done
}
push_changes() {
if test "$opt_no_net" = "0"; then
for f in bellmann loc-repo passp sunbase gitlab rsync-net; do
git remote | grep -q "^$f\$" && {
echo ==== push changes to $f ====
git push -f $f master maint next pu todo
}
done
for f in loc-repo passp sunbase rsync-net; do
git remote | grep -q "^$f\$" && {
echo ==== push tags to $f ====
git push --tags $f
}
done
echo ==== push finished ====
fi
lpar_git
}
print_timestamp() {
date +"%Y-%m-%d %H:%M:%S%z"
}
update_branches() {
git checkout $(git log -1 --format=%H) 2>/dev/null
echo -n "master: " >&2
git push . origin/master:master || {
echo $progname: master branch did not fast-forward, aborting >&2
git checkout -
myexit 1
}
for f in maint next pu todo; do
echo -n "$f: " >&2
git push -f . origin/$f:$f
done
git checkout -f $local_master
}
lpar_git() {
[ -f $HOME/src/git/lpar/git.lpar ] && lpar
}
[ -z "`git --version | grep '^git version '`" ] && {
echo $progname: You need to have git installed to use this script. >&2
myexit 1
}
rmdir $builddir 2>/dev/null
if [ ! -d $builddir/. ]; then
mkdir -p $builddir || {
echo $progname: $builddir: Cannot create directory
myexit 1
}
rmdir $builddir
echo ================= git clone =================
git clone $origin_url $builddir
cd $builddir || { echo $progname: $builddir: Cannot chdir >&2; myexit 1; }
git config lpar.name git
for f in maint next pu todo; do
git branch -t $f origin/$f || {
echo $progname: $f: Could not create branch >&2
myexit 1
}
done
fi
cd $builddir || { echo $progname: $builddir: Cannot chdir >&2; myexit 1; }
GIT_PAGER=cat git status --porcelain | grep . && {
echo $progname: $builddir is not clean, aborting >&2
myexit 1
}
curr_git_ver=$(
cd $builddir &&
(git tag | grep compiled-$hname-2 | tail -1) || echo UNKNOWN
)
lpar_git
echo
echo Variables:
echo
echo "curr_git_ver = \"$curr_git_ver\" ($(
cd $builddir
git describe --long --match 'v[12]*' $curr_git_ver
))"
echo "rcfile = \"$rcfile\" ($([ -e $rcfile ] || echo -n "not ")found)"
echo "builddir = \"$builddir\""
echo "pref = \"$pref\""
echo "sudo = \"$sudo\""
echo "local_master = \"$local_master\""
echo "remote_master = \"$remote_master\""
echo "makeflags = \"$makeflags\""
echo "make_doc = \"$make_doc\""
echo "make_info = \"$make_info\""
echo "hname = \"$hname\""
echo "use_configure = \"$use_configure\""
echo "configure_opts = \"$configure_opts\""
echo
git checkout $local_master || { echo Cannot check out branch >&2; myexit 1; }
if [ ! -e GIT-VERSION-GEN ]; then
# Paranoia check
echo $progname: Didn’t find GIT-VERSION-GEN. That’s strange, aborting.
myexit 1
fi
fetch_remotes
is_official_branch $local_master &&
destbranch=origin/$local_master || destbranch=$local_master
echo
if [ -n "$curr_git_ver" ]; then
echo ================= git status in `pwd` =================
GIT_PAGER=cat git status
echo
print_timestamp
unset choice
until [ "$choice" = "y" ]; do
echo
unset choice
echo $(git log --format=oneline $curr_git_ver..$destbranch | wc -l) \
"new commits available in range $curr_git_ver..$destbranch"
echo Going to compile git $(
git describe --long --match 'v[12]*' $destbranch
)
echo
echo If that looks okay to you, press \'y\' to start the build, or:
echo \'d\' to diff
echo \'ds\' to diff --stat
echo \'dw\' to word-diff
echo \'l\' to list log
echo \'lp\' to list log with patch
echo \'lt\' to list log with commit tree
echo \'lw\' to list log with patch using word diff
echo \'n\' to abort
echo \'p\' to push new commits
echo \'t\' to show commit tree
read choice
[ "$choice" = "d" ] && git diff $curr_git_ver $destbranch
[ "$choice" = "ds" ] && git diff --stat $curr_git_ver $destbranch
[ "$choice" = "dw" ] && git diff --word-diff $curr_git_ver $destbranch
[ "$choice" = "l" ] && git log --stat $curr_git_ver..$destbranch
[ "$choice" = "lp" ] && git log --patch $curr_git_ver..$destbranch
[ "$choice" = "lt" ] &&
git log --graph --stat $curr_git_ver..$destbranch
[ "$choice" = "lw" ] &&
git log --patch --word-diff $curr_git_ver..$destbranch
[ "$choice" = "n" ] && myexit 0
[ "$choice" = "p" ] && {
if test "$opt_no_net" = "0"; then
update_branches
push_changes
else
echo $progname: --no-net was specified, will not push >&2
fi
}
[ "$choice" = "t" ] && commit_tree $curr_git_ver..$destbranch
done
else
unset choice
until [ "$choice" = "y" ]; do
echo -n Press \'y\' to start the build, or \'n\' to abort...
read choice
[ "$choice" = "n" ] && myexit 0
done
fi
echo ================= git clean =================
git clean -fxd
echo ================= Update all branches =================
update_branches
vername=git.$local_master.`git describe --long --match 'v[12]*'`
dest=$pref/varprg/$vername
[ -d $dest/. ] && {
echo
echo "Sorry, no new git(1) for you this time."
echo You’ll have to stick with `git --version` for now.
push_changes
myexit 0
}
push_changes
if [ "$use_configure" = "1" ]; then
echo $progname: Creating ./configure
make configure
echo ==== ./configure --prefix=$dest $configure_opts
./configure --prefix=$dest $configure_opts
fi
if [ "$make_doc" = "1" ]; then
make_doc_str=doc
inst_doc_str="install-doc install-html"
else
make_doc_str=
inst_doc_str=
fi
if [ "$make_info" = "1" ]; then
make_info_str=info
inst_info_str=install-info
else
make_info_str=
inst_info_str=
fi
echo Compiling $vername
echo "==== make prefix=$dest $makeflags all" \
"$make_doc_str $make_info_str \|\| myexit"
make prefix=$dest $makeflags all $make_doc_str $make_info_str || myexit
if test "$run_tests" = "1"; then
echo ==== make $makeflags test
make $makeflags test
fi
echo
echo Ready to install $(./git --version) from branch \"$local_master\"
unset choice
until test "$choice" = "y"; do
echo
print_timestamp
echo -n If all tests succeeded, press y to continue...
read choice
done
enable_sudo
echo "==== $sudo make prefix=$dest" \
"$makeflags install $inst_doc_str $inst_info_str"
$sudo make prefix=$dest $makeflags install $inst_doc_str $inst_info_str
echo ================= make install finished =================
$sudo mkdir -p $pref/{bin,prg,varprg}
$sudo rm $pref/prg/git
$sudo ln -svf ../varprg/$vername $pref/prg/git
$sudo ln -sv /etc $pref/prg/git/etc
cd $pref/bin || {
echo $progname: $pref/bin: Cannot chdir, aborting >&2
myexit 1
}
$sudo ln -svf ../prg/git/bin/* .
echo ================= Check that the thing works =================
hash -r
localgit=`./git --version`
globalgit=`git --version`
if [ "$localgit" = "$globalgit" ]; then
echo Congratulations with your shiny new $globalgit
cd $builddir || { echo $progname: $builddir: Cannot chdir >&2; myexit 1; }
git tag compiled-$hname-$(date -u +"%Y%m%dT%H%M%SZ")
test "$opt_no_net" = "0" && git push --tags sunbase
else
echo Uhm, something went wrong.
echo Current version of git : $globalgit
echo Expected version of git: $localgit
myexit 1
fi
lpar_git
echo ================= symlink manpages =================
cd $pref/prg/git/share/man
mansects=`ls`
for f in $mansects; do
$sudo mkdir -p $pref/share/man/$f
cd $pref/share/man/$f || {
echo $progname: $pref/share/man/$f: Could not chdir, aborting >&2
myexit 1
}
pwd
$sudo ln -sf ../../../prg/git/share/man/$f/* .
done
if [ -d $pref/.git/. ]; then
echo ================= git commit the symlink =================
commitmsg=$(
echo $progname installed $globalgit on $(hostname)
echo
suuid -t commit,$progname
)
cd $pref/prg
$sudo git add git
echo Commit message:
echo $commitmsg
$sudo git commit -m "$commitmsg"
test "$opt_no_net" = "0" && git pa
fi
myexit 0