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