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