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