af35bf358d3f85eeec029957834d1962a543a92e
[xonotic/xonotic.git] / all
1 #!/bin/sh
2 # vim: filetype=zsh
3
4 set -e
5
6 d00=`pwd`
7 while ! [ -f ./all ]; do
8         if [ x"`pwd`" = x"/" ]; then
9                 echo "Cannot find myself."
10                 echo "Please run this script with the working directory inside a Xonotic checkout."
11                 exit 1
12         fi
13         cd ..
14 done
15 d0=`pwd`
16 SELF="$d0/all"
17
18 # If we are on WINDOWS:
19 case "$0" in
20         all|*/all)
21                 case "`uname`" in
22                         MINGW*|Win*)
23                                 # Windows hates users. So this script has to copy itself elsewhere first...
24                                 tname=
25                                 cp "$SELF" ../all.xonotic.sh
26                                 export WE_HATE_OUR_USERS=1
27                                 exec ../all.xonotic.sh "$@"
28                                 ;;
29                 esac
30                 ;;
31 esac
32
33 msg()
34 {
35         echo "\e[1m$*\e[m"
36 }
37
38 checksum()
39 {
40         if [ -x /usr/bin/md5sum ]; then
41                 /usr/bin/md5sum "$@"
42         elif [ -x /bin/md5sum ]; then
43                 /bin/md5sum "$@"
44         elif [ -x /usr/bin/cksum ]; then
45                 /usr/bin/cksum "$@"
46         else
47                 echo "NOCHECKSUM"
48         fi
49 }
50
51 self=`checksum "$SELF"`
52 checkself()
53 {
54         self_new=`checksum "$SELF"`
55         if [ x"$self" != x"$self_new" ]; then
56                 msg "./all has changed."
57                 if [ -z "$XONOTIC_FORBID_RERUN_ALL" ]; then
58                         msg "Rerunning the requested operation to make sure."
59                         export XONOTIC_FORBID_RERUN_ALL=1
60                         exec "$SELF" "$@"
61                 else
62                         msg "Please try $SELF update, and then retry your requested operation."
63                         exit 1
64                 fi
65         fi
66         return 0
67 }
68
69 verbose()
70 {
71         msg "+ $*"
72         "$@"
73 }
74
75 visible_repo_name()
76 {
77         case "$1" in
78                 .)
79                         echo "the root directory"
80                         ;;
81                 *)
82                         echo "\"$1\""
83                         ;;
84         esac
85 }
86
87 check_mergeconflict()
88 {
89         if git ls-files -u | grep ' 1   '; then
90                 echo
91                 echo "MERGE CONFLICT."
92                 echo "change into the \"$1\" project directory, and then:"
93                 echo "- edit the files mentioned above with your favorite editor,"
94                 echo "  and fix the conflicts (marked with <<<<<<< blocks)"
95                 echo "- for binary files, you can select the files using"
96                 echo "  git checkout --ours or git checkout --theirs"
97                 echo "- when done with a file, 'git add' the file"
98                 echo "- when done, 'git commit'"
99                 echo
100                 exit 1
101         fi
102 }
103
104 enter()
105 {
106         $2 cd "$1"
107         check_mergeconflict "$1"
108 }
109
110 repos_urls="
111 .                             |                                                   | master
112 data/xonotic-data.pk3dir      |                                                   | master
113 data/xonotic-maps.pk3dir      |                                                   | master
114 data/xonotic-music.pk3dir     |                                                   | master
115 data/xonotic-nexcompat.pk3dir |                                                   | master
116 mediasource                   |                                                   | master
117 darkplaces                    |                                                   | div0-stable
118 fteqcc                        | git://github.com/Blub/qclib.git                   | master
119 div0-gittools                 | git://git.icculus.org/divverent/div0-gittools.git | master
120 netradiant                    |                                                   | master
121 "
122 # todo: in darkplaces, change repobranch to div0-stable
123
124 repos=`echo "$repos_urls" | grep . | cut -d '|' -f 1 | tr -d ' '`
125
126 base=`git config remote.origin.url`
127 base=${base%xonotic.git}
128
129 repourl()
130 {
131         t=`echo "$repos_urls" | grep "^$1 " | cut -d '|' -f 2 | tr -d ' '`
132         if [ -n "$t" ]; then
133                 case "$t" in
134                         *://*)
135                                 echo "$t"
136                                 ;;
137                         *)
138                                 echo "$base$t"
139                                 ;;
140                 esac
141         else
142                 if [ x"$1" = x"." ]; then
143                         echo "$base""xonotic.git"
144                 else
145                         echo "$base${1##*/}.git"
146                 fi
147         fi
148 }
149
150 repobranch()
151 {
152         t=`echo "$repos_urls" | grep "^$1 " | cut -d '|' -f 3 | tr -d ' '`
153         if [ -n "$t" ]; then
154                 echo "$t"
155         else
156                 echo "master"
157         fi
158 }
159
160 repos=`for d in $repos; do
161         p="${d%dir}"
162         if [ x"$p" = x"$d" ] || [ -d "$d" ] || ! [ -f "$p" ]; then
163                 echo "$d"
164         fi
165 done`
166
167 if [ "$#" = 0 ]; then
168         set -- help
169 fi
170 cmd=$1
171 shift
172
173 case "$cmd" in
174         update|pull)
175                 allow_pull=true
176                 if [ x"$1" = x"-N" ]; then
177                         allow_pull=false
178                 fi
179                 for d in $repos; do
180                         url=`repourl "$d"`
181                         branch=`repobranch "$d"`
182                         if [ -d "$d0/$d" ]; then
183                                 if $allow_pull; then
184                                         enter "$d0/$d" verbose
185                                         verbose git config remote.origin.url "$url"
186                                         verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
187                                                 # TODO remove this line later
188
189                                         verbose git config core.autocrlf false
190                                         verbose git config core.safecrlf false # we don't NEED that...
191
192                                         r=`git symbolic-ref HEAD`
193                                         r=${r#refs/heads/}
194                                         if git config branch.$r.remote >/dev/null 2>&1; then
195                                                 if ! verbose git pull; then
196                                                         check_mergeconflict "$d"
197                                                         echo "Pulling failed. Press ENTER to continue, or Ctrl-C to abort."
198                                                         read -r DUMMY
199                                                 fi
200                                         fi
201
202                                         cd "$d00"
203                                         checkself "$cmd" "$@"
204                                         cd "$d0/$d"
205                                         verbose git remote prune origin
206                                         cd "$d0"
207                                 fi
208                         else
209                                 verbose git clone "$url" "$d0/$d"
210                                 enter "$d0/$d" verbose
211                                 verbose git checkout "$branch"
212                                 cd "$d0"
213                         fi
214                 done
215                 ;;
216         checkout|switch)
217                 remote=$1
218                 branch=$2
219                 if [ -z "$branch" ]; then
220                         branch=$remote
221                         remote=origin
222                 fi
223                 exists=false
224                 for d in $repos; do
225                         enter "$d0/$d" verbose
226                         if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
227                                 exists=true
228                                 verbose git checkout "$branch"
229                         elif git rev-parse "refs/remotes/$remote/$branch" >/dev/null 2>&1; then
230                                 exists=true
231                                 verbose git checkout --track -b "$branch" "$remote/$branch"
232                         else
233                                 verbose git checkout "`repobranch "$d"`"
234                         fi
235                         cd "$d00"
236                         checkself "$cmd" "$@"
237                         cd "$d0"
238                 done
239                 if ! $exists; then
240                         echo "The requested branch was not found in any repository."
241                 fi
242                 exec "$SELF" branch
243                 ;;
244         branch)
245                 remote=$1
246                 branch=$2
247                 srcbranch=$3
248                 if [ -z "$branch" ]; then
249                         branch=$remote
250                         remote=origin
251                 fi
252                 if [ -z "$branch" ]; then
253                         for d in $repos; do
254                                 enter "$d0/$d"
255                                 r=`git symbolic-ref HEAD`
256                                 r=${r#refs/heads/}
257                                 echo "$d is at $r"
258                                 cd "$d0"
259                         done
260                 else
261                         for d in $repos; do
262                                 dv=`visible_repo_name "$d"`
263                                 enter "$d0/$d" verbose
264                                 a=
265                                 if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
266                                         echo "Already having this branch in $dv."
267                                 else
268                                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
269                                                 echo "Branch in $dv?"
270                                                 read -r a
271                                         done
272                                         if [ x"$a" = x"y" ]; then
273                                                 if [ -n "$srcbranch" ]; then
274                                                         b=$srcbranch
275                                                 else
276                                                         b="`repobranch "$d"`"
277                                                 fi
278                                                 # TODO do this without pushing
279                                                 verbose git push "$remote" "$b":"$branch"
280                                                 verbose git checkout --track -b "$branch" "$remote/$branch"
281                                         fi
282                                 fi
283                                 cd "$d0"
284                         done
285                         "$SELF" branch
286                 fi
287                 ;;
288         branches)
289                 for d in $repos; do
290                         enter "$d0/$d"
291                         echo "In $d:"
292                         git branch -a -v -v | cut -c 3- | while read -r BRANCH REV UPSTREAM TEXT; do
293                                 case "$UPSTREAM" in
294                                         \[*)
295                                                 UPSTREAM=${UPSTREAM#\[}
296                                                 UPSTREAM=${UPSTREAM%\]}
297                                                 UPSTREAM=${UPSTREAM%:*}
298                                                 ;;
299                                         *)
300                                                 TEXT="$UPSTREAM $TEXT"
301                                                 UPSTREAM=
302                                                 ;;
303                                 esac
304                                 if [ x"$REV" = x"->" ]; then
305                                         continue
306                                 fi
307                                 BRANCH=${BRANCH#remotes/}
308                                 echo -n "  $BRANCH"
309                                 if [ -n "$UPSTREAM" ]; then
310                                         echo -n " (tracking $UPSTREAM)"
311                                 fi
312                                 #echo " $TEXT"
313                                 echo
314                         done
315                 done
316                 ;;
317         branches_short)
318                 for d in $repos; do
319                         cd "$d0/$d" # am in a pipe, shouldn't use enter
320                         git branch -a -v -v | cut -c 3- | sed "s,^,$d ,"
321                         cd "$d0"
322                 done | {
323                         branches_list=
324                         # branches_repos_*=
325                         while read -r d BRANCH REV UPSTREAM TEXT; do
326                                 case "$UPSTREAM" in
327                                         \[*)
328                                                 UPSTREAM=${UPSTREAM#\[}
329                                                 UPSTREAM=${UPSTREAM%\]}
330                                                 UPSTREAM=${UPSTREAM%:*}
331                                                 ;;
332                                         *)
333                                                 TEXT="$UPSTREAM $TEXT"
334                                                 UPSTREAM=
335                                                 ;;
336                                 esac
337                                 if [ x"$REV" = x"->" ]; then
338                                         continue
339                                 fi
340                                 BRANCH=${BRANCH#remotes/}
341                                 ID=`echo "$BRANCH" | tr -c "A-Za-z0-9." "_"`
342                                 branches_list="$branches_list $BRANCH" # TEH SORT MAKEZ IT UNIEQ
343                                 eval "r=\$branches_repos_$ID"
344                                 r="$r $d:$UPSTREAM"
345                                 eval "branches_repos_$ID=\$r"
346                         done
347                         echo -n "$branches_list" | xargs -n 1 echo | sort -u | while IFS= read -r BRANCH; do
348                                 ID=`echo "$BRANCH" | tr -c "A-Za-z0-9." "_"`
349                                 eval "r=\$branches_repos_$ID"
350                                 echo "$BRANCH: $r"
351                         done
352                 }
353                 ;;
354         merge)
355                 for d in $repos; do
356                         dv=`visible_repo_name "$d"`
357                         enter "$d0/$d" verbose
358                         r=`git symbolic-ref HEAD`
359                         r=${r#refs/heads/}
360                         if git log HEAD..origin/"`repobranch "$d"`" | grep .; then
361                                 # we have uncommitted changes
362                                 a=
363                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
364                                         echo "Could merge from \"`repobranch "$d"`\" into \"$r\" in $dv. Do it?"
365                                         read -r a
366                                 done
367                                 if [ x"$a" = x"y" ]; then
368                                         if ! verbose git merge origin/"`repobranch "$d"`"; then
369                                                 check_mergeconflict "$d"
370                                                 exit 1 # this should ALWAYS be fatal
371                                         fi
372                                 fi
373                         fi
374                         cd "$d0"
375                 done
376                 ;;
377         push|commit)
378                 submit=$1
379                 for d in $repos; do
380                         dv=`visible_repo_name "$d"`
381                         enter "$d0/$d" verbose
382                         r=`git symbolic-ref HEAD`
383                         r=${r#refs/heads/}
384                         if git diff HEAD | grep .; then
385                                 # we have uncommitted changes
386                                 a=
387                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
388                                         echo "Uncommitted changes in \"$r\" in $dv. Commit?"
389                                         read -r a
390                                 done
391                                 if [ x"$a" = x"y" ]; then
392                                         verbose git commit -a
393                                 fi
394                         fi
395                         rem=`git config "branch.$r.remote" || echo origin`
396                         if { git log "$rem/$r".."$r" || git log origin/"`repobranch "$d"`".."$r"; } | grep .; then
397                                 a=
398                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
399                                         echo "Push \"$r\" in $dv?"
400                                         read -r a
401                                 done
402                                 if [ x"$a" = x"y" ]; then
403                                         verbose git push "$rem" HEAD
404                                 fi
405                         fi
406                         if [ x"$submit" = x"-s" ]; then
407                                 case "$r" in
408                                         */*)
409                                                 verbose git push "$rem" HEAD:"${r%%/*}/finished/${r#*/}"
410                                                 ;;
411                                 esac
412                         fi
413                         cd "$d0"
414                 done
415                 ;;
416         compile)
417                 if [ -n "$WE_HATE_OUR_USERS" ]; then
418                         TARGETS="sv-debug cl-debug"
419                 else
420                         TARGETS="sv-debug cl-debug sdl-debug"
421                 fi
422                 case "$1" in
423                         -c)
424                                 clean=true
425                                 shift
426                                 ;;
427                         *)
428                                 clean=false
429                                 ;;
430                 esac
431                 case "$1" in
432                         sdl)
433                                 TARGETS="sdl-debug"
434                                 shift
435                                 ;;
436                         glx|agl|wgl)
437                                 TARGETS="cl-debug"
438                                 shift
439                                 ;;
440                         dedicated)
441                                 TARGETS="sv-debug"
442                                 shift
443                                 ;;
444                 esac
445                 if [ -z "$MAKEFLAGS" ]; then
446                         if [ -f /proc/cpuinfo ]; then
447                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
448                                 if [ $ncpus -gt 1 ]; then
449                                         MAKEFLAGS=-j$ncpus
450                                 fi
451                         fi
452                         case "`uname`" in
453                                 Linux|*BSD)
454                                         MAKEFLAGS="$MAKEFLAGS DP_LINK_TO_LIBJPEG=1"
455                                         ;;
456                         esac
457                         if [ -n "$WE_HATE_OUR_USERS" ]; then
458                                 MAKEFLAGS="$MAKEFLAGS DP_MAKE_TARGET=mingw"
459                         fi
460                 fi
461                 enter "$d0/fteqcc" verbose
462                 if $clean; then
463                         verbose make $MAKEFLAGS clean
464                 fi
465                 verbose make $MAKEFLAGS
466                 enter "$d0/data/xonotic-data.pk3dir" verbose
467                 if $clean; then
468                         verbose make $MAKEFLAGS clean
469                 fi
470                 verbose make FTEQCC="$d0/fteqcc/fteqcc.bin" "$@" $MAKEFLAGS
471                 enter "$d0/darkplaces" verbose
472                 if $clean; then
473                         verbose make $MAKEFLAGS clean
474                 fi
475                 for T in $TARGETS; do
476                         verbose make $MAKEFLAGS "$@" "$T"
477                 done
478                 ;;
479         run)
480                 if [ -n "$WE_HATE_OUR_USERS" ]; then
481                         client=
482                         export PATH="$d0/misc/buildfiles/w32:$PATH"
483                 elif [ x"`uname`" = x"Darwin" ]; then
484                         export DYLD_LIBRARY_PATH="$d0/misc/buildfiles/osx/Nexuiz.app/Contents/MacOS"
485                         client=-sdl
486                 else
487                         client=-sdl
488                 fi
489                 case "$1" in
490                         sdl|glx|agl|dedicated)
491                                 client=-$1
492                                 shift
493                                 ;;
494                         wgl)
495                                 client=
496                                 shift
497                                 ;;
498                 esac
499                 if ! [ -x "darkplaces/darkplaces$client" ]; then
500                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
501                                 client=$client.exe
502                         else
503                                 echo "Client darkplaces/darkplaces$client not found, aborting"
504                                 exit 1
505                         fi
506                 fi
507                 set -- "darkplaces/darkplaces$client" -nexuiz -customgamename Xonotic -customgamedirname1 data -customgamedirname2 "" -customgamescreenshotname xonotic -customgameuserdirname xonotic "$@"
508                 if [ -n "$USE_GDB" ]; then
509                         set -- gdb --args "$@"
510                 fi
511                 "$@"
512                 ;;
513         each|foreach)
514                 for d in $repos; do
515                         if verbose cd "$d0/$d"; then
516                                 verbose "$@"
517                                 cd "$d0"
518                         fi
519                 done
520                 ;;
521         save-patches)
522                 outfile=$1
523                 patchdir=`mktemp -d -t save-patches.XXXXXX`
524                 for d in $repos; do
525                         enter "$d0/$d" verbose
526                         git branch -v -v | cut -c 3- | {
527                                 i=0
528                                 while read -r BRANCH REV UPSTREAM TEXT; do
529                                         case "$UPSTREAM" in
530                                                 \[*)
531                                                         UPSTREAM=${UPSTREAM#\[}
532                                                         UPSTREAM=${UPSTREAM%\]}
533                                                         UPSTREAM=${UPSTREAM%:*}
534                                                         TRACK=true
535                                                         ;;
536                                                 *)
537                                                         UPSTREAM=origin/"`repobranch "$d"`"
538                                                         TRACK=false
539                                                         ;;
540                                         esac
541                                         if [ x"$REV" = x"->" ]; then
542                                                 continue
543                                         fi
544                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
545                                                 echo "$d" > "$patchdir/$i/info.txt"
546                                                 echo "$BRANCH" >> "$patchdir/$i/info.txt"
547                                                 echo "$UPSTREAM" >> "$patchdir/$i/info.txt"
548                                                 echo "$TRACK" >> "$patchdir/$i/info.txt"
549                                                 i=$(($i+1))
550                                         else
551                                                 rm -rf "$patchdir/$i"
552                                         fi
553                                 done
554                         }
555                 done
556                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
557                 rm -rf "$patchdir"
558                 ;;
559         restore-patches)
560                 infile=$1
561                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
562                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
563                 # detach the head
564                 for P in "$patchdir"/*/info.txt; do
565                         D=${P%/info.txt}
566                         exec 3<"$P"
567                         read -r d <&3
568                         read -r BRANCH <&3
569                         read -r UPSTREAM <&3
570                         read -r TRACK <&3
571                         verbose git checkout HEAD^0
572                         verbose git branch -D "$BRANCH"
573                         if [ x"$TRACK" = x"true" ]; then
574                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
575                         else
576                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
577                         fi
578                         verbose git am "$D"
579                 done
580                 rm -rf "$patchdir"
581                 ;;
582         admin-merge)
583                 if [ "$#" = 1 ]; then
584                         set -- "${1%%/*}" "${1#*/}"
585                 fi
586                 for d in $repos; do
587                         enter "$d0/$d" verbose
588                         git rev-parse "$1/$2" || continue
589                         # 1. review
590                         {
591                                 git log HEAD.."$1/$2"
592                                 git diff HEAD..."$1/$2"
593                         } | less
594                         a=
595                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
596                                 echo "Merge \"$1/$2\" into `git symbolic-ref HEAD` of $d?"
597                                 read -r a
598                         done
599                         if [ x"$a" = x"y" ]; then
600                                 git merge "$1/$2"
601                                 cd "$d0"
602                                 a=
603                                 if ! "$SELF" compile; then
604                                         a=n
605                                 fi
606                                 cd "$d0/$d"
607                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
608                                         echo "Still merge \"$1/$2\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."
609                                         read -r a
610                                 done
611                                 if [ x"$a" = x"y" ]; then
612                                         git push origin HEAD
613                                         git push "$1" :"$2"
614                                 else
615                                         git reset --hard HEAD@{1}
616                                 fi
617                         fi
618                 done
619                 ;;
620         *)
621                 echo "Usage:"
622                 echo "  $SELF pull"
623                 echo "  $SELF merge"
624                 echo "  $SELF push [-s]"
625                 echo "  $SELF branches"
626                 echo "  $SELF branch [<remote>] <branchname>"
627                 echo "  $SELF branch <remote> <branchname> <srcbranchname>"
628                 echo "  $SELF checkout [<remote>] <branchname>"
629                 echo "  $SELF compile [-c] [<client>] <options>"
630                 echo "  $SELF run [<client>] <options>"
631                 echo "  $SELF each <command>"
632                 ;;
633 esac