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