mktar: Use `wc` instead of `du` in summary message
[sunny256-utils.git] / build-git
blob7a846d7149f8d26e4ac0083afcb0259a655ca4e3
1 #!/usr/bin/env bash
3 #=======================================================================
4 # build-git
5 # File ID: 7075da30-98d2-11de-b3de-00248cd5cf1e
7 # Compile and install git(1).
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #=======================================================================
13 progname=build-git
14 VERSION=0.4.0
16 ARGS="$(getopt -o "\
20 " -l "\
21 help,\
22 no-net,\
23 quiet,\
24 verbose,\
25 version,\
26 " -n "$progname" -- "$@")"
27 test "$?" = "0" || exit 1
28 eval set -- "$ARGS"
30 opt_help=0
31 opt_no_net=0
32 opt_quiet=0
33 opt_verbose=0
34 while :; do
35 case "$1" in
36 -h|--help) opt_help=1; shift ;;
37 --no-net) opt_no_net=1; shift ;;
38 -q|--quiet) opt_quiet=$(($opt_quiet + 1)); shift ;;
39 -v|--verbose) opt_verbose=$(($opt_verbose + 1)); shift ;;
40 --version) echo $progname $VERSION; exit 0 ;;
41 --) shift; break ;;
42 *) echo $progname: Internal error >&2; exit 1 ;;
43 esac
44 done
45 opt_verbose=$(($opt_verbose - $opt_quiet))
47 if test "$opt_help" = "1"; then
48 test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
49 cat <<END
51 Compile and install git(1). Default action is to build from the newest
52 revision on 'master'. Another branch or tag can be specified as first
53 argument.
55 Usage: $progname [options] [branch]
57 Options:
59 -h, --help
60 Show this help.
61 --no-net
62 Don't fetch or push, use what's present in the local repo.
63 -q, --quiet
64 Be more quiet. Can be repeated to increase silence.
65 -v, --verbose
66 Increase level of verbosity. Can be repeated.
67 --version
68 Print version information.
70 END
71 exit 0
74 lockdir=$HOME/.Build-git.LOCK
76 myexit() {
77 rmdir $lockdir || echo $progname: $lockdir: Cannot remove lockdir >&2
78 exit $1
81 trap "myexit 1" INT TERM
82 mkdir $lockdir || {
83 echo $progname: $lockdir: Cannot create lockdir >&2
84 exit 1
87 rcfile=$HOME/.build-gitrc
88 origin_url=git://git.kernel.org/pub/scm/git/git.git
90 # Directory where the git build happens
91 builddir=$HOME/src/other/git/build-git
93 # Prefix to directory tree where git will be installed. You can change
94 # it to for example $HOME/local if you don’t have root access.
95 pref=/usr/local
97 # If you don’t have sudo rights or you don’t need it at the location in
98 # the file system, clear the value of the $sudo variable
99 sudo=sudo
101 # Local name of remote master
102 local_master=master
104 # Name of remote master
105 remote_master=origin/master
107 # Set to 0 to skip ./configure and use Makefile in git.git instead
108 use_configure=1
109 configure_opts=
111 makeflags=
112 make_doc=1
113 make_info=1
114 run_tests=1
115 hname=$(hostname)
117 [ -e $rcfile ] && . $rcfile
119 if [ -n "$1" ]; then
120 local_master=$1
123 is_official_branch() {
124 echo -n $1 | grep -Eq '^(master|maint|next|pu|todo)$' &&
125 return 0 || return 1
128 fetch_remotes() {
129 git remote | grep -q '^origin$' || git remote add origin $origin_url
130 git remote | grep -q '^kernelorg$' ||
131 git remote add kernelorg git://git.kernel.org/pub/scm/git/git.git
132 git remote | grep -q '^gitster$' || {
133 git remote add gitster git://github.com/gitster/git.git
134 git config --add remote.gitster.fetch +refs/notes/*:refs/notes/*
136 git remote | grep -q '^gitlab$' ||
137 git remote add gitlab git@gitlab.com:oyvholm/git.git
138 git remote | grep -q '^peff$' ||
139 git remote add peff git://github.com/peff/git.git
140 git remote | grep -q '^sunbase$' ||
141 git remote add sunbase \
142 sunny@sunbase.org:/home/sunny/repos/Git-other/git.git
143 if test "$opt_no_net" = "0"; then
144 echo ================= git fetch =================
145 echo ===== origin =====
146 until git fetch origin; do
147 echo $progname: Fetch error from origin, retrying >&2
148 sleep 2
149 done
150 # git fetch --all arrived in v1.6.6, and that’s too recent to use.
151 for f in $(git remote | grep -v '^origin$'); do
152 echo ===== $f =====
153 git fetch $f
154 done
155 for f in maint master next pu todo; do
156 git branch | cut -c 3- | grep -q ^$f\$ || git branch $f origin/$f
157 done
161 commit_tree() {
162 git log --color --graph --pretty=format:'%Cred%h %Cblue%p%Creset '\
163 '-%C(yellow)%d%Creset %s %Cgreen(%cd %Cblue%an%Cgreen)%Creset' \
164 --abbrev-commit $1
167 enable_sudo() {
168 until $sudo echo Password OK | grep -q "Password OK"; do
170 done
173 push_changes() {
174 if test "$opt_no_net" = "0"; then
175 for f in bellmann loc-repo passp sunbase gitlab rsync-net; do
176 git remote | grep -q "^$f\$" && {
177 echo ==== push changes to $f ====
178 git push -f $f master maint next pu todo
180 done
181 for f in loc-repo passp sunbase rsync-net; do
182 git remote | grep -q "^$f\$" && {
183 echo ==== push tags to $f ====
184 git push --tags $f
186 done
187 echo ==== push finished ====
189 lpar_git
192 print_timestamp() {
193 date +"%Y-%m-%d %H:%M:%S%z"
196 update_branches() {
197 git checkout $(git log -1 --format=%H) 2>/dev/null
198 echo -n "master: " >&2
199 git push . origin/master:master || {
200 echo $progname: master branch did not fast-forward, aborting >&2
201 git checkout -
202 myexit 1
204 for f in maint next pu todo; do
205 echo -n "$f: " >&2
206 git push -f . origin/$f:$f
207 done
208 git checkout -f $local_master
211 lpar_git() {
212 [ -f $HOME/src/git/lpar/git.lpar ] && lpar
215 [ -z "`git --version | grep '^git version '`" ] && {
216 echo $progname: You need to have git installed to use this script. >&2
217 myexit 1
220 rmdir $builddir 2>/dev/null
221 if [ ! -d $builddir/. ]; then
222 mkdir -p $builddir || {
223 echo $progname: $builddir: Cannot create directory
224 myexit 1
226 rmdir $builddir
227 echo ================= git clone =================
228 git clone $origin_url $builddir
229 cd $builddir || { echo $progname: $builddir: Cannot chdir >&2; myexit 1; }
230 git config lpar.name git
231 for f in maint next pu todo; do
232 git branch -t $f origin/$f || {
233 echo $progname: $f: Could not create branch >&2
234 myexit 1
236 done
238 cd $builddir || { echo $progname: $builddir: Cannot chdir >&2; myexit 1; }
239 GIT_PAGER=cat git status --porcelain | grep . && {
240 echo $progname: $builddir is not clean, aborting >&2
241 myexit 1
243 curr_git_ver=$(
244 cd $builddir &&
245 (git tag | grep compiled-$hname-2 | tail -1) || echo UNKNOWN
247 lpar_git
249 echo
250 echo Variables:
251 echo
252 echo "curr_git_ver = \"$curr_git_ver\" ($(
253 cd $builddir
254 git describe --long --match 'v[12]*' $curr_git_ver
256 echo "rcfile = \"$rcfile\" ($([ -e $rcfile ] || echo -n "not ")found)"
257 echo "builddir = \"$builddir\""
258 echo "pref = \"$pref\""
259 echo "sudo = \"$sudo\""
260 echo "local_master = \"$local_master\""
261 echo "remote_master = \"$remote_master\""
262 echo "makeflags = \"$makeflags\""
263 echo "make_doc = \"$make_doc\""
264 echo "make_info = \"$make_info\""
265 echo "hname = \"$hname\""
266 echo "use_configure = \"$use_configure\""
267 echo "configure_opts = \"$configure_opts\""
268 echo
270 git checkout $local_master || { echo Cannot check out branch >&2; myexit 1; }
271 if [ ! -e GIT-VERSION-GEN ]; then
272 # Paranoia check
273 echo $progname: Didn’t find GIT-VERSION-GEN. That’s strange, aborting.
274 myexit 1
276 fetch_remotes
277 is_official_branch $local_master &&
278 destbranch=origin/$local_master || destbranch=$local_master
279 echo
280 if [ -n "$curr_git_ver" ]; then
281 echo ================= git status in `pwd` =================
282 GIT_PAGER=cat git status
283 echo
284 print_timestamp
285 unset choice
286 until [ "$choice" = "y" ]; do
287 echo
288 unset choice
289 echo $(git log --format=oneline $curr_git_ver..$destbranch | wc -l) \
290 "new commits available in range $curr_git_ver..$destbranch"
291 echo Going to compile git $(
292 git describe --long --match 'v[12]*' $destbranch
294 echo
295 echo If that looks okay to you, press \'y\' to start the build, or:
296 echo \'d\' to diff
297 echo \'ds\' to diff --stat
298 echo \'dw\' to word-diff
299 echo \'l\' to list log
300 echo \'lp\' to list log with patch
301 echo \'lt\' to list log with commit tree
302 echo \'lw\' to list log with patch using word diff
303 echo \'n\' to abort
304 echo \'p\' to push new commits
305 echo \'t\' to show commit tree
306 read choice
307 [ "$choice" = "d" ] && git diff $curr_git_ver $destbranch
308 [ "$choice" = "ds" ] && git diff --stat $curr_git_ver $destbranch
309 [ "$choice" = "dw" ] && git diff --word-diff $curr_git_ver $destbranch
310 [ "$choice" = "l" ] && git log --stat $curr_git_ver..$destbranch
311 [ "$choice" = "lp" ] && git log --patch $curr_git_ver..$destbranch
312 [ "$choice" = "lt" ] &&
313 git log --graph --stat $curr_git_ver..$destbranch
314 [ "$choice" = "lw" ] &&
315 git log --patch --word-diff $curr_git_ver..$destbranch
316 [ "$choice" = "n" ] && myexit 0
317 [ "$choice" = "p" ] && {
318 if test "$opt_no_net" = "0"; then
319 update_branches
320 push_changes
321 else
322 echo $progname: --no-net was specified, will not push >&2
325 [ "$choice" = "t" ] && commit_tree $curr_git_ver..$destbranch
326 done
327 else
328 unset choice
329 until [ "$choice" = "y" ]; do
330 echo -n Press \'y\' to start the build, or \'n\' to abort...
331 read choice
332 [ "$choice" = "n" ] && myexit 0
333 done
336 echo ================= git clean =================
337 git clean -fxd
338 echo ================= Update all branches =================
339 update_branches
340 vername=git.$local_master.`git describe --long --match 'v[12]*'`
341 dest=$pref/varprg/$vername
342 [ -d $dest/. ] && {
343 echo
344 echo "Sorry, no new git(1) for you this time."
345 echo You’ll have to stick with `git --version` for now.
346 push_changes
347 myexit 0
349 push_changes
350 if [ "$use_configure" = "1" ]; then
351 echo $progname: Creating ./configure
352 make configure
353 echo ==== ./configure --prefix=$dest $configure_opts
354 ./configure --prefix=$dest $configure_opts
356 if [ "$make_doc" = "1" ]; then
357 make_doc_str=doc
358 inst_doc_str="install-doc install-html"
359 else
360 make_doc_str=
361 inst_doc_str=
363 if [ "$make_info" = "1" ]; then
364 make_info_str=info
365 inst_info_str=install-info
366 else
367 make_info_str=
368 inst_info_str=
370 echo Compiling $vername
371 echo "==== make prefix=$dest $makeflags all" \
372 "$make_doc_str $make_info_str \|\| myexit"
373 make prefix=$dest $makeflags all $make_doc_str $make_info_str || myexit
374 if test "$run_tests" = "1"; then
375 echo ==== make $makeflags test
376 make $makeflags test
378 echo
379 echo Ready to install $(./git --version) from branch \"$local_master\"
380 unset choice
381 until test "$choice" = "y"; do
382 echo
383 print_timestamp
384 echo -n If all tests succeeded, press y to continue...
385 read choice
386 done
387 enable_sudo
388 echo "==== $sudo make prefix=$dest" \
389 "$makeflags install $inst_doc_str $inst_info_str"
390 $sudo make prefix=$dest $makeflags install $inst_doc_str $inst_info_str
391 echo ================= make install finished =================
392 $sudo mkdir -p $pref/{bin,prg,varprg}
393 $sudo rm $pref/prg/git
394 $sudo ln -svf ../varprg/$vername $pref/prg/git
395 $sudo ln -sv /etc $pref/prg/git/etc
396 cd $pref/bin || {
397 echo $progname: $pref/bin: Cannot chdir, aborting >&2
398 myexit 1
400 $sudo ln -svf ../prg/git/bin/* .
401 echo ================= Check that the thing works =================
402 hash -r
403 localgit=`./git --version`
404 globalgit=`git --version`
405 if [ "$localgit" = "$globalgit" ]; then
406 echo Congratulations with your shiny new $globalgit
407 cd $builddir || { echo $progname: $builddir: Cannot chdir >&2; myexit 1; }
408 git tag compiled-$hname-$(date -u +"%Y%m%dT%H%M%SZ")
409 test "$opt_no_net" = "0" && git push --tags sunbase
410 else
411 echo Uhm, something went wrong.
412 echo Current version of git : $globalgit
413 echo Expected version of git: $localgit
414 myexit 1
416 lpar_git
417 echo ================= symlink manpages =================
418 cd $pref/prg/git/share/man
419 mansects=`ls`
420 for f in $mansects; do
421 $sudo mkdir -p $pref/share/man/$f
422 cd $pref/share/man/$f || {
423 echo $progname: $pref/share/man/$f: Could not chdir, aborting >&2
424 myexit 1
427 $sudo ln -sf ../../../prg/git/share/man/$f/* .
428 done
429 if [ -d $pref/.git/. ]; then
430 echo ================= git commit the symlink =================
431 commitmsg=$(
432 echo $progname installed $globalgit on $(hostname)
433 echo
434 suuid -t commit,$progname
436 cd $pref/prg
437 $sudo git add git
438 echo Commit message:
439 echo $commitmsg
440 $sudo git commit -m "$commitmsg"
441 test "$opt_no_net" = "0" && git pa
444 myexit 0