9a0a6d0ca0041aafda51f3dc693d65dd34a57737
[xonotic/xonotic.git] / all
1 #!/bin/sh
2 # vim: filetype=zsh
3
4 set -e
5
6 d00=`pwd`
7 while ! [ -f ./all ]; do
8         if [ x"`pwd`" = x"/" ]; then
9                 echo "Cannot find myself."
10                 echo "Please run this script with the working directory inside a Xonotic checkout."
11                 exit 1
12         fi
13         cd ..
14 done
15 d0=`pwd`
16 SELF="$d0/all"
17
18 # If we are on WINDOWS:
19 case "$0" in
20         all|*/all)
21                 case "`uname`" in
22                         MINGW*|Win*)
23                                 # Windows hates users. So this script has to copy itself elsewhere first...
24                                 tname=
25                                 cp "$SELF" ../all.xonotic.sh
26                                 export WE_HATE_OUR_USERS=1
27                                 exec ../all.xonotic.sh "$@"
28                                 ;;
29                 esac
30                 ;;
31 esac
32
33 msg()
34 {
35         echo "\e[1m$*\e[m"
36 }
37
38 checksum()
39 {
40         if [ -x /usr/bin/md5sum ]; then
41                 /usr/bin/md5sum "$@"
42         elif [ -x /bin/md5sum ]; then
43                 /bin/md5sum "$@"
44         elif [ -x /usr/bin/cksum ]; then
45                 /usr/bin/cksum "$@"
46         else
47                 echo "NOCHECKSUM"
48         fi
49 }
50
51 self=`checksum "$SELF"`
52 checkself()
53 {
54         self_new=`checksum "$SELF"`
55         if [ x"$self" != x"$self_new" ]; then
56                 msg "./all has changed."
57                 if [ -z "$XONOTIC_FORBID_RERUN_ALL" ]; then
58                         msg "Rerunning the requested operation to make sure."
59                         export XONOTIC_FORBID_RERUN_ALL=1
60                         exec "$SELF" "$@"
61                 else
62                         msg "Please try $SELF update, and then retry your requested operation."
63                         exit 1
64                 fi
65         fi
66         return 0
67 }
68
69 verbose()
70 {
71         msg "+ $*"
72         "$@"
73 }
74
75 visible_repo_name()
76 {
77         case "$1" in
78                 .)
79                         echo "the root directory"
80                         ;;
81                 *)
82                         echo "\"$1\""
83                         ;;
84         esac
85 }
86
87 check_mergeconflict()
88 {
89         if git ls-files -u | grep ' 1   '; then
90                 echo
91                 echo "MERGE CONFLICT."
92                 echo "change into the \"$1\" project directory, and then:"
93                 echo "- edit the files mentioned above with your favorite editor,"
94                 echo "  and fix the conflicts (marked with <<<<<<< blocks)"
95                 echo "- for binary files, you can select the files using"
96                 echo "  git checkout --ours or git checkout --theirs"
97                 echo "- when done with a file, 'git add' the file"
98                 echo "- when done, 'git commit'"
99                 echo
100                 exit 1
101         fi
102 }
103
104 enter()
105 {
106         $2 cd "$1"
107         check_mergeconflict "$1"
108 }
109
110 repos_urls="
111         .
112         data/xonotic-data.pk3dir
113         data/xonotic-maps.pk3dir
114         data/xonotic-music.pk3dir
115         data/xonotic-nexcompat.pk3dir
116         darkplaces
117         fteqcc@git://github.com/Blub/qclib.git
118         div0-gittools@git://git.icculus.org/divverent/div0-gittools.git
119         netradiant
120 "
121
122 repos=`for X in $repos_urls; do echo "${X%%@*}"; done`
123
124 if [ "$#" = 0 ]; then
125         set -- help
126 fi
127 cmd=$1
128 shift
129
130 case "$cmd" in
131         update|pull)
132                 base=`git config remote.origin.url`
133                 base=${base%xonotic.git}
134                 for dcomplete in $repos_urls; do
135                         case "$dcomplete" in
136                                 *@*)
137                                         d=${dcomplete%%@*}
138                                         url=${dcomplete#*@}
139                                         switch=false
140                                         ;;
141                                 *)
142                                         d=${dcomplete%%@*}
143                                         url=$base${d##*/}.git
144                                         switch=true
145                                         ;;
146                         esac
147                         if [ -d "$d0/$d" ]; then
148                                 enter "$d0/$d" verbose
149                                 case "$d" in
150                                         .)
151                                                 ;;
152                                         *)
153                                                 if $switch; then
154                                                         verbose git config remote.origin.url "$url"
155                                                 fi
156                                                 ;;
157                                 esac
158                                 verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
159                                         # TODO remove this line later
160
161                                 verbose git config core.autocrlf false
162                                 verbose git config core.safecrlf false # we don't NEED that...
163
164                                 r=`git symbolic-ref HEAD`
165                                 r=${r#refs/heads/}
166                                 if git config branch.$r.remote >/dev/null 2>&1; then
167                                         if ! verbose git pull; then
168                                                 check_mergeconflict "$d"
169                                                 exit 1 # FATAL
170                                         fi
171                                 fi
172
173                                 cd "$d00"
174                                 checkself "$cmd" "$@"
175                                 cd "$d0/$d"
176                                 verbose git remote prune origin
177                                 cd "$d0"
178                         else
179                                 verbose git clone "$url" "$d0/$d"
180                         fi
181                 done
182                 ;;
183         checkout|switch)
184                 remote=$1
185                 branch=$2
186                 if [ -z "$branch" ]; then
187                         branch=$remote
188                         remote=origin
189                 fi
190                 exists=false
191                 for d in $repos; do
192                         enter "$d0/$d" verbose
193                         if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
194                                 exists=true
195                                 verbose git checkout "$branch"
196                         elif git rev-parse "refs/remotes/$remote/$branch" >/dev/null 2>&1; then
197                                 exists=true
198                                 verbose git checkout --track -b "$branch" "$remote/$branch"
199                         else
200                                 verbose git checkout master
201                         fi
202                         cd "$d00"
203                         checkself "$cmd" "$@"
204                         cd "$d0"
205                 done
206                 if ! $exists; then
207                         echo "The requested branch was not found in any repository."
208                 fi
209                 exec "$SELF" branch
210                 ;;
211         branch)
212                 remote=$1
213                 branch=$2
214                 srcbranch=$3
215                 if [ -z "$branch" ]; then
216                         branch=$remote
217                         remote=origin
218                 fi
219                 if [ -z "$srcbranch" ]; then
220                         srcbranch=master
221                 fi
222                 if [ -z "$branch" ]; then
223                         for d in $repos; do
224                                 enter "$d0/$d"
225                                 r=`git symbolic-ref HEAD`
226                                 r=${r#refs/heads/}
227                                 echo "$d is at $r"
228                                 cd "$d0"
229                         done
230                 else
231                         for d in $repos; do
232                                 dv=`visible_repo_name "$d"`
233                                 enter "$d0/$d" verbose
234                                 a=
235                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
236                                         echo "Branch in $dv?"
237                                         read -r a
238                                 done
239                                 if [ x"$a" = x"y" ]; then
240                                         verbose git push "$remote" "$srcbranch":"$branch"
241                                         verbose git checkout --track -b "$branch" "$remote/$branch"
242                                 fi
243                                 cd "$d0"
244                         done
245                         "$SELF" branch
246                 fi
247                 ;;
248         branches)
249                 for d in $repos; do
250                         enter "$d0/$d"
251                         echo "In $d:"
252                         git branch -a -v -v | cut -c 3- | while read -r BRANCH REV UPSTREAM TEXT; do
253                                 case "$UPSTREAM" in
254                                         \[*)
255                                                 UPSTREAM=${UPSTREAM#\[}
256                                                 UPSTREAM=${UPSTREAM%\]}
257                                                 UPSTREAM=${UPSTREAM%:*}
258                                                 ;;
259                                         *)
260                                                 TEXT="$UPSTREAM $TEXT"
261                                                 UPSTREAM=
262                                                 ;;
263                                 esac
264                                 if [ x"$REV" = x"->" ]; then
265                                         continue
266                                 fi
267                                 BRANCH=${BRANCH#remotes/}
268                                 echo -n "  $BRANCH"
269                                 if [ -n "$UPSTREAM" ]; then
270                                         echo -n " (tracking $UPSTREAM)"
271                                 fi
272                                 #echo " $TEXT"
273                                 echo
274                         done
275                 done
276                 ;;
277         merge)
278                 for d in $repos; do
279                         dv=`visible_repo_name "$d"`
280                         enter "$d0/$d" verbose
281                         r=`git symbolic-ref HEAD`
282                         r=${r#refs/heads/}
283                         if git log HEAD..origin/master | grep .; then
284                                 # we have uncommitted changes
285                                 a=
286                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
287                                         echo "Could merge from \"master\" into \"$r\" in $dv. Do it?"
288                                         read -r a
289                                 done
290                                 if [ x"$a" = x"y" ]; then
291                                         if ! verbose git merge origin/master; then
292                                                 check_mergeconflict "$d"
293                                                 exit 1 # this should ALWAYS be fatal
294                                         fi
295                                 fi
296                         fi
297                         cd "$d0"
298                 done
299                 ;;
300         push|commit)
301                 submit=$1
302                 for d in $repos; do
303                         dv=`visible_repo_name "$d"`
304                         enter "$d0/$d" verbose
305                         r=`git symbolic-ref HEAD`
306                         r=${r#refs/heads/}
307                         if git diff HEAD | grep .; then
308                                 # we have uncommitted changes
309                                 a=
310                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
311                                         echo "Uncommitted changes in \"$r\" in $dv. Commit?"
312                                         read -r a
313                                 done
314                                 if [ x"$a" = x"y" ]; then
315                                         verbose git commit -a
316                                 fi
317                         fi
318                         rem=`git config "branch.$r.remote" || echo origin`
319                         if git log "$rem/$r".."$r" | grep .; then
320                                 a=
321                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
322                                         echo "Push \"$r\" in $dv?"
323                                         read -r a
324                                 done
325                                 if [ x"$a" = x"y" ]; then
326                                         verbose git push "$rem" HEAD
327                                 fi
328                         fi
329                         if [ x"$submit" = x"-s" ]; then
330                                 case "$r" in
331                                         */*)
332                                                 verbose git push "$rem" HEAD:"${r%%/*}/finished/${r#*/}"
333                                                 ;;
334                                 esac
335                         fi
336                         cd "$d0"
337                 done
338                 ;;
339         compile)
340                 if [ -z "$MAKEFLAGS" ]; then
341                         if [ -f /proc/cpuinfo ]; then
342                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
343                                 if [ $ncpus -gt 1 ]; then
344                                         MAKEFLAGS=-j$ncpus
345                                 fi
346                         fi
347                 fi
348                 enter "$d0/fteqcc" verbose
349                 verbose make $MAKEFLAGS
350                 enter "$d0/data/xonotic-data.pk3dir" verbose
351                 verbose make FTEQCC="$d0/fteqcc/fteqcc.bin" $MAKEFLAGS
352                 enter "$d0/darkplaces" verbose
353                 verbose make $MAKEFLAGS sv-debug
354                 verbose make $MAKEFLAGS cl-debug
355                 if ! [ -n "$WE_HATE_OUR_USERS" ]; then
356                         verbose make $MAKEFLAGS sdl-debug
357                 fi
358                 ;;
359         run)
360                 if [ -n "$WE_HATE_OUR_USERS" ]; then
361                         client=
362                 else
363                         client=-sdl
364                 fi
365                 case "$1" in
366                         sdl|glx|agl|dedicated)
367                                 client=-$1
368                                 shift
369                                 ;;
370                         wgl)
371                                 client=
372                                 shift
373                                 ;;
374                 esac
375                 if ! [ -x "darkplaces/darkplaces$client" ]; then
376                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
377                                 client=$client.exe
378                         else
379                                 echo "Client darkplaces/darkplaces$client not found, aborting"
380                                 exit 1
381                         fi
382                 fi
383                 #verbose "darkplaces/darkplaces$client" -xonotic "$@"
384                 verbose "darkplaces/darkplaces$client" -nexuiz -customgamename Xonotic -customgamedirname1 data -customgamedirname2 "" -customgamescreenshotname xonotic -customgameuserdirname xonotic "$@"
385                 ;;
386         each|foreach)
387                 for d in $repos; do
388                         enter "$d0/$d" verbose
389                         verbose "$@"
390                         cd "$d0"
391                 done
392                 ;;
393         save-patches)
394                 outfile=$1
395                 patchdir=`mktemp -d -t save-patches.XXXXXX`
396                 for d in $repos; do
397                         enter "$d0/$d" verbose
398                         git branch -v -v | cut -c 3- | {
399                                 i=0
400                                 while read -r BRANCH REV UPSTREAM TEXT; do
401                                         case "$UPSTREAM" in
402                                                 \[*)
403                                                         UPSTREAM=${UPSTREAM#\[}
404                                                         UPSTREAM=${UPSTREAM%\]}
405                                                         UPSTREAM=${UPSTREAM%:*}
406                                                         TRACK=true
407                                                         ;;
408                                                 *)
409                                                         UPSTREAM=origin/master
410                                                         TRACK=false
411                                                         ;;
412                                         esac
413                                         if [ x"$REV" = x"->" ]; then
414                                                 continue
415                                         fi
416                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
417                                                 echo "$d" > "$patchdir/$i/info.txt"
418                                                 echo "$BRANCH" >> "$patchdir/$i/info.txt"
419                                                 echo "$UPSTREAM" >> "$patchdir/$i/info.txt"
420                                                 echo "$TRACK" >> "$patchdir/$i/info.txt"
421                                                 i=$(($i+1))
422                                         else
423                                                 rm -rf "$patchdir/$i"
424                                         fi
425                                 done
426                         }
427                 done
428                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
429                 rm -rf "$patchdir"
430                 ;;
431         restore-patches)
432                 infile=$1
433                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
434                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
435                 # detach the head
436                 for P in "$patchdir"/*/info.txt; do
437                         D=${P%/info.txt}
438                         exec 3<"$P"
439                         read -r d <&3
440                         read -r BRANCH <&3
441                         read -r UPSTREAM <&3
442                         read -r TRACK <&3
443                         verbose git checkout HEAD^0
444                         verbose git branch -D "$BRANCH"
445                         if [ x"$TRACK" = x"true" ]; then
446                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
447                         else
448                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
449                         fi
450                         verbose git am "$D"
451                 done
452                 rm -rf "$patchdir"
453                 ;;
454         admin-merge)
455                 for d in $repos; do
456                         enter "$d0/$d" verbose
457                         git rev-parse "$1/$2" || continue
458                         # 1. review
459                         {
460                                 git log HEAD.."$1/$2"
461                                 git diff HEAD..."$1/$2"
462                         } | less
463                         a=
464                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
465                                 echo "Merge \"$1/$2\" into `git symbolic-ref HEAD` of $d?"
466                                 read -r a
467                         done
468                         if [ x"$a" = x"y" ]; then
469                                 git merge "$1/$2"
470                                 cd "$d0"
471                                 a=
472                                 if ! "$SELF" compile; then
473                                         a=n
474                                 fi
475                                 cd "$d0/$d"
476                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
477                                         echo "Still merge \"$1/$2\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."
478                                         read -r a
479                                 done
480                                 if [ x"$a" = x"y" ]; then
481                                         git push origin HEAD
482                                         git push "$1" :"$2"
483                                 else
484                                         git reset --hard HEAD@{1}
485                                 fi
486                         fi
487                 done
488                 ;;
489         *)
490                 echo "Usage:"
491                 echo "  $SELF pull"
492                 echo "  $SELF merge"
493                 echo "  $SELF push [-s]"
494                 echo "  $SELF branches"
495                 echo "  $SELF branch [<remote>] <branchname>"
496                 echo "  $SELF branch <remote> <branchname> <srcbranchname>"
497                 echo "  $SELF checkout [<remote>] <branchname>"
498                 echo "  $SELF compile"
499                 echo "  $SELF run <client> <options>"
500                 echo "  $SELF each <command>"
501                 ;;
502 esac