15704071284f798394e08ff5e1f241e4c23ce6ad
[xonotic/xonotic.git] / all
1 #!/bin/sh
2 # vim: filetype=zsh
3
4 set -e
5 if [ -n "$ZSH_VERSION" ]; then
6         setopt SH_WORD_SPLIT
7 fi
8 if [ -z "$ECHO" ]; then
9         if echo "\\\\" | grep .. >/dev/null; then
10                 ECHO=echo
11         else
12                 ECHO=`which echo`
13         fi
14 fi
15
16 # I use this in EVERY shell script ;)
17 LF="
18 "
19 ESC="\e"
20
21 d00=`pwd`
22 while ! [ -f ./all ]; do
23         if [ x"`pwd`" = x"/" ]; then
24                 $ECHO "Cannot find myself."
25                 $ECHO "Please run this script with the working directory inside a Xonotic checkout."
26                 exit 1
27         fi
28         cd ..
29 done
30 export d0=`pwd`
31 SELF="$d0/all"
32
33 # If we are on WINDOWS:
34 case "$0" in
35         all|*/all)
36                 case "`uname`" in
37                         MINGW*|Win*)
38                                 # Windows hates users. So this script has to copy itself elsewhere first...
39                                 cp "$SELF" ../all.xonotic.sh
40                                 export WE_HATE_OUR_USERS=1
41                                 exec ../all.xonotic.sh "$@"
42                                 ;;
43                 esac
44                 ;;
45 esac
46
47 msg()
48 {
49         $ECHO >&2 "$ESC""[1m$*$ESC""[m"
50 }
51
52 self=`git hash-object "$SELF"`
53 checkself()
54 {
55         self_new=`git hash-object "$SELF"`
56         if [ x"$self" != x"$self_new" ]; then
57                 msg "./all has changed."
58                 if [ -z "$XONOTIC_FORBID_RERUN_ALL" ]; then
59                         msg "Rerunning the requested operation to make sure."
60                         export XONOTIC_FORBID_RERUN_ALL=1
61                         exec "$SELF" "$@"
62                 else
63                         msg "Please try $SELF update, and then retry your requested operation."
64                         exit 1
65                 fi
66         fi
67         return 0
68 }
69
70 verbose()
71 {
72         msg "+ $*"
73         "$@"
74 }
75
76 visible_repo_name()
77 {
78         case "$1" in
79                 .)
80                         $ECHO "the root directory"
81                         ;;
82                 *)
83                         $ECHO "\"$1\""
84                         ;;
85         esac
86 }
87
88 check_mergeconflict()
89 {
90         if git ls-files -u | grep ' 1   '; then
91                 $ECHO
92                 $ECHO "MERGE CONFLICT."
93                 $ECHO "change into the \"$1\" project directory, and then:"
94                 $ECHO "- edit the files mentioned above with your favorite editor,"
95                 $ECHO "  and fix the conflicts (marked with <<<<<<< blocks)"
96                 $ECHO "- for binary files, you can select the files using"
97                 $ECHO "  git checkout --ours or git checkout --theirs"
98                 $ECHO "- when done with a file, 'git add' the file"
99                 $ECHO "- when done, 'git commit'"
100                 $ECHO
101                 exit 1
102         fi
103 }
104
105 yesno()
106 {
107         yesno=
108         while [ x"$yesno" != x"y" -a x"$yesno" != x"n" ]; do
109                 eval "$2"
110                 $ECHO "$1"
111                 IFS= read -r yesno
112         done
113         [ x"$yesno" = x"y" ]
114 }
115
116 enter()
117 {
118         $2 cd "$1" || exit 1
119         check_mergeconflict "$1"
120 }
121
122 repos_urls="
123 .                             |                                                   | master         |
124 data/xonotic-data.pk3dir      |                                                   | master         |
125 data/xonotic-music.pk3dir     |                                                   | master         |
126 data/xonotic-nexcompat.pk3dir |                                                   | master         | no
127 darkplaces                    |                                                   | div0-stable    | svn
128 netradiant                    |                                                   | master         |
129 div0-gittools                 |                                                   | master         | no
130 d0_blind_id                   |                                                   | master         |
131 data/xonotic-maps.pk3dir      |                                                   | master         |
132 mediasource                   |                                                   | master         | no
133 fteqcc                        |                                                   | xonotic-stable | noautocrlf
134 "
135 # todo: in darkplaces, change repobranch to div0-stable
136
137 repos=`$ECHO "$repos_urls" | grep . | cut -d '|' -f 1 | tr -d ' '`
138
139 base=`git config remote.origin.url`
140 case "$base" in
141         */xonotic.git)
142                 base=${base%xonotic.git}
143                 ;;
144         *)
145                 $ECHO "The main repo is not xonotic.git, what have you done?"
146                 exit 1
147                 ;;
148 esac
149 pushbase=`git config remote.origin.pushurl || true`
150 case "$pushbase" in
151         */xonotic.git)
152                 pushbase=${pushbase%xonotic.git}
153                 ;;
154         '')
155                 ;;
156         *)
157                 $ECHO "The main repo is not xonotic.git, what have you done?"
158                 exit 1
159                 ;;
160 esac
161
162 repourl()
163 {
164         repo_t=`$ECHO "$repos_urls" | grep "^$1 " | cut -d '|' -f 2 | tr -d ' '`
165         if [ -n "$repo_t" ]; then
166                 case "$repo_t" in
167                         *://*)
168                                 $ECHO "$repo_t"
169                                 ;;
170                         *)
171                                 $ECHO "$base$repo_t"
172                                 ;;
173                 esac
174         else
175                 if [ x"$1" = x"." ]; then
176                         $ECHO "$base""xonotic.git"
177                 else
178                         $ECHO "$base${1##*/}.git"
179                 fi
180         fi
181 }
182
183 repopushurl()
184 {
185         [ -n "$pushbase" ] || return 0
186         repo_t=`$ECHO "$repos_urls" | grep "^$1 " | cut -d '|' -f 2 | tr -d ' '`
187         if [ -n "$repo_t" ]; then
188                 case "$repo_t" in
189                         *://*)
190                                 ;;
191                         *)
192                                 $ECHO "$pushbase$repo_t"
193                                 ;;
194                 esac
195         else
196                 if [ x"$1" = x"." ]; then
197                         $ECHO "$pushbase""xonotic.git"
198                 else
199                         $ECHO "$pushbase${1##*/}.git"
200                 fi
201         fi
202 }
203
204 repobranch()
205 {
206         repo_t=`$ECHO "$repos_urls" | grep "^$1 " | cut -d '|' -f 3 | tr -d ' '`
207         if [ -n "$repo_t" ]; then
208                 $ECHO "$repo_t"
209         else
210                 $ECHO "master"
211         fi
212 }
213
214 repoflags()
215 {
216         $ECHO "$repos_urls" | grep "^$1 " | cut -d '|' -f 4 | tr -d ' '
217 }
218
219 listrepos()
220 {
221         for d in $repos; do
222                 p="${d%dir}"
223                 f="`repoflags "$d"`"
224                 # if we have the dir, always keep it
225                 if [ -d "$d" ]; then
226                         msg "Repository $d enabled because it already exists"
227                         $ECHO "$d"
228                         continue
229                 fi
230                 # if .yes file exists, always keep it
231                 if [ -f "$d.yes" ]; then
232                         msg "Repository $d enabled by a .yes file"
233                         $ECHO "$d"
234                         continue
235                 fi
236                 # if we have .no file, skip
237                 if [ -f "$d.no" ]; then
238                         msg "Repository $d disabled by a .no file, delete $p.no to enable"
239                         continue
240                 fi
241                 # if we have matching pk3, skip
242                 if [ x"$p" != x"$d" ] && [ -f "$p" ]; then
243                         msg "Repository $d disabled by matching .pk3 file, delete $p or create $d.yes to enable"
244                         continue
245                 fi
246                 # if "no" flag is set, skip
247                 case ",$f," in
248                         *,no,*)
249                                 msg "Repository $d disabled by default, create $d.yes to enable"
250                                 continue
251                                 ;;
252                 esac
253                 # default: enable
254                 msg "Repository $d enabled by default"
255                 $ECHO "$d"
256         done
257 }
258
259 repos=`listrepos`
260
261 if [ "$#" = 0 ]; then
262         set -- help
263 fi
264 cmd=$1
265 shift
266
267 fix_upstream_rebase()
268 {
269         if [ -z "$r_me" ] || [ -z "$r_other" ]; then
270                 return
271         fi
272         r_base=`git merge-base "$r_me" "$r_other"`
273
274         # no merge-base? upstream did filter-branch
275         if [ -n "$r_base" ]; then
276                 # otherwise, check if the two histories are "similar"
277                 r_l_me=`git log --pretty="format:%s" "$r_other".."$r_me" | grep -v "^Merge" | sort -u`
278                 r_l_other=`git log --pretty="format:%s" "$r_me".."$r_other" | grep -v "^Merge" | sort -u`
279
280                 # heuristics: upstream rebase/filter-branch if more than 50% of the commits of one of the sides are in the other too
281                 r_lc_me=`$ECHO "$r_l_me" | wc -l`
282                 r_lc_other=`$ECHO "$r_l_other" | wc -l`
283                 r_lc_together=`{ $ECHO "$r_l_me"; $ECHO "$r_l_other"; } | sort -u | wc -l`
284                 r_lc_same=$(($r_lc_me + $r_lc_other - $r_lc_together))
285
286                 if [ $(( $r_lc_same * 2 )) -gt $(( $r_lc_me )) ] || [ $(( $r_lc_same * 2 )) -gt $(( $r_lc_other )) ]; then
287                         if yesno "Probable upstream rebase detected, automatically fix?" 'git log --oneline --graph --date-order --left-right "$r_other"..."$r_me"'; then
288                                 git reset --hard "$r_me"
289                                 git pull --rebase
290                                 return 1
291                         fi
292                 fi
293         fi
294
295         return 0
296 }
297
298 fix_upstream_rebase_mergeok()
299 {
300         r_me=`git rev-parse --revs-only HEAD^1 2>/dev/null || true`
301         r_other=`git rev-parse --revs-only HEAD^2 2>/dev/null || true`
302         fix_upstream_rebase
303 }
304
305 fix_upstream_rebase_mergefail()
306 {
307         r_me=`git rev-parse --revs-only HEAD 2>/dev/null || true`
308         r_other=`git rev-parse --revs-only MERGE_HEAD 2>/dev/null || true`
309         fix_upstream_rebase
310 }
311
312 fix_git_config()
313 {
314         verbose git config remote.origin.url "$1"
315         if [ -n "$2" ]; then
316                 verbose git config remote.origin.pushurl "$2"
317         else
318                 verbose git config --unset remote.origin.pushurl || true
319         fi
320         verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
321         case ",`repoflags "$d"`," in
322                 *,noautocrlf,*)
323                         verbose git config --unset core.autocrlf || true
324                         ;;
325                 *)
326                         verbose git config core.autocrlf input
327                         ;;
328         esac
329         if [ -z "`git config push.default || true`" ]; then
330                 verbose git config push.default current # or is tracking better?
331         fi
332         verbose git config filter.mapclean.clean "tr -d '\r' | grep '^[^/]'"
333         verbose git config filter.mapclean.smudge "cat"
334 }
335
336 mkzip()
337 {
338         archive=$1
339         shift
340         ziplist=`mktemp`
341         find "$@" -xtype f \( -executable -or -type l \) -print > "$ziplist"
342         7za a -tzip -mx=9 -x@"$ziplist" "$archive" "$@" || true
343         zip         -9y   -@<"$ziplist" "$archive"      || true
344         rm -f "$ziplist"
345 }
346
347 mkzip0()
348 {
349         zip -0y "$@"
350 }
351
352 mirrorspeed()
353 {
354         # first result is to be ignored, but we use it to check status
355         git ls-remote "$1" refs/heads/master >/dev/null 2>&1 || return 1
356         { time -p git ls-remote "$1" refs/heads/master; } 2>&1 >/dev/null | head -n 1 | cut -d ' ' -f 2 | tr -d . | sed 's,^0*,,'
357                 # unit: clock ticks (depends on what "time" returns
358 }
359
360 bestmirror()
361 {
362         pre=$1; shift
363         suf=$1; shift
364
365         if ! { time -p true; } >/dev/null 2>&1; then
366                 return 1
367         fi
368
369         bestin=
370         bestt=
371         for in in "$@"; do
372                 m=$pre$in$suf
373                 if t=`mirrorspeed "$m"`; then
374                         msg "$m -> $t ticks"
375                         if [ -n "$t" ]; then
376                                 if [ -z "$bestt" ] || [ "$t" -lt "$bestt" ]; then
377                                         bestin=$in
378                                         bestt=$t
379                                 fi
380                         fi
381                 else
382                         msg "$m -> FAIL"
383                 fi
384         done
385         if [ -n "$bestin" ]; then
386                 msg "Best mirror seems to be $pre$bestin$suf"
387                 $ECHO "$bestin"
388         else
389                 return 1
390         fi
391 }
392
393 case "$cmd" in
394         fix_upstream_rebase)
395                 for d in $repos; do
396                         enter "$d0/$d" verbose
397                         verbose fix_upstream_rebase_mergefail && verbose fix_upstream_rebase_mergeok
398                 done
399                 ;;
400         fix_config)
401                 for d in $repos; do
402                         url=`repourl "$d"`
403                         pushurl=`repopushurl "$d"`
404                         branch=`repobranch "$d"`
405                         if [ -d "$d0/$d" ]; then
406                                 verbose cd "$d0/$d"
407                                 fix_git_config "$url" "$pushurl"
408                                 cd "$d0"
409                         fi
410                 done
411                 ;;
412         keygen)
413                 # enable the ssh URL for pushing
414                 "$SELF" update -N -p
415
416                 if [ -f ~/.ssh/id_rsa.pub ]; then
417                         msg ""
418                         msg "A key already exists and no new one will be generated. If you"
419                         msg "already have done the procedure for getting your key approved, you"
420                         msg "can skip the following paragraph and already use the repository."
421                         msg ""
422                         msg "To get access, your key has to be approved first. For that, visit"
423                         msg "http://dev.xonotic.org/, then log in, create a \"New Issue\" on"
424                         msg "the \"Support\" tracker in the \"Repository\" category where you"
425                         msg "apply for access and paste the following output into the issue:"
426                         msg ""
427                         msg "`cat ~/.ssh/id_rsa.pub`"
428                         msg ""
429                         msg "Note that you will only have write access to branches that start"
430                         msg "with your user name."
431                 elif [ -f ~/.ssh/id_dsa.pub ]; then
432                         msg ""
433                         msg "A key already exists and no new one will be generated. If you"
434                         msg "already have done the procedure for getting your key approved, you"
435                         msg "can skip the following paragraph and already use the repository."
436                         msg ""
437                         msg "To get access, your key has to be approved first. For that, visit"
438                         msg "http://dev.xonotic.org/, then log in, create a \"New Issue\" on"
439                         msg "the \"Support\" tracker in the \"Repository\" category where you"
440                         msg "apply for access and paste the following output into the issue:"
441                         msg ""
442                         msg "`cat ~/.ssh/id_dsa.pub`"
443                         msg ""
444                         msg "Note that you will only have write access to branches that start"
445                         msg "with your user name."
446                 else
447                         msg ""
448                         msg "No key has been generated yet. One will be generated now."
449                         msg "If other people are using your computer, it is recommended"
450                         msg "to specify a passphrase. Otherwise you can simply hit ENTER"
451                         msg "when asked for a passphrase."
452                         msg ""
453                         ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
454                         msg ""
455                         msg "To get access, your key has to be approved first. For that, visit"
456                         msg "http://dev.xonotic.org/, then log in, create a \"New Issue\" on"
457                         msg "the \"Support\" tracker in the \"Repository\" category where you"
458                         msg "apply for access and paste the following output into the issue:"
459                         msg ""
460                         msg "`cat ~/.ssh/id_rsa.pub`"
461                         msg ""
462                         msg "Note that you will only have write access to branches that start"
463                         msg "with your user name."
464                 fi
465                 ;;
466         update|pull)
467                 allow_pull=true
468                 fix_config=false
469                 location=current
470                 while :; do
471                         if [ x"$1" = x"-N" ]; then
472                                 allow_pull=false
473                         elif [ x"$1" = x"-p" ]; then
474                                 fix_config=true
475                                 if [ x"$base" != x"ssh://xonotic@git.xonotic.org/" ]; then
476                                         pushbase=ssh://xonotic@git.xonotic.org/
477                                 fi
478                         elif [ x"$1" = x"-s" ]; then
479                                 fix_config=true
480                                 base=ssh://xonotic@git.xonotic.org/
481                                 pushbase=
482                         elif [ x"$1" = x"-g" ]; then
483                                 fix_config=true
484                                 base=git://git.xonotic.org/xonotic/
485                         elif [ x"$1" = x"-h" ]; then
486                                 fix_config=true
487                                 base=http://git.xonotic.org/xonotic/
488                         elif [ x"$1" = x"-l" ]; then
489                                 case "$2" in
490                                         nl) ;;
491                                         de) ;;
492                                         best) ;;
493                                         default) ;;
494                                         *)
495                                                 msg "Invalid location!"
496                                                 msg "Possible locations for the -l option:"
497                                                 msg "  nl (Netherlands, run by merlijn)"
498                                                 msg "  de (Germany, run by divVerent)"
499                                                 msg "  best (find automatically)"
500                                                 msg "  default (currently nl)"
501                                                 exit 1
502                                                 ;;
503                                 esac
504                                 fix_config=true
505                                 location=$2
506                                 shift
507                         else
508                                 break
509                         fi
510                         shift
511                 done
512                 case "$location" in
513                         best)
514                                 newbase=`$ECHO "$base" | sed "s,://\(.*\.\)\?git.xonotic.org/,:// .git.xonotic.org/,"`
515                                 case "$newbase" in
516                                         *\ *)
517                                                 if location=`bestmirror $newbase"xonotic.git" de nl`; then
518                                                         :
519                                                 else
520                                                         location=current
521                                                 fi
522                                                 ;;
523                                         *)
524                                                 location=current
525                                                 ;;
526                                 esac
527                                 ;;
528                 esac
529                 case "$location" in
530                         default)
531                                 location=
532                                 ;;
533                         current)
534                                 case "$base" in
535                                         *://*.git.xonotic.org/*)
536                                                 location=${base%%.git.xonotic.org/*}
537                                                 location=${location##*://}
538                                                 ;;
539                                         *)
540                                                 location=
541                                                 ;;
542                                 esac
543                                 ;;
544                 esac
545                 if [ -n "$location" ]; then
546                         base=`$ECHO "$base" | sed "s,://\(.*\.\)\?git.xonotic.org/,://$location.git.xonotic.org/,"`
547                         pushbase=`$ECHO "$pushbase" | sed "s,://\(.*\.\)\?git.xonotic.org/,://$location.git.xonotic.org/,"`
548                 else
549                         base=`$ECHO "$base" | sed "s,://\(.*\.\)\?git.xonotic.org/,://git.xonotic.org/,"`
550                         pushbase=`$ECHO "$pushbase" | sed "s,://\(.*\.\)\?git.xonotic.org/,://git.xonotic.org/,"`
551                 fi
552                 if $fix_config; then
553                         url=`repourl .`
554                         pushurl=`repopushurl .`
555                         fix_git_config "$url" "$pushurl"
556                 fi
557                 if $allow_pull || $fix_config; then
558                         "$SELF" fix_config
559                 fi
560                 for d in $repos; do
561                         url=`repourl "$d"`
562                         pushurl=`repopushurl "$d"`
563                         branch=`repobranch "$d"`
564                         if [ -d "$d0/$d" ]; then
565                                 if $allow_pull; then
566                                         enter "$d0/$d" verbose
567                                         r=`git symbolic-ref HEAD`
568                                         r=${r#refs/heads/}
569                                         if git config branch.$r.remote >/dev/null 2>&1; then
570                                                 if ! verbose git pull; then
571                                                         fix_upstream_rebase_mergefail || true
572                                                         check_mergeconflict "$d"
573                                                         $ECHO "Pulling failed. Press ENTER to continue, or Ctrl-C to abort."
574                                                         read -r DUMMY
575                                                 else
576                                                         fix_upstream_rebase_mergeok || true
577                                                 fi
578                                         fi
579
580                                         cd "$d00"
581                                         checkself "$cmd" "$@"
582                                         cd "$d0/$d"
583                                         verbose git remote prune origin
584                                         cd "$d0"
585                                 fi
586                         else
587                                 verbose git clone "$url" "$d0/$d"
588                                 enter "$d0/$d" verbose
589                                 fix_git_config "$url" "$pushurl"
590                                 if [ "$branch" != "master" ]; then
591                                         verbose git checkout --track -b "$branch" origin/"$branch"
592                                 fi
593                                 cd "$d0"
594                         fi
595                 done
596                 ;;
597         update-maps)
598                 misc/tools/xonotic-map-compiler-autobuild download
599                 ;;
600         checkout|switch)
601                 checkoutflags=
602                 if [ x"$1" = x"-f" ]; then
603                         checkoutflags=-f
604                         shift
605                 fi
606                 remote=$1
607                 branch=$2
608                 if [ -z "$branch" ]; then
609                         case "$remote" in
610                                 origin/*)
611                                         branch=${remote#origin/}
612                                         remote=origin
613                                         ;;
614                                 *)
615                                         branch=$remote
616                                         remote=origin
617                                         ;;
618                         esac
619                 fi
620                 exists=false
621                 for d in $repos; do
622                         enter "$d0/$d" verbose
623                         b=$branch
624                         if [ -n "$b" ] && git rev-parse "refs/heads/$b" >/dev/null 2>&1; then
625                                 exists=true
626                                 verbose git checkout $checkoutflags "$b"
627                         elif [ -n "$b" ] && git rev-parse "refs/remotes/$remote/$b" >/dev/null 2>&1; then
628                                 exists=true
629                                 verbose git checkout $checkoutflags --track -b "$b" "$remote/$b"
630                         else
631                                 b=`repobranch "$d"`
632                                 if git rev-parse "refs/heads/$b" >/dev/null 2>&1; then
633                                         exists=true
634                                         verbose git checkout $checkoutflags "$b"
635                                 elif git rev-parse "refs/remotes/$remote/$b" >/dev/null 2>&1; then
636                                         exists=true
637                                         verbose git checkout $checkoutflags --track -b "$b" "$remote/$b"
638                                 else
639                                         $ECHO "WTF? Not even branch $b doesn't exist in $d"
640                                         exit 1
641                                 fi
642                         fi
643                         cd "$d00"
644                         checkself "$cmd" "$@"
645                         cd "$d0"
646                 done
647                 if ! $exists; then
648                         $ECHO "The requested branch was not found in any repository."
649                 fi
650                 exec "$SELF" branch
651                 ;;
652         branch)
653                 remote=$1
654                 branch=$2
655                 srcbranch=$3
656                 if [ -z "$branch" ]; then
657                         branch=$remote
658                         remote=origin
659                 fi
660                 if [ -z "$branch" ]; then
661                         for d in $repos; do
662                                 enter "$d0/$d"
663                                 r=`git symbolic-ref HEAD`
664                                 r=${r#refs/heads/}
665                                 $ECHO "$d is at $r"
666                                 cd "$d0"
667                         done
668                 else
669                         for d in $repos; do
670                                 dv=`visible_repo_name "$d"`
671                                 enter "$d0/$d" verbose
672                                 if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
673                                         $ECHO "Already having this branch in $dv."
674                                 else
675                                         if yesno "Branch in $dv?"; then
676                                                 if [ -n "$srcbranch" ]; then
677                                                         b=$srcbranch
678                                                 else
679                                                         b=origin/"`repobranch "$d"`"
680                                                         verbose git fetch origin || true
681                                                 fi
682                                                 # TODO do this without pushing
683                                                 verbose git checkout -b "$branch" "$b"
684                                                 verbose git config "branch.$branch.remote" "$remote"
685                                                 verbose git config "branch.$branch.merge" "refs/heads/$branch"
686                                         fi
687                                 fi
688                                 cd "$d0"
689                         done
690                         "$SELF" branch
691                 fi
692                 ;;
693         branches)
694                 for d in $repos; do
695                         cd "$d0/$d" # am in a pipe, shouldn't use enter
696                         git branch -r -v -v | cut -c 3- | sed "s/^(no branch)/(no_branch)/" | sed "s,^,$d ,"
697                         cd "$d0"
698                 done | {
699                         branches_list=
700                         # branches_repos_*=
701                         while read -r d BRANCH REV TEXT; do
702                                 if [ x"$BRANCH" = x"`repobranch "$d"`" ]; then
703                                         continue
704                                 fi
705                                 if [ x"$REV" = x"->" ]; then
706                                         continue
707                                 fi
708                                 BRANCH=${BRANCH#remotes/}
709                                 ID=`$ECHO "$BRANCH" | tr -c "A-Za-z0-9." "_"`
710                                 branches_list="$branches_list $BRANCH" # TEH SORT MAKEZ IT UNIEQ
711                                 eval "r=\$branches_repos_$ID"
712                                 r="$r $d"
713                                 eval "branches_repos_$ID=\$r"
714                         done
715                         $ECHO -n "$branches_list" | xargs -n 1 $ECHO | sort -u | while IFS= read -r BRANCH; do
716                                 ID=`$ECHO "$BRANCH" | tr -c "A-Za-z0-9." "_"`
717                                 eval "r=\$branches_repos_$ID"
718                                 printf "%-60s %s\n" "$BRANCH" "$r"
719                                 #$ECHO "$BRANCH: $r"
720                         done
721                 }
722                 ;;
723         merge)
724                 for d in $repos; do
725                         dv=`visible_repo_name "$d"`
726                         enter "$d0/$d" verbose
727                         r=`git symbolic-ref HEAD`
728                         r=${r#refs/heads/}
729                         if git log HEAD..origin/"`repobranch "$d"`" | grep .; then
730                                 # we have uncommitted changes
731                                 if yesno "Could merge from \"`repobranch "$d"`\" into \"$r\" in $dv. Do it?"; then
732                                         if ! verbose git merge origin/"`repobranch "$d"`"; then
733                                                 check_mergeconflict "$d"
734                                                 exit 1 # this should ALWAYS be fatal
735                                         fi
736                                 fi
737                         fi
738                         cd "$d0"
739                 done
740                 ;;
741         push|commit)
742                 submit=$1
743                 for d in $repos; do
744                         dv=`visible_repo_name "$d"`
745                         enter "$d0/$d" verbose
746                         r=`git symbolic-ref HEAD`
747                         r=${r#refs/heads/}
748                         diffdata=`git diff --color HEAD`
749                         if [ -n "$diffdata" ]; then
750                                 # we have uncommitted changes
751                                 if yesno "Uncommitted changes in \"$r\" in $dv. Commit?" '$ECHO "$diffdata" | less -r'; then
752                                         verbose git commit -a
753                                 fi
754                         fi
755                         rem=`git config "branch.$r.remote" || $ECHO origin`
756                         bra=`git config "branch.$r.merge" || $ECHO "$r"`
757                         upstream="$rem/${bra#refs/heads/}"
758                         if ! git rev-parse "$upstream" >/dev/null 2>&1; then
759                                 upstream="origin/`repobranch "$d"`"
760                         fi
761                         logdata=`git log --color "$upstream".."$r"`
762                         if [ -n "$logdata" ]; then
763                                 if yesno "Push \"$r\" in $dv?" '$ECHO "$logdata" | less -r'; then
764                                         verbose git push "$rem" HEAD
765                                 fi
766                         fi
767                         if [ x"$submit" = x"-s" ]; then
768                                 case "$r" in
769                                         */*)
770                                                 verbose git push "$rem" HEAD:"${bra%%/*}/finished/${bra#*/}"
771                                                 ;;
772                                 esac
773                         fi
774                         cd "$d0"
775                 done
776                 ;;
777         compile)
778                 cleand0=false
779                 cleandp=false
780                 cleanqcc=false
781                 cleanqc=false
782                 compiled0=false
783                 debug=debug
784                 snowleopardhack=false
785                 if [ -z "$CC" ]; then
786                         export CC="gcc -DSUPPORTIPV6"
787                 fi
788                 while :; do
789                         case "$1" in
790                                 -0)
791                                         compiled0=true
792                                         shift
793                                         ;;
794                                 -c)
795                                         cleand0=true
796                                         cleandp=true
797                                         cleanqcc=true
798                                         cleanqc=true
799                                         shift
800                                         ;;
801                                 -r)
802                                         debug=release
803                                         export CC="$CC -g -mtune=native -march=native"
804                                         if [ -n "$WE_HATE_OUR_USERS" ]; then
805                                                 export CC="$CC -fno-common"
806                                         fi
807                                         shift
808                                         ;;
809                                 *)
810                                         break
811                                         ;;
812                         esac
813                 done
814                 if [ -n "$WE_HATE_OUR_USERS" ]; then
815                         TARGETS="sv-$debug cl-$debug"
816                 elif [ x"`uname`" = x"Darwin" ]; then
817                         case "`uname -r`" in
818                                 ?.*)
819                                         TARGETS="sv-$debug cl-$debug sdl-$debug"
820                                         ;;
821                                 *)
822                                         # AGL cannot be compiled on systems with a kernel > 10.x (Snow Leopard)
823                                         snowleopardhack=true
824                                         TARGETS="sv-$debug sdl-$debug"
825                                         ;;
826                         esac
827                         export CC="$CC -fno-reorder-blocks -I$PWD/misc/buildfiles/osx/Xonotic-SDL.app/Contents/Frameworks/SDL.framework/Headers -F$PWD/misc/buildfiles/osx/Xonotic-SDL.app/Contents/Frameworks"
828                 else
829                         TARGETS="sv-$debug cl-$debug sdl-$debug"
830                 fi
831                 if [ $# -gt 0 ] && [ x"$1" = x"" ]; then
832                         # if we give the command make the arg "", it will surely fail (invalid filename),
833                         # so better handle it as an empty client option
834                         BAD_TARGETS=" "
835                         shift
836                 elif [ -n "$1" ]; then
837                         BAD_TARGETS=
838                         TARGETS_SAVE=$TARGETS
839                         TARGETS=
840                         for X in $1; do
841                                 case "$X" in
842                                         sdl)
843                                                 TARGETS="$TARGETS sdl-debug"
844                                                 ;;
845                                         agl)
846                                                 TARGETS="$TARGETS cl-debug"
847                                                 if $snowleopardhack; then
848                                                         export CC="$CC -arch i386"
849                                                 fi
850                                                 ;;
851                                         glx|wgl)
852                                                 TARGETS="$TARGETS cl-debug"
853                                                 ;;
854                                         dedicated)
855                                                 TARGETS="$TARGETS sv-debug"
856                                                 ;;
857                                         *)
858                                                 BAD_TARGETS="$BAD_TARGETS $X"
859                                                 ;;
860                                 esac
861                         done
862                         if [ -n "$TARGETS" ]; then # at least a valid client
863                                 shift
864                         else # no valid client, let's assume this option is not meant to be a client then
865                                 TARGETS=$TARGETS_SAVE
866                                 BAD_TARGETS=
867                         fi
868                 fi
869                 if [ -z "$MAKEFLAGS" ]; then
870                         if [ -f /proc/cpuinfo ]; then
871                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
872                                 if [ $ncpus -gt 1 ]; then
873                                         MAKEFLAGS=-j$ncpus
874                                 fi
875                         fi
876                         if [ -n "$WE_HATE_OUR_USERS" ]; then
877                                 MAKEFLAGS="$MAKEFLAGS DP_MAKE_TARGET=mingw LIB_JPEG= CFLAGS_LIBJPEG="
878                         fi
879                 fi
880
881                 enter "$d0/d0_blind_id" verbose
882                 if ! $compiled0; then
883                         # compilation of crypto library failed
884                         # use binaries then, if we can...
885                         mkdir -p .libs
886                         if [ -n "$WE_HATE_OUR_USERS" ]; then
887                                 verbose cp "$d0/misc/buildfiles/win32/libd0_blind_id"-* .libs/
888                                 verbose cp "$d0/misc/buildfiles/win32/libgmp"-* .libs/
889                         else
890                                 case "`uname`" in
891                                         Linux)
892                                                 case `uname -m` in
893                                                         x86_64)
894                                                                 verbose cp "$d0/misc/builddeps/dp.linux64/lib/libd0_blind_id".* .libs/
895                                                                 verbose cp "$d0/misc/builddeps/dp.linux64/lib/libgmp".* .libs/
896                                                                 MAKEFLAGS="$MAKEFLAGS DP_CRYPTO_STATIC_LIBDIR=../misc/builddeps/dp.linux64/lib/"
897                                                                 ;;
898                                                         *86)
899                                                                 verbose cp "$d0/misc/builddeps/dp.linux32/lib/libd0_blind_id".* .libs/
900                                                                 verbose cp "$d0/misc/builddeps/dp.linux32/lib/libgmp".* .libs/
901                                                                 MAKEFLAGS="$MAKEFLAGS DP_CRYPTO_STATIC_LIBDIR=../misc/builddeps/dp.linux32/lib/"
902                                                                 ;;
903                                                         *)
904                                                                 compiled0=true
905                                                                 ;;
906                                                 esac
907                                                 ;;
908                                         Darwin)
909                                                 verbose cp "$d0/misc/buildfiles/osx/Xonotic.app/Contents/MacOS/libd0_blind_id".* .libs/
910                                                 ;;
911                                         *)
912                                                 compiled0=true
913                                                 ;;
914                                 esac
915                         fi
916                 fi
917                 if $compiled0; then
918                         if $cleand0; then
919                                 if [ -f Makefile ]; then
920                                         verbose make $MAKEFLAGS distclean
921                                 fi
922                         fi
923                         if ! [ -f Makefile ]; then
924                                 verbose sh autogen.sh
925                                 verbose ./configure
926                         fi
927                         verbose make $MAKEFLAGS
928                 fi
929
930                 enter "$d0/fteqcc" verbose
931                 if $cleanqcc; then
932                         verbose make $MAKEFLAGS clean
933                 fi
934                 verbose make $MAKEFLAGS
935
936                 enter "$d0/data/xonotic-data.pk3dir" verbose
937                 if $cleanqc; then
938                         verbose make FTEQCC="../../../../fteqcc/fteqcc.bin" "$@" $MAKEFLAGS clean
939                 fi
940                 verbose make FTEQCC="../../../../fteqcc/fteqcc.bin" "$@" $MAKEFLAGS
941                 # 4 levels up: data, xonotic-data, qcsrc, server
942
943                 enter "$d0/darkplaces" verbose
944                 if [ x"$BAD_TARGETS" = x" " ]; then
945                         $ECHO "Warning: invalid empty client, default clients will be used."
946                 fi
947                 if $cleandp; then
948                         verbose make $MAKEFLAGS clean
949                 fi
950                 for T in $TARGETS; do
951                         verbose make $MAKEFLAGS STRIP=: "$@" "$T"
952                 done
953                 for T in $BAD_TARGETS; do
954                         $ECHO "Warning: discarded invalid client $T."
955                 done
956
957                 verbose "$SELF" update-maps
958                 ;;
959         run)
960                 if [ -n "$WE_HATE_OUR_USERS" ]; then
961                         client=
962                         export PATH="$d0/misc/buildfiles/win32:$d0/d0_blind_id/.libs:$PATH"
963                 elif [ x"`uname`" = x"Darwin" ]; then
964                         export DYLD_LIBRARY_PATH="$d0/misc/buildfiles/osx/Xonotic-SDL.app/Contents/MacOS:$d0/d0_blind_id/.libs"
965                         export DYLD_FRAMEWORK_PATH="$d0/misc/buildfiles/osx/Xonotic-SDL.app/Contents/Frameworks"
966                         client=-sdl
967                 else
968                         export LD_LIBRARY_PATH="$d0/d0_blind_id/.libs"
969                         client=-sdl
970                 fi
971                 case "$1" in
972                         sdl|glx|agl|dedicated)
973                                 client=-$1
974                                 shift
975                                 ;;
976                         wgl)
977                                 client=
978                                 shift
979                                 ;;
980                 esac
981                 if ! [ -x "darkplaces/darkplaces$client" ]; then
982                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
983                                 client=$client.exe
984                         else
985                                 $ECHO "Client darkplaces/darkplaces$client not found, aborting"
986                                 exit 1
987                         fi
988                 fi
989                 set -- "darkplaces/darkplaces$client" -xonotic -mygames "$@"
990
991                 # if pulseaudio is running: USE IT
992                 if [ -z "$SDL_AUDIODRIVER" ] && ! [ -n "$WE_HATE_OUR_USERS" ] && ! [ x"`uname`" = x"Darwin" ]; then
993                         if ps -C pulseaudio >/dev/null; then
994                                 if ldd /usr/lib/libSDL.so 2>/dev/null | grep pulse >/dev/null; then
995                                         export SDL_AUDIODRIVER=pulse
996                                 fi
997                         fi
998                 fi
999
1000                 binary=$1
1001
1002                 if [ -n "$USE_GDB" ]; then
1003                         set -- gdb --args "$@"
1004                 elif which gdb >/dev/null 2>&1; then
1005                         set -- gdb --batch -x savecore.gdb --args "$@"
1006                 elif which catchsegv >/dev/null 2>&1; then
1007                         set -- catchsegv "$@"
1008                 fi
1009                 rm -f xonotic.core
1010                 "$@" || true
1011                 if [ -f xonotic.core ]; then
1012                         if yesno "The program has CRASHED. Do you want to examine the core dump?"; then
1013                                 gdb "$binary" xonotic.core
1014                         #elif yesno "You did not want to examine the core dump. Do you want to provide it - including your DarkPlaces checkout - to the Xonotic developers?"; then
1015                         #       tar cvzf xonotic.core.tar.gz xonotic.core darkplaces/*.c darkplaces/*.h
1016                         #       # somehow send it
1017                         #       rm -f xonotic.core.tar.gz
1018                         else
1019                                 $ECHO "The core dump can be examined later by"
1020                                 $ECHO "  gdb $binary xonotic.core"
1021                         fi
1022                 fi
1023                 ;;
1024         each|foreach)
1025                 keep_going=false
1026                 if [ x"$1" = x"-k" ]; then
1027                         keep_going=true
1028                         shift
1029                 fi
1030                 for d in $repos; do
1031                         if verbose cd "$d0/$d"; then
1032                                 if $keep_going; then
1033                                         verbose "$@" || true
1034                                 else
1035                                         verbose "$@"
1036                                 fi
1037                                 cd "$d0"
1038                         fi
1039                 done
1040                 ;;
1041         save-patches)
1042                 outfile=$1
1043                 patchdir=`mktemp -d -t save-patches.XXXXXX`
1044                 for d in $repos; do
1045                         enter "$d0/$d" verbose
1046                         git branch -v -v | cut -c 3- | {
1047                                 i=0
1048                                 while read -r BRANCH REV UPSTREAM TEXT; do
1049                                         case "$UPSTREAM" in
1050                                                 \[*)
1051                                                         UPSTREAM=${UPSTREAM#\[}
1052                                                         UPSTREAM=${UPSTREAM%\]}
1053                                                         UPSTREAM=${UPSTREAM%:*}
1054                                                         TRACK=true
1055                                                         ;;
1056                                                 *)
1057                                                         UPSTREAM=origin/"`repobranch "$d"`"
1058                                                         TRACK=false
1059                                                         ;;
1060                                         esac
1061                                         if [ x"$REV" = x"->" ]; then
1062                                                 continue
1063                                         fi
1064                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
1065                                                 $ECHO "$d" > "$patchdir/$i/info.txt"
1066                                                 $ECHO "$BRANCH" >> "$patchdir/$i/info.txt"
1067                                                 $ECHO "$UPSTREAM" >> "$patchdir/$i/info.txt"
1068                                                 $ECHO "$TRACK" >> "$patchdir/$i/info.txt"
1069                                                 i=$(($i+1))
1070                                         else
1071                                                 rm -rf "$patchdir/$i"
1072                                         fi
1073                                 done
1074                         }
1075                 done
1076                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
1077                 rm -rf "$patchdir"
1078                 ;;
1079         restore-patches)
1080                 infile=$1
1081                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
1082                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
1083                 # detach the head
1084                 for P in "$patchdir"/*/info.txt; do
1085                         D=${P%/info.txt}
1086                         exec 3<"$P"
1087                         read -r d <&3
1088                         read -r BRANCH <&3
1089                         read -r UPSTREAM <&3
1090                         read -r TRACK <&3
1091                         verbose git checkout HEAD^0
1092                         verbose git branch -D "$BRANCH"
1093                         if [ x"$TRACK" = x"true" ]; then
1094                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
1095                         else
1096                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
1097                         fi
1098                         verbose git am "$D"
1099                 done
1100                 rm -rf "$patchdir"
1101                 ;;
1102         admin-merge)
1103                 branch=$1
1104                 t=`mktemp`
1105                 report=""
1106                 reportecho()
1107                 {
1108                         report=$report"$*$LF"
1109                         $ECHO "$*"
1110                 }
1111                 reportecho4()
1112                 {
1113                         report=$report"    $*$LF"
1114                         $ECHO "    $*"
1115                 }
1116                 reportdo4()
1117                 {
1118                         o=`"$@" | sed 's/^/    /' || true`
1119                         reportecho "$o"
1120                 }
1121                 for d in $repos; do
1122                         case "$d" in
1123                                 fteqcc)
1124                                         # sorry, fteqcc repo is managed manually
1125                                         continue
1126                                         ;;
1127                         esac
1128                         enter "$d0/$d" verbose
1129                         base="`repobranch "$d"`"
1130                         reportecho "In $d:"
1131                         for ref in `git for-each-ref --format='%(refname)' refs/remotes/origin/`; do
1132                                 case "${ref#refs/remotes/origin/}" in
1133                                         "$base")
1134                                                 continue
1135                                                 ;;
1136                                         HEAD|master)
1137                                                 continue
1138                                                 ;;
1139                                         */*)
1140                                                 ;;
1141                                         *)
1142                                                 continue
1143                                                 ;;
1144                                 esac
1145                                 if [ -n "$branch" ]; then
1146                                         if [ x"$branch" != x"${ref#refs/remotes/origin/}" ]; then
1147                                                 continue
1148                                         fi
1149                                 fi
1150                                 case "$base" in
1151                                         master)
1152                                                 realbase=$base
1153                                                 ;;
1154                                         *)
1155                                                 l0=`git rev-list "$base".."$ref" | wc -l`
1156                                                 l1=`git rev-list master.."$ref" | wc -l`
1157                                                 if [ $l0 -gt $l1 ]; then
1158                                                         realbase=master
1159                                                 else
1160                                                         realbase=$base
1161                                                 fi
1162                                                 ;;
1163                                 esac
1164                                 reportecho "  Branch $ref:"
1165                                 note=`GIT_NOTES_REF=refs/notes/admin-merge git notes show "$ref" 2>/dev/null || true`
1166                                 logdata=`git log --color "$realbase".."$ref"`
1167                                 if [ -z "$logdata" ]; then
1168                                         reportecho4 "--> not merging, no changes vs master"
1169                                         if yesno "Branch \"$ref\" probably should get deleted. Do it?" ''; then
1170                                                 git push origin :"${ref#refs/remotes/origin/}"
1171                                                 reportecho4 "--> branch deleted"
1172                                         fi
1173                                 else
1174                                         diffdata=`git diff --color --find-copies-harder --ignore-space-change "$realbase"..."$ref"`
1175                                         if [ -z "$diffdata" ]; then
1176                                                 reportecho4 "--> not merging, no changes vs master, branch contains redundant history"
1177                                                 if yesno "Branch \"$ref\" probably should get deleted. Do it?" '{ $ECHO "$logdata"; } | less -r'; then
1178                                                         git push origin :"${ref#refs/remotes/origin/}"
1179                                                         reportecho4 "--> branch deleted"
1180                                                 fi
1181                                         elif [ -z "$branch" ] && [ -n "$note" ]; then
1182                                                 reportdo4 $ECHO "$note"
1183                                                 reportecho4 "--> not merging, already had this one rejected before"
1184                                         elif yesno "Branch \"$ref\" may want to get merged. Do it?" '{ $ECHO "$logdata"; $ECHO "$diffdata"; } | less -r'; then
1185                                                 git checkout "$realbase"
1186                                                 org=`git rev-parse HEAD`
1187                                                 if ! git merge --no-ff "$ref" 2>&1 | tee "$t" && ! { git ls-files -u | grep ' 1 ' >/dev/null; }; then
1188                                                         git reset --hard "$org"
1189                                                         GIT_NOTES_REF=refs/notes/admin-merge git notes edit -m "Merge failed:$LF`cat "$t"`" "$ref"
1190                                                         reportdo4 cat "$t"
1191                                                         reportecho4 "--> merge failed"
1192                                                 elif ! "$SELF" compile 2>&1 | tee "$t"; then
1193                                                         git reset --hard "$org"
1194                                                         GIT_NOTES_REF=refs/notes/admin-merge git notes edit -m "Compile failed:$LF`cat "$t"`" "$ref"
1195                                                         reportdo4 cat "$t"
1196                                                         reportecho4 "--> compile failed"
1197                                                 elif ! yesno "Still merge \"$ref\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."; then
1198                                                         git reset --hard "$org"
1199                                                         GIT_NOTES_REF=refs/notes/admin-merge git notes edit "$ref"
1200                                                         note=`GIT_NOTES_REF=refs/notes/admin-merge git notes show "$ref" 2>/dev/null || true`
1201                                                         if [ x"$note" = x"del" ]; then
1202                                                                 git push origin :"${ref#refs/remotes/origin/}"
1203                                                                 reportecho4 "--> test failed, branch deleted"
1204                                                         elif [ -n "$note" ]; then
1205                                                                 reportdo4 $ECHO "$note"
1206                                                                 reportecho4 "--> test failed"
1207                                                         else
1208                                                                 reportecho4 "--> test failed, postponed"
1209                                                         fi
1210                                                 else
1211                                                         # apply crlf, or other cleanup filters (non-behavioural changes)
1212                                                         git reset --hard
1213                                                         find . -type f -exec touch {} \;
1214                                                         git commit -a --amend -C HEAD || true # don't fail if nothing to commit
1215
1216                                                         $ECHO "MERGING"
1217                                                         case ",`repoflags "$d"`," in
1218                                                                 *,svn,*)
1219                                                                         # we do quite a mess here... luckily we know $org
1220                                                                         git fetch # svn needs to be current
1221                                                                         git rebase -i --onto origin/master "$org"
1222                                                                         git svn dcommit --add-author-from
1223                                                                         git reset --hard "$org"
1224                                                                         ;;
1225                                                                 *)
1226                                                                         git push origin HEAD
1227                                                                         ;;
1228                                                         esac
1229                                                         reportecho4 "--> MERGED"
1230                                                         if yesno "Delete original branch \"$ref\"?"; then
1231                                                                 git push origin :"${ref#refs/remotes/origin/}"
1232                                                                 reportecho4 "--> branch deleted"
1233                                                         fi
1234                                                 fi
1235                                         else
1236                                                 GIT_NOTES_REF=refs/notes/admin-merge git notes edit "$ref"
1237                                                 note=`GIT_NOTES_REF=refs/notes/admin-merge git notes show "$ref" 2>/dev/null || true`
1238                                                 if [ x"$note" = x"del" ]; then
1239                                                         git push origin :"${ref#refs/remotes/origin/}"
1240                                                         reportecho4 "--> branch deleted"
1241                                                 elif [ -n "$note" ]; then
1242                                                         reportdo4 $ECHO "$note"
1243                                                         reportecho4 "--> rejected"
1244                                                 else
1245                                                         reportecho4 "--> postponed"
1246                                                 fi
1247                                         fi
1248                                 fi
1249                                 reportecho ""
1250                         done
1251                         reportecho ""
1252                 done
1253                 rm -f "$t"
1254                 $ECHO "$report" | ssh nexuiz@rm.endoftheinternet.org cat '>>' public_html/xonotic-merge-notes.txt
1255                 ;;
1256         clean)
1257                 "$SELF" fix_config
1258                 "$SELF" update -N
1259                 force=false
1260                 gotoupstream=false
1261                 fetchupstream=false
1262                 gotomaster=false
1263                 rmuntracked=false
1264                 killbranches=false
1265                 # usage:
1266                 #   ./all clean [-m] [-f | -fu | -fU] [-r] [-D]
1267                 #   ./all clean --reclone
1268                 found=false
1269                 for X in "$@"; do
1270                         if [ x"$X" = x"--reclone" ]; then
1271                                 force=true
1272                                 fetchupstream=true
1273                                 gotoupstream=true
1274                                 gotomaster=true
1275                                 rmuntracked=true
1276                                 killbranches=true
1277                         elif [ x"$X" = x"-f" ]; then
1278                                 force=true
1279                         elif [ x"$X" = x"-u" ]; then
1280                                 gotoupstream=true
1281                         elif [ x"$X" = x"-U" ]; then
1282                                 gotoupstream=true
1283                                 fetchupstream=true
1284                         elif [ x"$X" = x"-fu" ]; then
1285                                 force=true
1286                                 gotoupstream=true
1287                         elif [ x"$X" = x"-fU" ]; then
1288                                 force=true
1289                                 gotoupstream=true
1290                                 fetchupstream=true
1291                         elif [ x"$X" = x"-m" ]; then
1292                                 gotomaster=true
1293                         elif [ x"$X" = x"-r" ]; then
1294                                 rmuntracked=true
1295                         elif [ x"$X" = x"-D" ]; then
1296                                 killbranches=true
1297                         elif $ECHO "$X" | grep '^-FFFF*UUUU*$' >/dev/null; then
1298                                 msg ''
1299                                 msg "        _____"
1300                                 msg "    ,--'-\\P/\`\\  FFFFFFF"
1301                                 msg " __/_    B/,-.\\  FFFFFFF"
1302                                 msg " /  _\\  (//  O\\\\  FFFFFF"
1303                                 msg "| (O  \`) _\\._ _)\\  FFFUU"
1304                                 msg "| |___/.^d0~~\"\\  \\ UUUU"
1305                                 msg "|     |\`~'     \\ |  UUUU"
1306                                 msg "|     |    __,C>|| UUUU"
1307                                 msg "\\    /_ ,-/,-'   |  UUUU"
1308                                 msg " \\\\_ \\_>~'      /  UUUU-"
1309                                 msg ''
1310                         else
1311                                 msg "Unknown arg: $X"
1312                         fi
1313                         found=true
1314                         shift
1315                 done
1316                 if ! $found; then
1317                         rmuntracked=true
1318                 fi
1319                 for d in $repos; do
1320                         verbose cd "$d0/$d"
1321                         if $gotoupstream; then
1322                                 if ! $force; then
1323                                         msg "Must also use -f (delete local changes) when using -u"
1324                                         exit 1
1325                                 fi
1326                                 if $gotomaster; then
1327                                         if $fetchupstream; then
1328                                                 verbose git fetch origin
1329                                                 verbose git remote prune origin
1330                                         fi
1331                                         verbose git checkout -f "`repobranch "$d"`"
1332                                         verbose git reset --hard origin/"`repobranch "$d"`"
1333                                 else
1334                                         r=`git symbolic-ref HEAD`
1335                                         r=${r#refs/heads/}
1336                                         rem=`git config "branch.$r.remote" || $ECHO origin`
1337                                         bra=`git config "branch.$r.merge" || $ECHO "$r"`
1338                                         upstream="$rem/${bra#refs/heads/}"
1339                                         if $fetchupstream; then
1340                                                 verbose git fetch "$rem"
1341                                                 verbose git remote prune "$rem"
1342                                         fi
1343                                         if ! git rev-parse "$upstream" >/dev/null 2>&1; then
1344                                                 upstream="origin/`repobranch "$d"`"
1345                                         fi
1346                                         verbose git reset --hard "$upstream"
1347                                 fi
1348                         elif $gotomaster; then
1349                                 if $force; then
1350                                         verbose git checkout -f "`repobranch "$d"`"
1351                                         verbose git reset --hard
1352                                 else
1353                                         verbose git checkout "`repobranch "$d"`"
1354                                 fi
1355                         elif $force; then
1356                                 verbose git reset --hard
1357                         fi
1358                         if $rmuntracked; then
1359                                 case "$d" in
1360                                         .)
1361                                                 verbose git clean -df
1362                                                 ;;
1363                                         *)
1364                                                 verbose git clean -xdf
1365                                                 ;;
1366                                 esac
1367                         fi
1368                         if $killbranches; then
1369                                 git for-each-ref --format='%(refname)' refs/heads/ | while IFS= read -r B; do
1370                                         if [ x"$B" != x"`git symbolic-ref HEAD`" ]; then
1371                                                 verbose git branch -D "${B#refs/heads/}"
1372                                         fi
1373                                 done
1374                                 git rev-parse refs/heads/master >/dev/null 2>&1 || verbose git branch -t master origin/master || true
1375                                 git rev-parse "refs/heads/`repobranch "$d"`" >/dev/null 2>&1 || verbose git branch -t "`repobranch "$d"`" origin/"`repobranch "$d"`" || true
1376                         fi
1377                         checkself "$cmd" "$@"
1378                 done
1379                 ;;
1380
1381         # release building goes here
1382         release-prepare)
1383                 #"$SELF" each git clean -fxd
1384                 case "$RELEASETYPE" in
1385                         beta)
1386                                 msg "Building a BETA"
1387                                 ;;
1388                         release)
1389                                 msg "Building a RELEASE"
1390                                 ;;
1391                         *)
1392                                 $ECHO >&2 -n "$ESC[2J$ESC[H"
1393                                 msg ""
1394                                 msg ""
1395                                 msg ""
1396                                 msg ""
1397                                 msg ""
1398                                 msg ""
1399                                 msg "        +---------------------------------------------------------.---+"
1400                                 msg "        | NOTE                                                    | X |"
1401                                 msg "        +---------------------------------------------------------^---+"
1402                                 msg "        |   ____                                                      |"
1403                                 msg "        |  /    \  This is the official release build system.         |"
1404                                 msg "        | |      | If you are not a member of the Xonotic Core Team,  |"
1405                                 msg "        | | STOP | you are not supposed to use this script and should |"
1406                                 msg "        | |      | instead use ./all compile to compile the engine    |"
1407                                 msg "        |  \____/  and game code.                                     |"
1408                                 msg "        |                                                             |"
1409                                 msg "        |                      [ I understand ]                       |"
1410                                 msg "        +-------------------------------------------------------------+"
1411                                 sleep 10
1412                                 # A LOT of build infrastructure is required:
1413                                 # - vorbis-tools
1414                                 # - ImageMagick
1415                                 # - .ssh/config must be configured so the following
1416                                 #   host names are reachable and have a compile
1417                                 #   infrastructure set up:
1418                                 #   - xonotic-build-linux32 (with gcc on x86)
1419                                 #   - xonotic-build-linux64 (with gcc on x86_64)
1420                                 #   - xonotic-build-win32 (with i586-mingw32msvc-g++)
1421                                 #   - xonotic-build-win64 (with amd64-mingw32msvc-g++
1422                                 #     and x86_64-w64-mingw32-g++)
1423                                 #   - xonotic-build-osx (with Xcode and SDL.framework)
1424                                 # - AMD Compressonator installed in WINE
1425                                 # - ResEdit installed in WINE
1426                                 # - a lot of other requirements you will figure out
1427                                 #   while reading the error messages
1428                                 # - environment variable RELEASETYPE set
1429                                 # - optionally, environment variable RELEASEDATE set
1430                                 #   (YYYYMMDD)
1431                                 exit 1
1432                                 ;;
1433                 esac
1434                 verbose rm -rf Xonotic Xonotic*.zip
1435                 verbose mkdir -p Xonotic
1436                 if [ -n "$RELEASEDATE" ]; then
1437                         verbose $ECHO "$RELEASEDATE" > Xonotic/stamp.txt
1438                 else
1439                         verbose date +%Y%m%d > Xonotic/stamp.txt
1440                 fi
1441                 verbose git archive --format=tar HEAD -- Docs misc server xonotic-linux-glx.sh xonotic-linux-sdl.sh misc/buildfiles key_0.d0pk | {
1442                         verbose cd Xonotic
1443                         verbose mkdir data fteqcc source source/darkplaces source/fteqcc
1444                         verbose tar xvf -
1445                         verbose rm -rf misc/builddeps
1446                         verbose mv misc/buildfiles/win32/* . || true
1447                         verbose mv misc/buildfiles/win64 bin64 || true
1448                         verbose mv misc/buildfiles/osx/* . || true
1449                         verbose rm -rf misc/buildfiles
1450                         verbose rm -rf misc/pki
1451                 }
1452                 {
1453                         verbose cd darkplaces
1454                         verbose git archive --format=tar HEAD
1455                 } | {
1456                         verbose cd Xonotic/source/darkplaces
1457                         verbose tar xvf -
1458                 }
1459                 {
1460                         verbose cd fteqcc
1461                         verbose git archive --format=tar HEAD
1462                 } | {
1463                         verbose cd Xonotic/source/fteqcc
1464                         verbose tar xvf -
1465                 }
1466                 {
1467                         verbose cd data/xonotic-data.pk3dir
1468                         verbose git archive --format=tar HEAD -- qcsrc Makefile
1469                 } | {
1470                         verbose cd Xonotic/source
1471                         verbose tar xvf -
1472                 }
1473                 rm -f Xonotic/key_15.d0pk
1474                 ;;
1475         release-compile-run)
1476                 host=$1
1477                 buildpath=$2
1478                 maketargets=$3
1479                 makeflags=$4
1480                 srcdir=$5
1481                 depsdir=$6
1482                 targetfiles=$7
1483                 set -x
1484                 if [ -n "$targetfiles" ]; then
1485                         case " $HOSTS_THAT_ARE_DISABLED " in
1486                                 *\ $host\ *)
1487                                         exit
1488                                         ;;
1489                         esac
1490                         case " $HOSTS_THAT_ARE_MYSELF " in
1491                                 *\ $host\ *)
1492                                         verbose rsync --delete -zLvaSHP "$srcdir"/ "$buildpath/"
1493                                         verbose rsync --delete -zLvaSHP "$depsdir"/ "$buildpath.deps/"
1494                                         verbose ln -snf "$buildpath.deps" "$buildpath/.deps"
1495                                         verbose eval make -C "$buildpath" clean $maketargets $makeflags
1496                                         for f in $targetfiles; do
1497                                                 verbose mv "$buildpath/${f%:*}" "${f##*:}" || true
1498                                         done
1499                                         ;;
1500                                 *)
1501                                         verbose rsync --delete -zLvaSHP "$srcdir"/ "$host:$buildpath/"
1502                                         verbose rsync --delete -zLvaSHP "$depsdir"/ "$host:$buildpath.deps/"
1503                                         verbose ssh "$host" "ln -snf $buildpath.deps $buildpath/.deps && cd $buildpath && nice -`nice` make clean $maketargets $makeflags"
1504                                         for f in $targetfiles; do
1505                                                 verbose rsync -zvaSHP "$host:$buildpath/${f%:*}" "${f##*:}" || true
1506                                         done
1507                                         ;;
1508                         esac
1509                         # now rebrand the binaries...
1510                         for f in $targetfiles; do
1511                                 #verbose "$d0/misc/tools/rebrand-darkplaces-engine.sh" "${XONOTIC_BRAND:-$d0/misc/tools/xonotic.brand}" "${f##*:}" || true
1512                                 case "${f##*:}" in
1513                                         xonotic*.exe)
1514                                                 verbose "$d0/misc/tools/change-icon-of-exe.sh" "$d0/misc/logos/icons_ico/xonotic.ico" "${f##*:}"
1515                                                 (
1516                                                         d=`mktemp -d -t rebrand.XXXXXX`
1517                                                         cd "$d"
1518                                                         $ECHO "-mygames" > darkplaces.opt
1519                                                         zip -9r darkplaces.zip darkplaces.opt
1520                                                         cat darkplaces.zip
1521                                                         cd "$d0"
1522                                                         rm -rf "$d"
1523                                                 ) >> "${f##*:}"
1524                                                 ;;
1525                                 esac
1526                         done
1527                 fi
1528                 ;;
1529         release-compile)
1530                 suffix=$1
1531                 makeflags=$2
1532                 fteqcc_maketargets=$3
1533                 fteqcc_files=$4
1534                 darkplaces_maketargets=$5
1535                 darkplaces_files=$6
1536                 host=xonotic-build-$suffix
1537                 verbose "$SELF" release-compile-run "$host" /tmp/fteqcc.build."$suffix" "$fteqcc_maketargets" "$makeflags" "Xonotic/source/fteqcc" "$d0/misc/builddeps/dp.$suffix" "$fteqcc_files"
1538                 verbose "$SELF" release-compile-run "$host" /tmp/Darkplaces.build."$suffix" "$darkplaces_maketargets" "$makeflags" "Xonotic/source/darkplaces" "$d0/misc/builddeps/dp.$suffix" "$darkplaces_files"
1539                 ;;
1540         release-engine-win32)
1541                 verbose "$SELF" release-compile win32 \
1542                         'STRIP=: DP_MAKE_TARGET=mingw CC="i586-mingw32msvc-gcc -march=i686 -g -Wl,--dynamicbase -Wl,--nxcompat -I.deps/include -L.deps/lib -DUSE_WSPIAPI_H -DSUPPORTIPV6" WINDRES="i586-mingw32msvc-windres" SDL_CONFIG=".deps/bin/sdl-config" LIB_JPEG= CFLAGS_LIBJPEG= WIN32RELEASE=1 D3D=0' \
1543                         win 'fteqcc.exe:Xonotic/fteqcc/fteqcc.exe' \
1544                         '' ''
1545                 verbose "$SELF" release-compile win32 \
1546                         'STRIP=: DP_MAKE_TARGET=mingw CC="i586-mingw32msvc-gcc -g -Wl,--dynamicbase -Wl,--nxcompat -I.deps/include -L.deps/lib -DUSE_WSPIAPI_H -DSUPPORTIPV6" WINDRES="i586-mingw32msvc-windres" SDL_CONFIG=".deps/bin/sdl-config" LIB_JPEG= CFLAGS_LIBJPEG= WIN32RELEASE=1 D3D=0' \
1547                         '' '' \
1548                         release 'darkplaces.exe:Xonotic/xonotic.exe darkplaces-sdl.exe:Xonotic/xonotic-sdl.exe darkplaces-dedicated.exe:Xonotic/xonotic-dedicated.exe'
1549                 ;;
1550         release-engine-win64)
1551                 verbose "$SELF" release-compile win64 \
1552                         'STRIP=: DP_MAKE_TARGET=mingw CC="amd64-mingw32msvc-gcc -g -Wl,--dynamicbase -Wl,--nxcompat -I.deps/include -L.deps/lib -DSUPPORTIPV6" WINDRES="amd64-mingw32msvc-windres" SDL_CONFIG=".deps/bin/sdl-config" LIB_JPEG= CFLAGS_LIBJPEG= WIN64RELEASE=1 D3D=0' \
1553                         win 'fteqcc.exe:Xonotic/fteqcc/fteqcc-x64.exe' \
1554                         'sv-release sdl-release' 'darkplaces-sdl.exe:Xonotic/xonotic-x64-sdl.exe darkplaces-dedicated.exe:Xonotic/xonotic-x64-dedicated.exe'
1555                 verbose "$SELF" release-compile win64 \
1556                         'STRIP=: DP_MAKE_TARGET=mingw CC="x86_64-w64-mingw32-gcc -g -Wl,--dynamicbase -Wl,--nxcompat -I.deps/include -L.deps/lib -DSUPPORTIPV6" WINDRES="x86_64-w64-mingw32-windres" SDL_CONFIG=".deps/bin/sdl-config" LIB_JPEG= CFLAGS_LIBJPEG= WIN64RELEASE=1 D3D=0' \
1557                         '' '' \
1558                         cl-release 'darkplaces.exe:Xonotic/xonotic-x64.exe'
1559                 ;;
1560         release-engine-osx)
1561                 # gcc on OSX is buggy, needs -fno-reorder-blocks for a release build to succeed
1562                 verbose "$SELF" release-compile osx \
1563                         'STRIP=: CC="gcc -g -arch i386 -arch ppc -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -I.deps/include -L.deps/lib -fno-reorder-blocks -DSUPPORTIPV6"' \
1564                         all 'fteqcc.bin:Xonotic/fteqcc/fteqcc.osx' \
1565                         'sv-release sdl-release' 'darkplaces-sdl:Xonotic/Xonotic-SDL.app/Contents/MacOS/xonotic-osx-sdl-bin darkplaces-dedicated:Xonotic/xonotic-osx-dedicated'
1566                 verbose "$SELF" release-compile osx \
1567                         'STRIP=: CC="gcc -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -I.deps/include -L.deps/lib -fno-reorder-blocks -DSUPPORTIPV6"' \
1568                         '' '' \
1569                         'cl-release' 'darkplaces-agl:Xonotic/Xonotic.app/Contents/MacOS/xonotic-osx-agl-bin'
1570                 ;;
1571         release-engine-linux32)
1572                 verbose "$SELF" release-compile linux32 \
1573                         'STRIP=: CC="gcc -m32 -march=i686 -g -I.deps/include -L.deps/lib -DSUPPORTIPV6" DP_MODPLUG_STATIC_LIBDIR=.deps/lib LIB_JPEG=.deps/lib/libjpeg.a DP_CRYPTO_STATIC_LIBDIR=.deps/lib' \
1574                         all 'fteqcc.bin:Xonotic/fteqcc/fteqcc.linux32' \
1575                         release 'darkplaces-glx:Xonotic/xonotic-linux32-glx darkplaces-sdl:Xonotic/xonotic-linux32-sdl darkplaces-dedicated:Xonotic/xonotic-linux32-dedicated'
1576                 ;;
1577         release-engine-linux64)
1578                 verbose "$SELF" release-compile linux64 \
1579                         'STRIP=: CC="gcc -m64 -g -I.deps/include -L.deps/lib -DSUPPORTIPV6" DP_MODPLUG_STATIC_LIBDIR=.deps/lib LIB_JPEG=.deps/lib/libjpeg.a DP_CRYPTO_STATIC_LIBDIR=.deps/lib' \
1580                         all 'fteqcc.bin:Xonotic/fteqcc/fteqcc.linux64' \
1581                         release 'darkplaces-glx:Xonotic/xonotic-linux64-glx darkplaces-sdl:Xonotic/xonotic-linux64-sdl darkplaces-dedicated:Xonotic/xonotic-linux64-dedicated'
1582                 ;;
1583         release-engine)
1584                 verbose "$SELF" release-engine-linux32 &
1585                 verbose "$SELF" release-engine-linux64 &
1586                 verbose "$SELF" release-engine-win32 &
1587                 verbose "$SELF" release-engine-win64 &
1588                 verbose "$SELF" release-engine-osx &
1589                 wait %1
1590                 wait %2
1591                 wait %3
1592                 wait %4
1593                 wait %5
1594                 wait
1595                 ;;
1596         release-maps)
1597                 verbose "$SELF" update-maps
1598                 ;;
1599         release-qc)
1600                 case "$RELEASETYPE" in
1601                         beta)
1602                                 verbose make -C Xonotic/source FTEQCC="../../../fteqcc/fteqcc.linux32" XON_BUILDSYSTEM=1 clean all
1603                                 # back out of: source/qcsrc/server
1604                                 ;;
1605                         release)
1606                                 verbose make -C Xonotic/source FTEQCC="../../../fteqcc/fteqcc.linux32" XON_BUILDSYSTEM=1 FTEQCCFLAGS_WATERMARK= clean all
1607                                 ;;
1608                 esac
1609                 verbose rm -f Xonotic/source/*/fteqcc.log
1610                 ;;
1611         release-buildpk3-transform-raw)
1612                 dir=$1
1613                 ;;
1614         release-buildpk3-transform-normal)
1615                 dir=$1
1616                 verbose cd "$dir"
1617                 # texture: convert to jpeg and dds
1618                 verbose export do_jpeg=true
1619                 verbose export jpeg_qual_rgb=95
1620                 verbose export jpeg_qual_a=99
1621                 verbose export do_dds=true
1622                 verbose export dds_flags=
1623                 verbose export do_ogg=false
1624                 verbose export del_src=true
1625                 find . -type f -print0 | verbose xargs -0 "$d0"/misc/tools/cached-converter.sh
1626                 ;;
1627         release-buildpk3-transform-low)
1628                 dir=$1
1629                 verbose cd "$dir"
1630                 # texture: convert to jpeg and dds
1631                 # music: reduce bitrate
1632                 verbose export do_jpeg=true
1633                 verbose export jpeg_qual_rgb=80
1634                 verbose export jpeg_qual_a=97
1635                 verbose export do_dds=false
1636                 verbose export do_ogg=true
1637                 verbose export ogg_qual=1
1638                 verbose export del_src=true
1639                 find . -type f -print0 | verbose xargs -0 "$d0"/misc/tools/cached-converter.sh
1640                 ;;
1641         release-buildpk3-transform-lowdds)
1642                 dir=$1
1643                 verbose cd "$dir"
1644                 # texture: convert to jpeg and dds
1645                 # music: reduce bitrate
1646                 verbose export do_jpeg=false
1647                 verbose export do_jpeg_if_not_dds=true
1648                 verbose export jpeg_qual_rgb=80
1649                 verbose export jpeg_qual_a=99
1650                 verbose export do_dds=true
1651                 verbose export dds_flags=
1652                 verbose export do_ogg=true
1653                 verbose export ogg_qual=1
1654                 verbose export del_src=true
1655                 find . -type f -print0 | verbose xargs -0 "$d0"/misc/tools/cached-converter.sh
1656                 ;;
1657         release-buildpk3)
1658                 src=$1
1659                 dst=$2
1660                 transform=$3
1661                 case "$dst" in
1662                         /*)
1663                                 ;;
1664                         */)
1665                                 dst="$PWD/$dst"
1666                                 ;;
1667                 esac
1668                 verbose rm -rf Xonotic/temp
1669                 verbose mkdir -p Xonotic/temp
1670                 {
1671                         verbose cd "$src"
1672                         verbose git archive --format=tar HEAD
1673                 } | {
1674                         verbose cd Xonotic/temp
1675                         verbose tar xvf -
1676                 }
1677                 verbose cd Xonotic/temp
1678                 if [ x"$src" = x"data/xonotic-data.pk3dir" ]; then
1679                         verbose cp ../source/progs.dat .
1680                         verbose cp ../source/csprogs.dat .
1681                         verbose cp ../source/menu.dat .
1682                         verbose rm -rf qcsrc
1683                         gv=`grep "^gameversion " "defaultXonotic.cfg" | awk '{ print $2 }'`
1684                         major=$(($gv / 10000))
1685                         minor=$(($gv / 100 - $major * 100))
1686                         patch=$(($gv - $major * 10000 - $minor * 100))
1687                         versionstr="$major.$minor.$patch"
1688                         case "$RELEASETYPE" in
1689                                 beta)
1690                                         versionstr="$versionstr""beta"
1691                                         ;;
1692                         esac
1693                         verbose sed -i "
1694                                 s/^set g_xonoticversion [^ ]* /set g_xonoticversion $versionstr /;
1695                                 s/^gameversion_min [0-9]*/gameversion_min $(( ($gv / 100) * 100 - 100 ))/;
1696                                 s/^gameversion_max [0-9]*/gameversion_max $(( ($gv / 100) * 100 + 199 ))/;
1697                         " defaultXonotic.cfg
1698                         (
1699                                 verbose cd gfx/menu/luminos
1700                                 verbose cp "$d0"/mediasource/gfx/menu/luminos_versionbuilder/background_l2.svg .
1701                                 verbose "$d0"/mediasource/gfx/menu/luminos_versionbuilder/versionbuilder "$versionstr"
1702                                 verbose rm background_l2.svg
1703                         )
1704                 fi
1705                 if [ x"$src" = x"data/xonotic-maps.pk3dir" ]; then
1706                         for X in ../../data/*-????????????????????????????????????????-????????????????????????????????????????.pk3; do
1707                                 if [ -f "$X" ]; then
1708                                         verbose unzip "$X"
1709                                         verbose rm -f maps/*.log maps/*.irc maps/*.lin
1710                                 fi
1711                         done
1712                 fi
1713                 verbose export git_src_repo="$d0/$src" # skip hash-object
1714                 verbose "$SELF" release-buildpk3-transform-$transform "Xonotic/temp"
1715                 verbose mkzip "../../$dst" *
1716                 verbose cd ../..
1717                 verbose rm -rf Xonotic/temp
1718                 ;;
1719         release-buildpk3s)
1720                 stamp=`cat Xonotic/stamp.txt`
1721                 src=$1
1722                 shift
1723                 dst=${src%.pk3dir}
1724                 case "$dst" in
1725                         data/xonotic-*)
1726                                 dst="data/xonotic-$stamp-${dst#data/xonotic-}"
1727                                 ;;
1728                         *)
1729                                 dst="$dst-$stamp"
1730                                 ;;
1731                 esac
1732                 while [ "$#" -gt 1 ]; do
1733                         verbose "$SELF" release-buildpk3 "$src" "Xonotic/$dst$2.pk3" "$1"
1734                         shift
1735                         shift
1736                 done
1737                 ;;
1738         release-pack)
1739                 verbose "$SELF" release-buildpk3s data/font-nimbussansl.pk3dir             raw ''
1740                 verbose "$SELF" release-buildpk3s data/xonotic-data.pk3dir       normal ''            low '-low' lowdds '-lowdds'
1741                 verbose "$SELF" release-buildpk3s data/xonotic-maps.pk3dir       normal ''            low '-low' lowdds '-lowdds'
1742                 verbose "$SELF" release-buildpk3s data/xonotic-music.pk3dir                raw ''     low '-low'
1743                 verbose "$SELF" release-buildpk3s data/xonotic-nexcompat.pk3dir                       low ''
1744                 ;;
1745         release-pack-needsx11)
1746                 case "$DISPLAY" in
1747                         '')
1748                                 verbose startx "$SELF" release-pack -- /usr/bin/Xvfb :7
1749                                 ;;
1750                         *)
1751                                 verbose "$SELF" release-pack
1752                                 ;;
1753                 esac
1754                 ;;
1755         release-zip)
1756                 stamp=`cat Xonotic/stamp.txt`
1757                 # exe and dll files do not need +x, so this makes them eligible for 7zip compression too
1758                 chmod a-x Xonotic/*.exe Xonotic/*.dll || true
1759                 # let's pass crypto import laws of some nasty countries
1760                 crypto_libs=`find Xonotic -name \*d0_rijndael\*`
1761                 if [ -n "$crypto_libs" ]; then
1762                         verbose mkzip Xonotic-$stamp-crypto.zip \
1763                                 $crypto_libs
1764                         rm -f $crypto_libs
1765                 fi
1766                 # build the archives
1767                 verbose mkzip Xonotic-$stamp-engine.zip \
1768                         Xonotic/*.dll \
1769                         Xonotic/bin64/*.dll \
1770                         Xonotic/*.app \
1771                         Xonotic/xonotic-* \
1772                         Xonotic/xonotic.exe \
1773                         Xonotic/source/darkplaces/
1774                 verbose cp Xonotic-$stamp-engine.zip Xonotic-$stamp-common.zip
1775                 verbose mkzip Xonotic-$stamp-common.zip \
1776                         Xonotic/source/fteqcc/ \
1777                         Xonotic/source/qcsrc/ \
1778                         Xonotic/Docs \
1779                         Xonotic/misc \
1780                         Xonotic/fteqcc \
1781                         Xonotic/server \
1782                         Xonotic/key_0.d0pk \
1783                         Xonotic/data/font-nimbussansl-$stamp.pk3
1784                 verbose cp Xonotic-$stamp-common.zip Xonotic-$stamp.zip
1785                 verbose mkzip0 Xonotic-$stamp.zip \
1786                         Xonotic/data/xonotic-$stamp-data.pk3 \
1787                         Xonotic/data/xonotic-$stamp-maps.pk3 \
1788                         Xonotic/data/xonotic-$stamp-music.pk3 \
1789                         Xonotic/data/xonotic-$stamp-nexcompat.pk3
1790                 verbose cp Xonotic-$stamp-common.zip Xonotic-$stamp-low.zip
1791                 verbose mkzip0 Xonotic-$stamp-low.zip \
1792                         Xonotic/data/xonotic-$stamp-data-low.pk3 \
1793                         Xonotic/data/xonotic-$stamp-maps-low.pk3 \
1794                         Xonotic/data/xonotic-$stamp-music-low.pk3
1795 #               verbose cp Xonotic-$stamp-common.zip Xonotic-$stamp-high.zip
1796 #               verbose mkzip0 Xonotic-$stamp-high.zip \
1797 #                       Xonotic/data/xonotic-$stamp-data-raw.pk3 \
1798 #                       Xonotic/data/xonotic-$stamp-maps-raw.pk3 \
1799 #                       Xonotic/data/xonotic-$stamp-music.pk3 \
1800 #                       Xonotic/data/xonotic-$stamp-nexcompat.pk3
1801                 verbose mv Xonotic-$stamp-common.zip Xonotic-$stamp-lowdds.zip
1802                 verbose mkzip0 Xonotic-$stamp-lowdds.zip \
1803                         Xonotic/data/xonotic-$stamp-data-lowdds.pk3 \
1804                         Xonotic/data/xonotic-$stamp-maps-lowdds.pk3 \
1805                         Xonotic/data/xonotic-$stamp-music-low.pk3
1806                 ;;
1807         release)
1808                 verbose "$SELF" release-prepare
1809                 verbose "$SELF" release-maps
1810                 verbose "$SELF" release-engine
1811                 verbose "$SELF" release-qc
1812                 verbose "$SELF" release-pack-needsx11
1813                 verbose "$SELF" release-zip
1814                 ;;
1815
1816         *)
1817                 $ECHO "Usage:"
1818                 $ECHO "  $SELF admin-merge [<branch>]"
1819                 $ECHO "  $SELF branch <branch>"
1820                 $ECHO "  $SELF branch <remote> <branch> [<srcbranch>]"
1821                 $ECHO "  $SELF branches"
1822                 $ECHO "  $SELF checkout|switch <branch>"
1823                 $ECHO "  $SELF checkout|switch <remote>/<branch>"
1824                 $ECHO "  $SELF clean [-m] [-f | -fu | -fU] [-r] [-D]"
1825                 $ECHO "  $SELF clean --reclone"
1826                 $ECHO "  $SELF compile [-c] [-r] [-0]"
1827                 $ECHO "  $SELF each|foreach [-k] command..."
1828                 $ECHO "  $SELF fix_upstream_rebase"
1829                 $ECHO "  $SELF keygen"
1830                 $ECHO "  $SELF merge"
1831                 $ECHO "  $SELF push|commit [-s]"
1832                 $ECHO "  $SELF release"
1833                 $ECHO "  $SELF restore-patches"
1834                 $ECHO "  $SELF run [sdl|glx|wgl|agl|dedicated] options..."
1835                 $ECHO "  $SELF save-patches"
1836                 $ECHO "  $SELF update-maps"
1837                 $ECHO "  $SELF update|pull [-N] [-s | -h [-p] | -g [-p]] [-l de|nl|default]"
1838                 ;;
1839 esac