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