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