76914d71c21f533576bc8444f2cfb159e7c48c16
[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                 for d in $repos; do
176                         url=`repourl "$d"`
177                         branch=`repobranch "$d"`
178                         if [ -d "$d0/$d" ]; then
179                                 enter "$d0/$d" verbose
180                                 verbose git config remote.origin.url "$url"
181                                 verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
182                                         # TODO remove this line later
183
184                                 verbose git config core.autocrlf false
185                                 verbose git config core.safecrlf false # we don't NEED that...
186
187                                 r=`git symbolic-ref HEAD`
188                                 r=${r#refs/heads/}
189                                 if git config branch.$r.remote >/dev/null 2>&1; then
190                                         if ! verbose git pull; then
191                                                 check_mergeconflict "$d"
192                                                 echo "Pulling failed. Press ENTER to continue, or Ctrl-C to abort."
193                                                 read -r DUMMY
194                                         fi
195                                 fi
196
197                                 cd "$d00"
198                                 checkself "$cmd" "$@"
199                                 cd "$d0/$d"
200                                 verbose git remote prune origin
201                                 cd "$d0"
202                         else
203                                 verbose git clone "$url" "$d0/$d"
204                                 enter "$d0/$d" verbose
205                                 verbose git checkout "$branch"
206                                 cd "$d0"
207                         fi
208                 done
209                 ;;
210         checkout|switch)
211                 remote=$1
212                 branch=$2
213                 if [ -z "$branch" ]; then
214                         branch=$remote
215                         remote=origin
216                 fi
217                 exists=false
218                 for d in $repos; do
219                         enter "$d0/$d" verbose
220                         if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
221                                 exists=true
222                                 verbose git checkout "$branch"
223                         elif git rev-parse "refs/remotes/$remote/$branch" >/dev/null 2>&1; then
224                                 exists=true
225                                 verbose git checkout --track -b "$branch" "$remote/$branch"
226                         else
227                                 verbose git checkout "`repobranch "$d"`"
228                         fi
229                         cd "$d00"
230                         checkself "$cmd" "$@"
231                         cd "$d0"
232                 done
233                 if ! $exists; then
234                         echo "The requested branch was not found in any repository."
235                 fi
236                 exec "$SELF" branch
237                 ;;
238         branch)
239                 remote=$1
240                 branch=$2
241                 srcbranch=$3
242                 if [ -z "$branch" ]; then
243                         branch=$remote
244                         remote=origin
245                 fi
246                 if [ -z "$branch" ]; then
247                         for d in $repos; do
248                                 enter "$d0/$d"
249                                 r=`git symbolic-ref HEAD`
250                                 r=${r#refs/heads/}
251                                 echo "$d is at $r"
252                                 cd "$d0"
253                         done
254                 else
255                         for d in $repos; do
256                                 dv=`visible_repo_name "$d"`
257                                 enter "$d0/$d" verbose
258                                 a=
259                                 if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
260                                         echo "Already having this branch in $dv."
261                                 else
262                                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
263                                                 echo "Branch in $dv?"
264                                                 read -r a
265                                         done
266                                         if [ x"$a" = x"y" ]; then
267                                                 if [ -n "$srcbranch" ]; then
268                                                         b=$srcbranch
269                                                 else
270                                                         b="`repobranch "$d"`"
271                                                 fi
272                                                 # TODO do this without pushing
273                                                 verbose git push "$remote" "$b":"$branch"
274                                                 verbose git checkout --track -b "$branch" "$remote/$branch"
275                                         fi
276                                 fi
277                                 cd "$d0"
278                         done
279                         "$SELF" branch
280                 fi
281                 ;;
282         branches)
283                 for d in $repos; do
284                         enter "$d0/$d"
285                         echo "In $d:"
286                         git branch -a -v -v | cut -c 3- | while read -r BRANCH REV UPSTREAM TEXT; do
287                                 case "$UPSTREAM" in
288                                         \[*)
289                                                 UPSTREAM=${UPSTREAM#\[}
290                                                 UPSTREAM=${UPSTREAM%\]}
291                                                 UPSTREAM=${UPSTREAM%:*}
292                                                 ;;
293                                         *)
294                                                 TEXT="$UPSTREAM $TEXT"
295                                                 UPSTREAM=
296                                                 ;;
297                                 esac
298                                 if [ x"$REV" = x"->" ]; then
299                                         continue
300                                 fi
301                                 BRANCH=${BRANCH#remotes/}
302                                 echo -n "  $BRANCH"
303                                 if [ -n "$UPSTREAM" ]; then
304                                         echo -n " (tracking $UPSTREAM)"
305                                 fi
306                                 #echo " $TEXT"
307                                 echo
308                         done
309                 done
310                 ;;
311         branches_short)
312                 for d in $repos; do
313                         cd "$d0/$d" # am in a pipe, shouldn't use enter
314                         git branch -a -v -v | cut -c 3- | sed "s,^,$d ,"
315                         cd "$d0"
316                 done | {
317                         branches_list=
318                         # branches_repos_*=
319                         while read -r d BRANCH REV UPSTREAM TEXT; do
320                                 case "$UPSTREAM" in
321                                         \[*)
322                                                 UPSTREAM=${UPSTREAM#\[}
323                                                 UPSTREAM=${UPSTREAM%\]}
324                                                 UPSTREAM=${UPSTREAM%:*}
325                                                 ;;
326                                         *)
327                                                 TEXT="$UPSTREAM $TEXT"
328                                                 UPSTREAM=
329                                                 ;;
330                                 esac
331                                 if [ x"$REV" = x"->" ]; then
332                                         continue
333                                 fi
334                                 BRANCH=${BRANCH#remotes/}
335                                 ID=`echo "$BRANCH" | tr -c "A-Za-z0-9." "_"`
336                                 branches_list="$branches_list $BRANCH" # TEH SORT MAKEZ IT UNIEQ
337                                 eval "r=\$branches_repos_$ID"
338                                 r="$r $d:$UPSTREAM"
339                                 eval "branches_repos_$ID=\$r"
340                         done
341                         echo -n "$branches_list" | xargs -n 1 echo | sort -u | while IFS= read -r BRANCH; do
342                                 ID=`echo "$BRANCH" | tr -c "A-Za-z0-9." "_"`
343                                 eval "r=\$branches_repos_$ID"
344                                 echo "$BRANCH: $r"
345                         done
346                 }
347                 ;;
348         merge)
349                 for d in $repos; do
350                         dv=`visible_repo_name "$d"`
351                         enter "$d0/$d" verbose
352                         r=`git symbolic-ref HEAD`
353                         r=${r#refs/heads/}
354                         if git log HEAD..origin/"`repobranch "$d"`" | grep .; then
355                                 # we have uncommitted changes
356                                 a=
357                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
358                                         echo "Could merge from \"`repobranch "$d"`\" into \"$r\" in $dv. Do it?"
359                                         read -r a
360                                 done
361                                 if [ x"$a" = x"y" ]; then
362                                         if ! verbose git merge origin/"`repobranch "$d"`"; then
363                                                 check_mergeconflict "$d"
364                                                 exit 1 # this should ALWAYS be fatal
365                                         fi
366                                 fi
367                         fi
368                         cd "$d0"
369                 done
370                 ;;
371         push|commit)
372                 submit=$1
373                 for d in $repos; do
374                         dv=`visible_repo_name "$d"`
375                         enter "$d0/$d" verbose
376                         r=`git symbolic-ref HEAD`
377                         r=${r#refs/heads/}
378                         if git diff HEAD | grep .; then
379                                 # we have uncommitted changes
380                                 a=
381                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
382                                         echo "Uncommitted changes in \"$r\" in $dv. Commit?"
383                                         read -r a
384                                 done
385                                 if [ x"$a" = x"y" ]; then
386                                         verbose git commit -a
387                                 fi
388                         fi
389                         rem=`git config "branch.$r.remote" || echo origin`
390                         if { git log "$rem/$r".."$r" || git log origin/"`repobranch "$d"`".."$r"; } | grep .; then
391                                 a=
392                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
393                                         echo "Push \"$r\" in $dv?"
394                                         read -r a
395                                 done
396                                 if [ x"$a" = x"y" ]; then
397                                         verbose git push "$rem" HEAD
398                                 fi
399                         fi
400                         if [ x"$submit" = x"-s" ]; then
401                                 case "$r" in
402                                         */*)
403                                                 verbose git push "$rem" HEAD:"${r%%/*}/finished/${r#*/}"
404                                                 ;;
405                                 esac
406                         fi
407                         cd "$d0"
408                 done
409                 ;;
410         compile)
411                 if [ -n "$WE_HATE_OUR_USERS" ]; then
412                         TARGETS="sv-debug cl-debug"
413                 else
414                         TARGETS="sv-debug cl-debug sdl-debug"
415                 fi
416                 case "$1" in
417                         -c)
418                                 clean=true
419                                 shift
420                                 ;;
421                         *)
422                                 clean=false
423                                 ;;
424                 esac
425                 case "$1" in
426                         sdl)
427                                 TARGETS="sdl-debug"
428                                 shift
429                                 ;;
430                         glx|agl|wgl)
431                                 TARGETS="cl-debug"
432                                 shift
433                                 ;;
434                         dedicated)
435                                 TARGETS="sv-debug"
436                                 shift
437                                 ;;
438                 esac
439                 if [ -z "$MAKEFLAGS" ]; then
440                         if [ -f /proc/cpuinfo ]; then
441                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
442                                 if [ $ncpus -gt 1 ]; then
443                                         MAKEFLAGS=-j$ncpus
444                                 fi
445                         fi
446                         case "`uname`" in
447                                 Linux|*BSD)
448                                         MAKEFLAGS="$MAKEFLAGS DP_LINK_TO_LIBJPEG=1"
449                                         ;;
450                         esac
451                 fi
452                 enter "$d0/fteqcc" verbose
453                 if $clean; then
454                         verbose make $MAKEFLAGS clean
455                 fi
456                 verbose make $MAKEFLAGS
457                 enter "$d0/data/xonotic-data.pk3dir" verbose
458                 if $clean; then
459                         verbose make $MAKEFLAGS clean
460                 fi
461                 verbose make FTEQCC="$d0/fteqcc/fteqcc.bin" "$@" $MAKEFLAGS
462                 enter "$d0/darkplaces" verbose
463                 if $clean; then
464                         verbose make $MAKEFLAGS clean
465                 fi
466                 for T in $TARGETS; do
467                         verbose make $MAKEFLAGS "$@" "$T"
468                 done
469                 ;;
470         run)
471                 if [ -n "$WE_HATE_OUR_USERS" ]; then
472                         client=
473                         export PATH="$d0/misc/buildfiles/w32:$PATH"
474                 elif [ x"`uname`" = x"Darwin" ]; then
475                         export DYLD_LIBRARY_PATH="$d0/misc/buildfiles/osx/Nexuiz.app/Contents/MacOS"
476                         client=-sdl
477                 else
478                         client=-sdl
479                 fi
480                 case "$1" in
481                         sdl|glx|agl|dedicated)
482                                 client=-$1
483                                 shift
484                                 ;;
485                         wgl)
486                                 client=
487                                 shift
488                                 ;;
489                 esac
490                 if ! [ -x "darkplaces/darkplaces$client" ]; then
491                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
492                                 client=$client.exe
493                         else
494                                 echo "Client darkplaces/darkplaces$client not found, aborting"
495                                 exit 1
496                         fi
497                 fi
498                 set -- "darkplaces/darkplaces$client" -nexuiz -customgamename Xonotic -customgamedirname1 data -customgamedirname2 "" -customgamescreenshotname xonotic -customgameuserdirname xonotic "$@"
499                 if [ -n "$USE_GDB" ]; then
500                         set -- gdb --args "$@"
501                 fi
502                 "$@"
503                 ;;
504         each|foreach)
505                 for d in $repos; do
506                         enter "$d0/$d" verbose
507                         verbose "$@"
508                         cd "$d0"
509                 done
510                 ;;
511         save-patches)
512                 outfile=$1
513                 patchdir=`mktemp -d -t save-patches.XXXXXX`
514                 for d in $repos; do
515                         enter "$d0/$d" verbose
516                         git branch -v -v | cut -c 3- | {
517                                 i=0
518                                 while read -r BRANCH REV UPSTREAM TEXT; do
519                                         case "$UPSTREAM" in
520                                                 \[*)
521                                                         UPSTREAM=${UPSTREAM#\[}
522                                                         UPSTREAM=${UPSTREAM%\]}
523                                                         UPSTREAM=${UPSTREAM%:*}
524                                                         TRACK=true
525                                                         ;;
526                                                 *)
527                                                         UPSTREAM=origin/"`repobranch "$d"`"
528                                                         TRACK=false
529                                                         ;;
530                                         esac
531                                         if [ x"$REV" = x"->" ]; then
532                                                 continue
533                                         fi
534                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
535                                                 echo "$d" > "$patchdir/$i/info.txt"
536                                                 echo "$BRANCH" >> "$patchdir/$i/info.txt"
537                                                 echo "$UPSTREAM" >> "$patchdir/$i/info.txt"
538                                                 echo "$TRACK" >> "$patchdir/$i/info.txt"
539                                                 i=$(($i+1))
540                                         else
541                                                 rm -rf "$patchdir/$i"
542                                         fi
543                                 done
544                         }
545                 done
546                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
547                 rm -rf "$patchdir"
548                 ;;
549         restore-patches)
550                 infile=$1
551                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
552                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
553                 # detach the head
554                 for P in "$patchdir"/*/info.txt; do
555                         D=${P%/info.txt}
556                         exec 3<"$P"
557                         read -r d <&3
558                         read -r BRANCH <&3
559                         read -r UPSTREAM <&3
560                         read -r TRACK <&3
561                         verbose git checkout HEAD^0
562                         verbose git branch -D "$BRANCH"
563                         if [ x"$TRACK" = x"true" ]; then
564                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
565                         else
566                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
567                         fi
568                         verbose git am "$D"
569                 done
570                 rm -rf "$patchdir"
571                 ;;
572         admin-merge)
573                 if [ "$#" = 1 ]; then
574                         set -- "${1%%/*}" "${1#*/}"
575                 fi
576                 for d in $repos; do
577                         enter "$d0/$d" verbose
578                         git rev-parse "$1/$2" || continue
579                         # 1. review
580                         {
581                                 git log HEAD.."$1/$2"
582                                 git diff HEAD..."$1/$2"
583                         } | less
584                         a=
585                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
586                                 echo "Merge \"$1/$2\" into `git symbolic-ref HEAD` of $d?"
587                                 read -r a
588                         done
589                         if [ x"$a" = x"y" ]; then
590                                 git merge "$1/$2"
591                                 cd "$d0"
592                                 a=
593                                 if ! "$SELF" compile; then
594                                         a=n
595                                 fi
596                                 cd "$d0/$d"
597                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
598                                         echo "Still merge \"$1/$2\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."
599                                         read -r a
600                                 done
601                                 if [ x"$a" = x"y" ]; then
602                                         git push origin HEAD
603                                         git push "$1" :"$2"
604                                 else
605                                         git reset --hard HEAD@{1}
606                                 fi
607                         fi
608                 done
609                 ;;
610         *)
611                 echo "Usage:"
612                 echo "  $SELF pull"
613                 echo "  $SELF merge"
614                 echo "  $SELF push [-s]"
615                 echo "  $SELF branches"
616                 echo "  $SELF branch [<remote>] <branchname>"
617                 echo "  $SELF branch <remote> <branchname> <srcbranchname>"
618                 echo "  $SELF checkout [<remote>] <branchname>"
619                 echo "  $SELF compile [-c] [<client>] <options>"
620                 echo "  $SELF run [<client>] <options>"
621                 echo "  $SELF each <command>"
622                 ;;
623 esac