no longer use github URLs for some repos
[xonotic/xonotic.git] / all
1 #!/bin/sh
2 # vim: filetype=zsh
3
4 set -e
5
6 # I use this in EVERY shell script ;)
7 LF="
8 "
9 ESC="\e"
10
11 d00=`pwd`
12 while ! [ -f ./all ]; do
13         if [ x"`pwd`" = x"/" ]; then
14                 echo "Cannot find myself."
15                 echo "Please run this script with the working directory inside a Xonotic checkout."
16                 exit 1
17         fi
18         cd ..
19 done
20 export d0=`pwd`
21 SELF="$d0/all"
22
23 # If we are on WINDOWS:
24 case "$0" in
25         all|*/all)
26                 case "`uname`" in
27                         MINGW*|Win*)
28                                 # Windows hates users. So this script has to copy itself elsewhere first...
29                                 cp "$SELF" ../all.xonotic.sh
30                                 export WE_HATE_OUR_USERS=1
31                                 exec ../all.xonotic.sh "$@"
32                                 ;;
33                 esac
34                 ;;
35 esac
36
37 msg()
38 {
39         echo >&2 "$ESC[1m$*$ESC[m"
40 }
41
42 self=`git hash-object "$SELF"`
43 checkself()
44 {
45         self_new=`git hash-object "$SELF"`
46         if [ x"$self" != x"$self_new" ]; then
47                 msg "./all has changed."
48                 if [ -z "$XONOTIC_FORBID_RERUN_ALL" ]; then
49                         msg "Rerunning the requested operation to make sure."
50                         export XONOTIC_FORBID_RERUN_ALL=1
51                         exec "$SELF" "$@"
52                 else
53                         msg "Please try $SELF update, and then retry your requested operation."
54                         exit 1
55                 fi
56         fi
57         return 0
58 }
59
60 verbose()
61 {
62         msg "+ $*"
63         "$@"
64 }
65
66 visible_repo_name()
67 {
68         case "$1" in
69                 .)
70                         echo "the root directory"
71                         ;;
72                 *)
73                         echo "\"$1\""
74                         ;;
75         esac
76 }
77
78 check_mergeconflict()
79 {
80         if git ls-files -u | grep ' 1   '; then
81                 echo
82                 echo "MERGE CONFLICT."
83                 echo "change into the \"$1\" project directory, and then:"
84                 echo "- edit the files mentioned above with your favorite editor,"
85                 echo "  and fix the conflicts (marked with <<<<<<< blocks)"
86                 echo "- for binary files, you can select the files using"
87                 echo "  git checkout --ours or git checkout --theirs"
88                 echo "- when done with a file, 'git add' the file"
89                 echo "- when done, 'git commit'"
90                 echo
91                 exit 1
92         fi
93 }
94
95 yesno()
96 {
97         yesno=
98         while [ x"$yesno" != x"y" -a x"$yesno" != x"n" ]; do
99                 eval "$2"
100                 echo "$1"
101                 IFS= read -r yesno
102         done
103         [ x"$yesno" = x"y" ]
104 }
105
106 enter()
107 {
108         $2 cd "$1" || exit 1
109         check_mergeconflict "$1"
110 }
111
112 repos_urls="
113 .                             |                                                   | master      |
114 data/xonotic-data.pk3dir      |                                                   | master      |
115 data/xonotic-music.pk3dir     |                                                   | master      |
116 data/xonotic-nexcompat.pk3dir |                                                   | master      | no
117 darkplaces                    |                                                   | div0-stable | svn
118 netradiant                    |                                                   | master      |
119 div0-gittools                 |                                                   | master      | no
120 d0_blind_id                   |                                                   | master      |
121 data/xonotic-maps.pk3dir      |                                                   | master      |
122 mediasource                   |                                                   | master      | no
123 fteqcc                        |                                                   | 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                 snowleopardhack=false
708                 if [ -z "$CC" ]; then
709                         export CC="gcc -DSUPPORTIPV6"
710                 fi
711                 while :; do
712                         case "$1" in
713                                 -0)
714                                         compiled0=true
715                                         shift
716                                         ;;
717                                 -c)
718                                         cleand0=true
719                                         cleandp=true
720                                         cleanqcc=true
721                                         cleanqc=true
722                                         shift
723                                         ;;
724                                 -r)
725                                         debug=release
726                                         export CC="$CC -g -mtune=native -march=native"
727                                         shift
728                                         ;;
729                                 *)
730                                         break
731                                         ;;
732                         esac
733                 done
734                 if [ -n "$WE_HATE_OUR_USERS" ]; then
735                         TARGETS="sv-$debug cl-$debug"
736                 elif [ x"`uname`" = x"Darwin" ]; then
737                         case "`uname -r`" in
738                                 ?.*)
739                                         TARGETS="sv-$debug cl-$debug sdl-$debug"
740                                         ;;
741                                 *)
742                                         # AGL cannot be compiled on systems with a kernel > 10.x (Snow Leopard)
743                                         snowleopardhack=true
744                                         TARGETS="sv-$debug sdl-$debug"
745                                         ;;
746                         esac
747                         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"
748                 else
749                         TARGETS="sv-$debug cl-$debug sdl-$debug"
750                 fi
751                 if [ $# -gt 0 ] && [ x"$1" = x"" ]; then
752                         # if we give the command make the arg "", it will surely fail (invalid filename),
753                         # so better handle it as an empty client option
754                         BAD_TARGETS=" "
755                         shift
756                 elif [ -n "$1" ]; then
757                         BAD_TARGETS=
758                         TARGETS_SAVE=$TARGETS
759                         TARGETS=
760                         for X in $1; do
761                                 case "$X" in
762                                         sdl)
763                                                 TARGETS="$TARGETS sdl-debug"
764                                                 ;;
765                                         agl)
766                                                 TARGETS="$TARGETS cl-debug"
767                                                 if $snowleopardhack; then
768                                                         export CC="$CC -arch i386"
769                                                 fi
770                                                 ;;
771                                         glx|wgl)
772                                                 TARGETS="$TARGETS cl-debug"
773                                                 ;;
774                                         dedicated)
775                                                 TARGETS="$TARGETS sv-debug"
776                                                 ;;
777                                         *)
778                                                 BAD_TARGETS="$BAD_TARGETS $X"
779                                                 ;;
780                                 esac
781                         done
782                         if [ -n "$TARGETS" ]; then # at least a valid client
783                                 shift
784                         else # no valid client, let's assume this option is not meant to be a client then
785                                 TARGETS=$TARGETS_SAVE
786                                 BAD_TARGETS=
787                         fi
788                 fi
789                 if [ -z "$MAKEFLAGS" ]; then
790                         if [ -f /proc/cpuinfo ]; then
791                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
792                                 if [ $ncpus -gt 1 ]; then
793                                         MAKEFLAGS=-j$ncpus
794                                 fi
795                         fi
796                         if [ -n "$WE_HATE_OUR_USERS" ]; then
797                                 MAKEFLAGS="$MAKEFLAGS DP_MAKE_TARGET=mingw LIB_JPEG= CFLAGS_LIBJPEG="
798                         fi
799                 fi
800
801                 enter "$d0/d0_blind_id" verbose
802                 if ! $compiled0; then
803                         # compilation of crypto library failed
804                         # use binaries then, if we can...
805                         mkdir -p .libs
806                         if [ -n "$WE_HATE_OUR_USERS" ]; then
807                                 verbose cp "$d0/misc/buildfiles/win32/libd0_blind_id"-* .libs/
808                                 verbose cp "$d0/misc/buildfiles/win32/libgmp"-* .libs/
809                         else
810                                 case "`uname`" in
811                                         Linux)
812                                                 case `uname -m` in
813                                                         x86_64)
814                                                                 verbose cp "$d0/misc/builddeps/dp.linux64/lib/libd0_blind_id".* .libs/
815                                                                 verbose cp "$d0/misc/builddeps/dp.linux64/lib/libgmp".* .libs/
816                                                                 MAKEFLAGS="$MAKEFLAGS DP_CRYPTO_STATIC_LIBDIR=../misc/builddeps/dp.linux64/lib/"
817                                                                 ;;
818                                                         *86)
819                                                                 verbose cp "$d0/misc/builddeps/dp.linux32/lib/libd0_blind_id".* .libs/
820                                                                 verbose cp "$d0/misc/builddeps/dp.linux32/lib/libgmp".* .libs/
821                                                                 MAKEFLAGS="$MAKEFLAGS DP_CRYPTO_STATIC_LIBDIR=../misc/builddeps/dp.linux32/lib/"
822                                                                 ;;
823                                                         *)
824                                                                 compiled0=true
825                                                                 ;;
826                                                 esac
827                                                 ;;
828                                         Darwin)
829                                                 verbose cp "$d0/misc/buildfiles/osx/Xonotic.app/Contents/MacOS/libd0_blind_id".* .libs/
830                                                 ;;
831                                         *)
832                                                 compiled0=true
833                                                 ;;
834                                 esac
835                         fi
836                 fi
837                 if $compiled0; then
838                         if $cleand0; then
839                                 if [ -f Makefile ]; then
840                                         verbose make $MAKEFLAGS distclean
841                                 fi
842                         fi
843                         if ! [ -f Makefile ]; then
844                                 verbose sh autogen.sh
845                                 verbose ./configure
846                         fi
847                         verbose make $MAKEFLAGS
848                 fi
849
850                 enter "$d0/fteqcc" verbose
851                 if $cleanqcc; then
852                         verbose make $MAKEFLAGS clean
853                 fi
854                 verbose make $MAKEFLAGS
855
856                 enter "$d0/data/xonotic-data.pk3dir" verbose
857                 if $cleanqc; then
858                         verbose make FTEQCC="../../../../fteqcc/fteqcc.bin" "$@" $MAKEFLAGS clean
859                 fi
860                 verbose make FTEQCC="../../../../fteqcc/fteqcc.bin" "$@" $MAKEFLAGS
861                 # 4 levels up: data, xonotic-data, qcsrc, server
862
863                 enter "$d0/darkplaces" verbose
864                 if [ x"$BAD_TARGETS" = x" " ]; then
865                         echo "Warning: invalid empty client, default clients will be used."
866                 fi
867                 if $cleandp; then
868                         verbose make $MAKEFLAGS clean
869                 fi
870                 for T in $TARGETS; do
871                         verbose make $MAKEFLAGS STRIP=: "$@" "$T"
872                 done
873                 for T in $BAD_TARGETS; do
874                         echo "Warning: discarded invalid client $T."
875                 done
876
877                 verbose "$SELF" update-maps
878                 ;;
879         run)
880                 if [ -n "$WE_HATE_OUR_USERS" ]; then
881                         client=
882                         export PATH="$d0/misc/buildfiles/win32:$d0/d0_blind_id/.libs:$PATH"
883                 elif [ x"`uname`" = x"Darwin" ]; then
884                         export DYLD_LIBRARY_PATH="$d0/misc/buildfiles/osx/Xonotic-SDL.app/Contents/MacOS:$d0/d0_blind_id/.libs"
885                         export DYLD_FRAMEWORK_PATH="$d0/misc/buildfiles/osx/Xonotic-SDL.app/Contents/Frameworks"
886                         client=-sdl
887                 else
888                         export LD_LIBRARY_PATH="$d0/d0_blind_id/.libs"
889                         client=-sdl
890                 fi
891                 case "$1" in
892                         sdl|glx|agl|dedicated)
893                                 client=-$1
894                                 shift
895                                 ;;
896                         wgl)
897                                 client=
898                                 shift
899                                 ;;
900                 esac
901                 if ! [ -x "darkplaces/darkplaces$client" ]; then
902                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
903                                 client=$client.exe
904                         else
905                                 echo "Client darkplaces/darkplaces$client not found, aborting"
906                                 exit 1
907                         fi
908                 fi
909                 set -- "darkplaces/darkplaces$client" -xonotic -mygames "$@"
910
911                 # if pulseaudio is running: USE IT
912                 if [ -z "$SDL_AUDIODRIVER" ] && ! [ -n "$WE_HATE_OUR_USERS" ] && ! [ x"`uname`" = x"Darwin" ]; then
913                         if ps -C pulseaudio >/dev/null; then
914                                 if ldd /usr/lib/libSDL.so 2>/dev/null | grep pulse >/dev/null; then
915                                         export SDL_AUDIODRIVER=pulse
916                                 fi
917                         fi
918                 fi
919
920                 binary=$1
921
922                 if [ -n "$USE_GDB" ]; then
923                         set -- gdb --args "$@"
924                 elif which gdb >/dev/null 2>&1; then
925                         set -- gdb --batch -x savecore.gdb --args "$@"
926                 elif which catchsegv >/dev/null 2>&1; then
927                         set -- catchsegv "$@"
928                 fi
929                 rm -f xonotic.core
930                 "$@" || true
931                 if [ -f xonotic.core ]; then
932                         if yesno "The program has CRASHED. Do you want to examine the core dump?"; then
933                                 gdb "$binary" xonotic.core
934                         #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
935                         #       tar cvzf xonotic.core.tar.gz xonotic.core darkplaces/*.c darkplaces/*.h
936                         #       # somehow send it
937                         #       rm -f xonotic.core.tar.gz
938                         else
939                                 echo "The core dump can be examined later by"
940                                 echo "  gdb $binary xonotic.core"
941                         fi
942                 fi
943                 ;;
944         each|foreach)
945                 keep_going=false
946                 if [ x"$1" = x"-k" ]; then
947                         keep_going=true
948                         shift
949                 fi
950                 for d in $repos; do
951                         if verbose cd "$d0/$d"; then
952                                 if $keep_going; then
953                                         verbose "$@" || true
954                                 else
955                                         verbose "$@"
956                                 fi
957                                 cd "$d0"
958                         fi
959                 done
960                 ;;
961         save-patches)
962                 outfile=$1
963                 patchdir=`mktemp -d -t save-patches.XXXXXX`
964                 for d in $repos; do
965                         enter "$d0/$d" verbose
966                         git branch -v -v | cut -c 3- | {
967                                 i=0
968                                 while read -r BRANCH REV UPSTREAM TEXT; do
969                                         case "$UPSTREAM" in
970                                                 \[*)
971                                                         UPSTREAM=${UPSTREAM#\[}
972                                                         UPSTREAM=${UPSTREAM%\]}
973                                                         UPSTREAM=${UPSTREAM%:*}
974                                                         TRACK=true
975                                                         ;;
976                                                 *)
977                                                         UPSTREAM=origin/"`repobranch "$d"`"
978                                                         TRACK=false
979                                                         ;;
980                                         esac
981                                         if [ x"$REV" = x"->" ]; then
982                                                 continue
983                                         fi
984                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
985                                                 echo "$d" > "$patchdir/$i/info.txt"
986                                                 echo "$BRANCH" >> "$patchdir/$i/info.txt"
987                                                 echo "$UPSTREAM" >> "$patchdir/$i/info.txt"
988                                                 echo "$TRACK" >> "$patchdir/$i/info.txt"
989                                                 i=$(($i+1))
990                                         else
991                                                 rm -rf "$patchdir/$i"
992                                         fi
993                                 done
994                         }
995                 done
996                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
997                 rm -rf "$patchdir"
998                 ;;
999         restore-patches)
1000                 infile=$1
1001                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
1002                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
1003                 # detach the head
1004                 for P in "$patchdir"/*/info.txt; do
1005                         D=${P%/info.txt}
1006                         exec 3<"$P"
1007                         read -r d <&3
1008                         read -r BRANCH <&3
1009                         read -r UPSTREAM <&3
1010                         read -r TRACK <&3
1011                         verbose git checkout HEAD^0
1012                         verbose git branch -D "$BRANCH"
1013                         if [ x"$TRACK" = x"true" ]; then
1014                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
1015                         else
1016                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
1017                         fi
1018                         verbose git am "$D"
1019                 done
1020                 rm -rf "$patchdir"
1021                 ;;
1022         admin-merge)
1023                 branch=$1
1024                 t=`mktemp`
1025                 report=""
1026                 reportecho()
1027                 {
1028                         report=$report"$*$LF"
1029                         echo "$*"
1030                 }
1031                 reportecho4()
1032                 {
1033                         report=$report"    $*$LF"
1034                         echo "    $*"
1035                 }
1036                 reportdo4()
1037                 {
1038                         o=`"$@" | sed 's/^/    /' || true`
1039                         reportecho "$o"
1040                 }
1041                 for d in $repos; do
1042                         enter "$d0/$d" verbose
1043                         base="`repobranch "$d"`"
1044                         reportecho "In $d:"
1045                         for ref in `git for-each-ref --format='%(refname)' refs/remotes/origin/`; do
1046                                 case "${ref#refs/remotes/origin/}" in
1047                                         "$base")
1048                                                 continue
1049                                                 ;;
1050                                         HEAD|master)
1051                                                 continue
1052                                                 ;;
1053                                         */*)
1054                                                 ;;
1055                                         *)
1056                                                 continue
1057                                                 ;;
1058                                 esac
1059                                 if [ -n "$branch" ]; then
1060                                         if [ x"$branch" != x"${ref#refs/remotes/origin/}" ]; then
1061                                                 continue
1062                                         fi
1063                                 fi
1064                                 case "$base" in
1065                                         master)
1066                                                 realbase=$base
1067                                                 ;;
1068                                         *)
1069                                                 l0=`git rev-list "$base".."$ref" | wc -l`
1070                                                 l1=`git rev-list master.."$ref" | wc -l`
1071                                                 if [ $l0 -gt $l1 ]; then
1072                                                         realbase=master
1073                                                 else
1074                                                         realbase=$base
1075                                                 fi
1076                                                 ;;
1077                                 esac
1078                                 reportecho "  Branch $ref:"
1079                                 note=`GIT_NOTES_REF=refs/notes/admin-merge git notes show "$ref" 2>/dev/null || true`
1080                                 logdata=`git log --color "$realbase".."$ref"`
1081                                 if [ -z "$logdata" ]; then
1082                                         reportecho4 "--> not merging, no changes vs master"
1083                                         if yesno "Branch \"$ref\" probably should get deleted. Do it?" ''; then
1084                                                 git push origin :"${ref#refs/remotes/origin/}"
1085                                                 reportecho4 "--> branch deleted"
1086                                         fi
1087                                 else
1088                                         diffdata=`git diff --color --find-copies-harder --ignore-space-change "$realbase"..."$ref"`
1089                                         if [ -z "$diffdata" ]; then
1090                                                 reportecho4 "--> not merging, no changes vs master, branch contains redundant history"
1091                                                 if yesno "Branch \"$ref\" probably should get deleted. Do it?" '{ echo "$logdata"; } | less -r'; then
1092                                                         git push origin :"${ref#refs/remotes/origin/}"
1093                                                         reportecho4 "--> branch deleted"
1094                                                 fi
1095                                         elif [ -z "$branch" ] && [ -n "$note" ]; then
1096                                                 reportdo4 echo "$note"
1097                                                 reportecho4 "--> not merging, already had this one rejected before"
1098                                         elif yesno "Branch \"$ref\" may want to get merged. Do it?" '{ echo "$logdata"; echo "$diffdata"; } | less -r'; then
1099                                                 git checkout "$realbase"
1100                                                 org=`git rev-parse HEAD`
1101                                                 if ! git merge --no-ff "$ref" 2>&1 | tee "$t" && ! { git ls-files -u | grep ' 1 ' >/dev/null; }; then
1102                                                         git reset --hard "$org"
1103                                                         GIT_NOTES_REF=refs/notes/admin-merge git notes edit -m "Merge failed:$LF`cat "$t"`" "$ref"
1104                                                         reportdo4 cat "$t"
1105                                                         reportecho4 "--> merge failed"
1106                                                 elif ! "$SELF" compile 2>&1 | tee "$t"; then
1107                                                         git reset --hard "$org"
1108                                                         GIT_NOTES_REF=refs/notes/admin-merge git notes edit -m "Compile failed:$LF`cat "$t"`" "$ref"
1109                                                         reportdo4 cat "$t"
1110                                                         reportecho4 "--> compile failed"
1111                                                 elif ! yesno "Still merge \"$ref\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."; then
1112                                                         git reset --hard "$org"
1113                                                         GIT_NOTES_REF=refs/notes/admin-merge git notes edit "$ref"
1114                                                         note=`GIT_NOTES_REF=refs/notes/admin-merge git notes show "$ref" 2>/dev/null || true`
1115                                                         if [ x"$note" = x"del" ]; then
1116                                                                 git push origin :"${ref#refs/remotes/origin/}"
1117                                                                 reportecho4 "--> test failed, branch deleted"
1118                                                         elif [ -n "$note" ]; then
1119                                                                 reportdo4 echo "$note"
1120                                                                 reportecho4 "--> test failed"
1121                                                         else
1122                                                                 reportecho4 "--> test failed, postponed"
1123                                                         fi
1124                                                 else
1125                                                         echo "MERGING"
1126                                                         case ",`repoflags "$d"`," in
1127                                                                 *,svn,*)
1128                                                                         # we do quite a mess here... luckily we know $org
1129                                                                         git fetch # svn needs to be current
1130                                                                         git rebase -i --onto origin/master "$org"
1131                                                                         git svn dcommit --add-author-from
1132                                                                         git reset --hard "$org"
1133                                                                         ;;
1134                                                                 *)
1135                                                                         git push origin HEAD
1136                                                                         ;;
1137                                                         esac
1138                                                         reportecho4 "--> MERGED"
1139                                                         if yesno "Delete original branch \"$ref\"?"; then
1140                                                                 git push origin :"${ref#refs/remotes/origin/}"
1141                                                                 reportecho4 "--> branch deleted"
1142                                                         fi
1143                                                 fi
1144                                         else
1145                                                 GIT_NOTES_REF=refs/notes/admin-merge git notes edit "$ref"
1146                                                 note=`GIT_NOTES_REF=refs/notes/admin-merge git notes show "$ref" 2>/dev/null || true`
1147                                                 if [ x"$note" = x"del" ]; then
1148                                                         git push origin :"${ref#refs/remotes/origin/}"
1149                                                         reportecho4 "--> branch deleted"
1150                                                 elif [ -n "$note" ]; then
1151                                                         reportdo4 echo "$note"
1152                                                         reportecho4 "--> rejected"
1153                                                 else
1154                                                         reportecho4 "--> postponed"
1155                                                 fi
1156                                         fi
1157                                 fi
1158                                 reportecho ""
1159                         done
1160                         reportecho ""
1161                 done
1162                 rm -f "$t"
1163                 echo "$report" | ssh nexuiz@rm.endoftheinternet.org cat '>>' public_html/xonotic-merge-notes.txt
1164                 ;;
1165         clean)
1166                 "$SELF" fix_config
1167                 "$SELF" update -N
1168                 force=false
1169                 gotoupstream=false
1170                 fetchupstream=false
1171                 gotomaster=false
1172                 rmuntracked=false
1173                 killbranches=false
1174                 # usage:
1175                 #   ./all clean [-m] [-f | -fu | -fU] [-r] [-D]
1176                 #   ./all clean --reclone
1177                 found=false
1178                 for X in "$@"; do
1179                         if [ x"$X" = x"--reclone" ]; then
1180                                 force=true
1181                                 fetchupstream=true
1182                                 gotoupstream=true
1183                                 gotomaster=true
1184                                 rmuntracked=true
1185                                 killbranches=true
1186                         elif [ x"$X" = x"-f" ]; then
1187                                 force=true
1188                         elif [ x"$X" = x"-u" ]; then
1189                                 gotoupstream=true
1190                         elif [ x"$X" = x"-U" ]; then
1191                                 gotoupstream=true
1192                                 fetchupstream=true
1193                         elif [ x"$X" = x"-fu" ]; then
1194                                 force=true
1195                                 gotoupstream=true
1196                         elif [ x"$X" = x"-fU" ]; then
1197                                 force=true
1198                                 gotoupstream=true
1199                                 fetchupstream=true
1200                         elif [ x"$X" = x"-m" ]; then
1201                                 gotomaster=true
1202                         elif [ x"$X" = x"-r" ]; then
1203                                 rmuntracked=true
1204                         elif [ x"$X" = x"-D" ]; then
1205                                 killbranches=true
1206                         else
1207                                 break
1208                         fi
1209                         found=true
1210                         shift
1211                 done
1212                 if ! $found; then
1213                         rmuntracked=true
1214                 fi
1215                 for d in $repos; do
1216                         verbose cd "$d0/$d"
1217                         if $gotoupstream; then
1218                                 if ! $force; then
1219                                         msg "Must also use -f (delete local changes) when using -u"
1220                                         exit 1
1221                                 fi
1222                                 if $gotomaster; then
1223                                         if $fetchupstream; then
1224                                                 verbose git fetch origin
1225                                                 verbose git remote prune origin
1226                                         fi
1227                                         verbose git checkout -f "`repobranch "$d"`"
1228                                         verbose git reset --hard origin/"`repobranch "$d"`"
1229                                 else
1230                                         r=`git symbolic-ref HEAD`
1231                                         r=${r#refs/heads/}
1232                                         rem=`git config "branch.$r.remote" || echo origin`
1233                                         bra=`git config "branch.$r.merge" || echo "$r"`
1234                                         upstream="$rem/${bra#refs/heads/}"
1235                                         if $fetchupstream; then
1236                                                 verbose git fetch "$rem"
1237                                                 verbose git remote prune "$rem"
1238                                         fi
1239                                         if ! git rev-parse "$upstream" >/dev/null 2>&1; then
1240                                                 upstream="origin/`repobranch "$d"`"
1241                                         fi
1242                                         verbose git reset --hard "$upstream"
1243                                 fi
1244                         elif $gotomaster; then
1245                                 if $force; then
1246                                         verbose git checkout -f "`repobranch "$d"`"
1247                                         verbose git reset --hard
1248                                 else
1249                                         verbose git checkout "`repobranch "$d"`"
1250                                 fi
1251                         elif $force; then
1252                                 verbose git reset --hard
1253                         fi
1254                         if $rmuntracked; then
1255                                 case "$d" in
1256                                         .)
1257                                                 verbose git clean -df
1258                                                 ;;
1259                                         *)
1260                                                 verbose git clean -xdf
1261                                                 ;;
1262                                 esac
1263                         fi
1264                         if $killbranches; then
1265                                 git for-each-ref --format='%(refname)' refs/heads/ | while IFS= read -r B; do
1266                                         if [ x"$B" != x"`git symbolic-ref HEAD`" ]; then
1267                                                 verbose git branch -D "${B#refs/heads/}"
1268                                         fi
1269                                 done
1270                                 git rev-parse refs/heads/master >/dev/null 2>&1 || verbose git branch -t master origin/master || true
1271                                 git rev-parse "refs/heads/`repobranch "$d"`" >/dev/null 2>&1 || verbose git branch -t "`repobranch "$d"`" origin/"`repobranch "$d"`" || true
1272                         fi
1273                         checkself "$cmd" "$@"
1274                 done
1275                 ;;
1276
1277         # release building goes here
1278         release-prepare)
1279                 #"$SELF" each git clean -fxd
1280                 case "$RELEASETYPE" in
1281                         beta)
1282                                 msg "Building a BETA"
1283                                 ;;
1284                         release)
1285                                 msg "Building a RELEASE"
1286                                 ;;
1287                         *)
1288                                 echo >&2 -n "$ESC[2J$ESC[H"
1289                                 msg ""
1290                                 msg ""
1291                                 msg ""
1292                                 msg ""
1293                                 msg ""
1294                                 msg ""
1295                                 msg "        +---------------------------------------------------------.---+"
1296                                 msg "        | NOTE                                                    | X |"
1297                                 msg "        +---------------------------------------------------------^---+"
1298                                 msg "        |   ____                                                      |"
1299                                 msg "        |  /    \  This is the official release build system.         |"
1300                                 msg "        | |      | If you are not a member of the Xonotic Core Team,  |"
1301                                 msg "        | | STOP | you are not supposed to use this script and should |"
1302                                 msg "        | |      | instead use ./all compile to compile the engine    |"
1303                                 msg "        |  \____/  and game code.                                     |"
1304                                 msg "        |                                                             |"
1305                                 msg "        |                      [ I understand ]                       |"
1306                                 msg "        +-------------------------------------------------------------+"
1307                                 sleep 10
1308                                 # A LOT of build infrastructure is required:
1309                                 # - vorbis-tools
1310                                 # - ImageMagick
1311                                 # - .ssh/config must be configured so the following
1312                                 #   host names are reachable and have a compile
1313                                 #   infrastructure set up:
1314                                 #   - xonotic-build-linux32 (with gcc on x86)
1315                                 #   - xonotic-build-linux64 (with gcc on x86_64)
1316                                 #   - xonotic-build-win32 (with i586-mingw32msvc-g++)
1317                                 #   - xonotic-build-win64 (with amd64-mingw32msvc-g++
1318                                 #     and x86_64-w64-mingw32-g++)
1319                                 #   - xonotic-build-osx (with Xcode and SDL.framework)
1320                                 # - AMD Compressonator installed in WINE
1321                                 # - ResEdit installed in WINE
1322                                 # - a lot of other requirements you will figure out
1323                                 #   while reading the error messages
1324                                 # - environment variable RELEASETYPE set
1325                                 # - optionally, environment variable RELEASEDATE set
1326                                 #   (YYYYMMDD)
1327                                 exit 1
1328                                 ;;
1329                 esac
1330                 verbose rm -rf Xonotic Xonotic*.zip
1331                 verbose mkdir -p Xonotic
1332                 if [ -n "$RELEASEDATE" ]; then
1333                         verbose echo "$RELEASEDATE" > Xonotic/stamp.txt
1334                 else
1335                         verbose date +%Y%m%d > Xonotic/stamp.txt
1336                 fi
1337                 verbose git archive --format=tar HEAD -- Docs misc server xonotic-linux-glx.sh xonotic-linux-sdl.sh misc/buildfiles key_0.d0pk | {
1338                         verbose cd Xonotic
1339                         verbose mkdir data fteqcc source source/darkplaces source/fteqcc
1340                         verbose tar xvf -
1341                         verbose rm -rf misc/builddeps
1342                         verbose mv misc/buildfiles/win32/* . || true
1343                         verbose mv misc/buildfiles/win64 bin64 || true
1344                         verbose mv misc/buildfiles/osx/* . || true
1345                         verbose rm -rf misc/buildfiles
1346                         verbose rm -rf misc/pki
1347                 }
1348                 {
1349                         verbose cd darkplaces
1350                         verbose git archive --format=tar HEAD
1351                 } | {
1352                         verbose cd Xonotic/source/darkplaces
1353                         verbose tar xvf -
1354                 }
1355                 {
1356                         verbose cd fteqcc
1357                         verbose git archive --format=tar HEAD
1358                 } | {
1359                         verbose cd Xonotic/source/fteqcc
1360                         verbose tar xvf -
1361                 }
1362                 {
1363                         verbose cd data/xonotic-data.pk3dir
1364                         verbose git archive --format=tar HEAD -- qcsrc Makefile
1365                 } | {
1366                         verbose cd Xonotic/source
1367                         verbose tar xvf -
1368                 }
1369                 rm -f Xonotic/key_15.d0pk
1370                 ;;
1371         release-compile-run)
1372                 host=$1
1373                 buildpath=$2
1374                 maketargets=$3
1375                 makeflags=$4
1376                 srcdir=$5
1377                 depsdir=$6
1378                 targetfiles=$7
1379                 set -x
1380                 if [ -n "$targetfiles" ]; then
1381                         case " $HOSTS_THAT_ARE_DISABLED " in
1382                                 *\ $host\ *)
1383                                         exit
1384                                         ;;
1385                         esac
1386                         case " $HOSTS_THAT_ARE_MYSELF " in
1387                                 *\ $host\ *)
1388                                         verbose rsync --delete -zLvaSHP "$srcdir"/ "$buildpath/"
1389                                         verbose rsync --delete -zLvaSHP "$depsdir"/ "$buildpath.deps/"
1390                                         verbose ln -snf "$buildpath.deps" "$buildpath/.deps"
1391                                         verbose eval make -C "$buildpath" clean $maketargets $makeflags
1392                                         for f in $targetfiles; do
1393                                                 verbose mv "$buildpath/${f%:*}" "${f##*:}" || true
1394                                         done
1395                                         ;;
1396                                 *)
1397                                         verbose rsync --delete -zLvaSHP "$srcdir"/ "$host:$buildpath/"
1398                                         verbose rsync --delete -zLvaSHP "$depsdir"/ "$host:$buildpath.deps/"
1399                                         verbose ssh "$host" "ln -snf $buildpath.deps $buildpath/.deps && cd $buildpath && nice -`nice` make clean $maketargets $makeflags"
1400                                         for f in $targetfiles; do
1401                                                 verbose rsync -zvaSHP "$host:$buildpath/${f%:*}" "${f##*:}" || true
1402                                         done
1403                                         ;;
1404                         esac
1405                         # now rebrand the binaries...
1406                         for f in $targetfiles; do
1407                                 #verbose "$d0/misc/tools/rebrand-darkplaces-engine.sh" "${XONOTIC_BRAND:-$d0/misc/tools/xonotic.brand}" "${f##*:}" || true
1408                                 case "${f##*:}" in
1409                                         xonotic*.exe)
1410                                                 verbose "$d0/misc/tools/change-icon-of-exe.sh" "$d0/misc/logos/icons_ico/xonotic.ico" "${f##*:}"
1411                                                 (
1412                                                         d=`mktemp -d -t rebrand.XXXXXX`
1413                                                         cd "$d"
1414                                                         echo "-mygames" > darkplaces.opt
1415                                                         zip -9r darkplaces.zip darkplaces.opt
1416                                                         cat darkplaces.zip
1417                                                         cd "$d0"
1418                                                         rm -rf "$d"
1419                                                 ) >> "${f##*:}"
1420                                                 ;;
1421                                 esac
1422                         done
1423                 fi
1424                 ;;
1425         release-compile)
1426                 suffix=$1
1427                 makeflags=$2
1428                 fteqcc_maketargets=$3
1429                 fteqcc_files=$4
1430                 darkplaces_maketargets=$5
1431                 darkplaces_files=$6
1432                 host=xonotic-build-$suffix
1433                 verbose "$SELF" release-compile-run "$host" /tmp/fteqcc.build."$suffix" "$fteqcc_maketargets" "$makeflags" "Xonotic/source/fteqcc" "$d0/misc/builddeps/dp.$suffix" "$fteqcc_files"
1434                 verbose "$SELF" release-compile-run "$host" /tmp/Darkplaces.build."$suffix" "$darkplaces_maketargets" "$makeflags" "Xonotic/source/darkplaces" "$d0/misc/builddeps/dp.$suffix" "$darkplaces_files"
1435                 ;;
1436         release-engine-win32)
1437                 verbose "$SELF" release-compile win32 \
1438                         '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' \
1439                         win 'fteqcc.exe:Xonotic/fteqcc/fteqcc.exe' \
1440                         '' ''
1441                 verbose "$SELF" release-compile win32 \
1442                         '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' \
1443                         '' '' \
1444                         release 'darkplaces.exe:Xonotic/xonotic.exe darkplaces-sdl.exe:Xonotic/xonotic-sdl.exe darkplaces-dedicated.exe:Xonotic/xonotic-dedicated.exe'
1445                 ;;
1446         release-engine-win64)
1447                 verbose "$SELF" release-compile win64 \
1448                         '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' \
1449                         win 'fteqcc.exe:Xonotic/fteqcc/fteqcc-x64.exe' \
1450                         'sv-release sdl-release' 'darkplaces-sdl.exe:Xonotic/xonotic-x64-sdl.exe darkplaces-dedicated.exe:Xonotic/xonotic-x64-dedicated.exe'
1451                 verbose "$SELF" release-compile win64 \
1452                         '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' \
1453                         '' '' \
1454                         cl-release 'darkplaces.exe:Xonotic/xonotic-x64.exe'
1455                 ;;
1456         release-engine-osx)
1457                 # gcc on OSX is buggy, needs -fno-reorder-blocks for a release build to succeed
1458                 verbose "$SELF" release-compile osx \
1459                         '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"' \
1460                         all 'fteqcc.bin:Xonotic/fteqcc/fteqcc.osx' \
1461                         'sv-release sdl-release' 'darkplaces-sdl:Xonotic/Xonotic-SDL.app/Contents/MacOS/xonotic-osx-sdl-bin darkplaces-dedicated:Xonotic/xonotic-osx-dedicated'
1462                 verbose "$SELF" release-compile osx \
1463                         '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"' \
1464                         '' '' \
1465                         'cl-release' 'darkplaces-agl:Xonotic/Xonotic.app/Contents/MacOS/xonotic-osx-agl-bin'
1466                 ;;
1467         release-engine-linux32)
1468                 verbose "$SELF" release-compile linux32 \
1469                         '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' \
1470                         all 'fteqcc.bin:Xonotic/fteqcc/fteqcc.linux32' \
1471                         release 'darkplaces-glx:Xonotic/xonotic-linux32-glx darkplaces-sdl:Xonotic/xonotic-linux32-sdl darkplaces-dedicated:Xonotic/xonotic-linux32-dedicated'
1472                 ;;
1473         release-engine-linux64)
1474                 verbose "$SELF" release-compile linux64 \
1475                         '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' \
1476                         all 'fteqcc.bin:Xonotic/fteqcc/fteqcc.linux64' \
1477                         release 'darkplaces-glx:Xonotic/xonotic-linux64-glx darkplaces-sdl:Xonotic/xonotic-linux64-sdl darkplaces-dedicated:Xonotic/xonotic-linux64-dedicated'
1478                 ;;
1479         release-engine)
1480                 verbose "$SELF" release-engine-linux32 &
1481                 verbose "$SELF" release-engine-linux64 &
1482                 verbose "$SELF" release-engine-win32 &
1483                 verbose "$SELF" release-engine-win64 &
1484                 verbose "$SELF" release-engine-osx &
1485                 wait %1
1486                 wait %2
1487                 wait %3
1488                 wait %4
1489                 wait %5
1490                 wait
1491                 ;;
1492         release-maps)
1493                 verbose "$SELF" update-maps
1494                 ;;
1495         release-qc)
1496                 case "$RELEASETYPE" in
1497                         beta)
1498                                 verbose make -C Xonotic/source FTEQCC="../../../fteqcc/fteqcc.linux32" XON_BUILDSYSTEM=1 clean all
1499                                 # back out of: source/qcsrc/server
1500                                 ;;
1501                         release)
1502                                 verbose make -C Xonotic/source FTEQCC="../../../fteqcc/fteqcc.linux32" XON_BUILDSYSTEM=1 FTEQCCFLAGS_WATERMARK= clean all
1503                                 ;;
1504                 esac
1505                 verbose rm -f Xonotic/source/*/fteqcc.log
1506                 ;;
1507         release-buildpk3-transform-raw)
1508                 dir=$1
1509                 ;;
1510         release-buildpk3-transform-normal)
1511                 dir=$1
1512                 verbose cd "$dir"
1513                 # texture: convert to jpeg and dds
1514                 verbose export do_jpeg=true
1515                 verbose export jpeg_qual_rgb=95
1516                 verbose export jpeg_qual_a=99
1517                 verbose export do_dds=true
1518                 verbose export dds_flags=
1519                 verbose export do_ogg=false
1520                 verbose export del_src=true
1521                 find . -type f -print0 | verbose xargs -0 "$d0"/misc/tools/cached-converter.sh
1522                 ;;
1523         release-buildpk3-transform-low)
1524                 dir=$1
1525                 verbose cd "$dir"
1526                 # texture: convert to jpeg and dds
1527                 # music: reduce bitrate
1528                 verbose export do_jpeg=true
1529                 verbose export jpeg_qual_rgb=80
1530                 verbose export jpeg_qual_a=99
1531                 verbose export do_dds=false
1532                 verbose export do_ogg=true
1533                 verbose export ogg_qual=1
1534                 verbose export del_src=true
1535                 find . -type f -print0 | verbose xargs -0 "$d0"/misc/tools/cached-converter.sh
1536                 ;;
1537         release-buildpk3-transform-lowdds)
1538                 dir=$1
1539                 verbose cd "$dir"
1540                 # texture: convert to jpeg and dds
1541                 # music: reduce bitrate
1542                 verbose export do_jpeg=false
1543                 verbose export do_jpeg_if_not_dds=true
1544                 verbose export jpeg_qual_rgb=80
1545                 verbose export jpeg_qual_a=99
1546                 verbose export do_dds=true
1547                 verbose export dds_flags=
1548                 verbose export do_ogg=true
1549                 verbose export ogg_qual=1
1550                 verbose export del_src=true
1551                 find . -type f -print0 | verbose xargs -0 "$d0"/misc/tools/cached-converter.sh
1552                 ;;
1553         release-buildpk3)
1554                 src=$1
1555                 dst=$2
1556                 transform=$3
1557                 case "$dst" in
1558                         /*)
1559                                 ;;
1560                         */)
1561                                 dst="$PWD/$dst"
1562                                 ;;
1563                 esac
1564                 verbose rm -rf Xonotic/temp
1565                 verbose mkdir -p Xonotic/temp
1566                 {
1567                         verbose cd "$src"
1568                         verbose git archive --format=tar HEAD
1569                 } | {
1570                         verbose cd Xonotic/temp
1571                         verbose tar xvf -
1572                 }
1573                 verbose cd Xonotic/temp
1574                 if [ x"$src" = x"data/xonotic-data.pk3dir" ]; then
1575                         verbose cp ../source/progs.dat .
1576                         verbose cp ../source/csprogs.dat .
1577                         verbose cp ../source/menu.dat .
1578                         verbose rm -rf qcsrc
1579                         gv=`grep "^gameversion " "defaultXonotic.cfg" | awk '{ print $2 }'`
1580                         major=$(($gv / 10000))
1581                         minor=$(($gv / 100 - $major * 100))
1582                         patch=$(($gv - $major * 10000 - $minor * 100))
1583                         versionstr="$major.$minor.$patch"
1584                         case "$RELEASETYPE" in
1585                                 beta)
1586                                         versionstr="$versionstr""beta"
1587                                         ;;
1588                         esac
1589                         verbose sed -i "
1590                                 s/^set g_xonoticversion [^ ]* /set g_xonoticversion $versionstr /;
1591                                 s/^gameversion_min [0-9]*/gameversion_min $(( ($gv / 100) * 100 - 100 ))/;
1592                                 s/^gameversion_max [0-9]*/gameversion_max $(( ($gv / 100) * 100 + 199 ))/;
1593                         " defaultXonotic.cfg
1594                         (
1595                                 verbose cd gfx/menu/luminos
1596                                 verbose cp "$d0"/mediasource/gfx/menu/luminos_versionbuilder/background_l2.svg .
1597                                 verbose "$d0"/mediasource/gfx/menu/luminos_versionbuilder/versionbuilder "$versionstr"
1598                                 verbose rm background_l2.svg
1599                         )
1600                 fi
1601                 if [ x"$src" = x"data/xonotic-maps.pk3dir" ]; then
1602                         for X in ../../data/*-????????????????????????????????????????-????????????????????????????????????????.pk3; do
1603                                 if [ -f "$X" ]; then
1604                                         verbose unzip "$X"
1605                                         verbose rm -f maps/*.log maps/*.irc maps/*.lin
1606                                 fi
1607                         done
1608                 fi
1609                 verbose export git_src_repo="$d0/$src" # skip hash-object
1610                 verbose "$SELF" release-buildpk3-transform-$transform "Xonotic/temp"
1611                 verbose mkzip "../../$dst" *
1612                 verbose cd ../..
1613                 verbose rm -rf Xonotic/temp
1614                 ;;
1615         release-buildpk3s)
1616                 stamp=`cat Xonotic/stamp.txt`
1617                 src=$1
1618                 shift
1619                 dst=${src%.pk3dir}
1620                 case "$dst" in
1621                         data/xonotic-*)
1622                                 dst="data/xonotic-$stamp-${dst#data/xonotic-}"
1623                                 ;;
1624                         *)
1625                                 dst="$dst-$stamp"
1626                                 ;;
1627                 esac
1628                 while [ "$#" -gt 1 ]; do
1629                         verbose "$SELF" release-buildpk3 "$src" "Xonotic/$dst$2.pk3" "$1"
1630                         shift
1631                         shift
1632                 done
1633                 ;;
1634         release-pack)
1635                 verbose "$SELF" release-buildpk3s data/font-nimbussansl.pk3dir             raw ''
1636                 verbose "$SELF" release-buildpk3s data/xonotic-data.pk3dir       normal ''            low '-low' lowdds '-lowdds'
1637                 verbose "$SELF" release-buildpk3s data/xonotic-maps.pk3dir       normal ''            low '-low' lowdds '-lowdds'
1638                 verbose "$SELF" release-buildpk3s data/xonotic-music.pk3dir                raw ''     low '-low'
1639                 verbose "$SELF" release-buildpk3s data/xonotic-nexcompat.pk3dir                       low ''
1640                 ;;
1641         release-pack-needsx11)
1642                 case "$DISPLAY" in
1643                         '')
1644                                 verbose startx "$SELF" release-pack -- /usr/bin/Xvfb :7
1645                                 ;;
1646                         *)
1647                                 verbose "$SELF" release-pack
1648                                 ;;
1649                 esac
1650                 ;;
1651         release-zip)
1652                 stamp=`cat Xonotic/stamp.txt`
1653                 # exe and dll files do not need +x, so this makes them eligible for 7zip compression too
1654                 chmod a-x Xonotic/*.exe Xonotic/*.dll || true
1655                 # let's pass crypto import laws of some nasty countries
1656                 crypto_libs=`find Xonotic -name \*d0_rijndael\*`
1657                 if [ -n "$crypto_libs" ]; then
1658                         verbose mkzip Xonotic-$stamp-crypto.zip \
1659                                 $crypto_libs
1660                         rm -f $crypto_libs
1661                 fi
1662                 # build the archives
1663                 verbose mkzip Xonotic-$stamp-engine.zip \
1664                         Xonotic/*.dll \
1665                         Xonotic/bin64/*.dll \
1666                         Xonotic/*.app \
1667                         Xonotic/xonotic-* \
1668                         Xonotic/xonotic.exe \
1669                         Xonotic/source/darkplaces/
1670                 verbose cp Xonotic-$stamp-engine.zip Xonotic-$stamp-common.zip
1671                 verbose mkzip Xonotic-$stamp-common.zip \
1672                         Xonotic/source/fteqcc/ \
1673                         Xonotic/source/qcsrc/ \
1674                         Xonotic/Docs \
1675                         Xonotic/misc \
1676                         Xonotic/fteqcc \
1677                         Xonotic/server \
1678                         Xonotic/key_0.d0pk \
1679                         Xonotic/data/font-nimbussansl-$stamp.pk3
1680                 verbose cp Xonotic-$stamp-common.zip Xonotic-$stamp.zip
1681                 verbose mkzip0 Xonotic-$stamp.zip \
1682                         Xonotic/data/xonotic-$stamp-data.pk3 \
1683                         Xonotic/data/xonotic-$stamp-maps.pk3 \
1684                         Xonotic/data/xonotic-$stamp-music.pk3 \
1685                         Xonotic/data/xonotic-$stamp-nexcompat.pk3
1686                 verbose cp Xonotic-$stamp-common.zip Xonotic-$stamp-low.zip
1687                 verbose mkzip0 Xonotic-$stamp-low.zip \
1688                         Xonotic/data/xonotic-$stamp-data-low.pk3 \
1689                         Xonotic/data/xonotic-$stamp-maps-low.pk3 \
1690                         Xonotic/data/xonotic-$stamp-music-low.pk3
1691 #               verbose cp Xonotic-$stamp-common.zip Xonotic-$stamp-high.zip
1692 #               verbose mkzip0 Xonotic-$stamp-high.zip \
1693 #                       Xonotic/data/xonotic-$stamp-data-raw.pk3 \
1694 #                       Xonotic/data/xonotic-$stamp-maps-raw.pk3 \
1695 #                       Xonotic/data/xonotic-$stamp-music.pk3 \
1696 #                       Xonotic/data/xonotic-$stamp-nexcompat.pk3
1697                 verbose mv Xonotic-$stamp-common.zip Xonotic-$stamp-lowdds.zip
1698                 verbose mkzip0 Xonotic-$stamp-lowdds.zip \
1699                         Xonotic/data/xonotic-$stamp-data-lowdds.pk3 \
1700                         Xonotic/data/xonotic-$stamp-maps-lowdds.pk3 \
1701                         Xonotic/data/xonotic-$stamp-music-low.pk3
1702                 ;;
1703         release)
1704                 verbose "$SELF" release-prepare
1705                 verbose "$SELF" release-maps
1706                 verbose "$SELF" release-engine
1707                 verbose "$SELF" release-qc
1708                 verbose "$SELF" release-pack-needsx11
1709                 verbose "$SELF" release-zip
1710                 ;;
1711
1712         *)
1713                 echo "Usage:"
1714                 echo "  $SELF admin-merge [<branch>]"
1715                 echo "  $SELF branch <branch>"
1716                 echo "  $SELF branch <remote> <branch> [<srcbranch>]"
1717                 echo "  $SELF branches"
1718                 echo "  $SELF checkout|switch <branch>"
1719                 echo "  $SELF checkout|switch <remote>/<branch>"
1720                 echo "  $SELF clean [-m] [-f | -fu | -fU] [-r] [-D]"
1721                 echo "  $SELF clean --reclone"
1722                 echo "  $SELF compile [-c] [-r] [-0]"
1723                 echo "  $SELF each|foreach [-k] command..."
1724                 echo "  $SELF fix_upstream_rebase"
1725                 echo "  $SELF keygen"
1726                 echo "  $SELF merge"
1727                 echo "  $SELF push|commit [-s]"
1728                 echo "  $SELF release"
1729                 echo "  $SELF restore-patches"
1730                 echo "  $SELF run [sdl|glx|wgl|agl|dedicated] options..."
1731                 echo "  $SELF save-patches"
1732                 echo "  $SELF update-maps"
1733                 echo "  $SELF update|pull [-N] [-s | -h [-p] | -g [-p]] [-l de|nl|default]"
1734                 ;;
1735 esac