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