15a98b79b908adf03a2fdb14155ec56ce402215d
[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_urls=`
123         for X in $repos_urls; do 
124                 d="${X%%@*}"
125                 p="${d%dir}"
126                 if [ x"$p" = x"$d" ] || [ -d "$d" ] || ! [ -f "$p" ]; then
127                         echo "$X"
128                 fi
129         done
130 `
131
132 repos=`for X in $repos_urls; do echo "${X%%@*}"; done`
133
134 if [ "$#" = 0 ]; then
135         set -- help
136 fi
137 cmd=$1
138 shift
139
140 case "$cmd" in
141         update|pull)
142                 base=`git config remote.origin.url`
143                 base=${base%xonotic.git}
144                 for dcomplete in $repos_urls; do
145                         case "$dcomplete" in
146                                 *@*)
147                                         d=${dcomplete%%@*}
148                                         url=${dcomplete#*@}
149                                         switch=false
150                                         ;;
151                                 *)
152                                         d=${dcomplete%%@*}
153                                         url=$base${d##*/}.git
154                                         switch=true
155                                         ;;
156                         esac
157                         if [ -d "$d0/$d" ]; then
158                                 enter "$d0/$d" verbose
159                                 case "$d" in
160                                         .)
161                                                 ;;
162                                         *)
163                                                 if $switch; then
164                                                         verbose git config remote.origin.url "$url"
165                                                 fi
166                                                 ;;
167                                 esac
168                                 verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
169                                         # TODO remove this line later
170
171                                 verbose git config core.autocrlf false
172                                 verbose git config core.safecrlf false # we don't NEED that...
173
174                                 r=`git symbolic-ref HEAD`
175                                 r=${r#refs/heads/}
176                                 if git config branch.$r.remote >/dev/null 2>&1; then
177                                         if ! verbose git pull; then
178                                                 check_mergeconflict "$d"
179                                                 echo "Pulling failed. Press ENTER to continue, or Ctrl-C to abort."
180                                                 read -r DUMMY
181                                         fi
182                                 fi
183
184                                 cd "$d00"
185                                 checkself "$cmd" "$@"
186                                 cd "$d0/$d"
187                                 verbose git remote prune origin
188                                 cd "$d0"
189                         else
190                                 verbose git clone "$url" "$d0/$d"
191                         fi
192                 done
193                 ;;
194         checkout|switch)
195                 remote=$1
196                 branch=$2
197                 if [ -z "$branch" ]; then
198                         branch=$remote
199                         remote=origin
200                 fi
201                 exists=false
202                 for d in $repos; do
203                         enter "$d0/$d" verbose
204                         if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
205                                 exists=true
206                                 verbose git checkout "$branch"
207                         elif git rev-parse "refs/remotes/$remote/$branch" >/dev/null 2>&1; then
208                                 exists=true
209                                 verbose git checkout --track -b "$branch" "$remote/$branch"
210                         else
211                                 verbose git checkout master
212                         fi
213                         cd "$d00"
214                         checkself "$cmd" "$@"
215                         cd "$d0"
216                 done
217                 if ! $exists; then
218                         echo "The requested branch was not found in any repository."
219                 fi
220                 exec "$SELF" branch
221                 ;;
222         branch)
223                 remote=$1
224                 branch=$2
225                 srcbranch=$3
226                 if [ -z "$branch" ]; then
227                         branch=$remote
228                         remote=origin
229                 fi
230                 if [ -z "$srcbranch" ]; then
231                         srcbranch=master
232                 fi
233                 if [ -z "$branch" ]; then
234                         for d in $repos; do
235                                 enter "$d0/$d"
236                                 r=`git symbolic-ref HEAD`
237                                 r=${r#refs/heads/}
238                                 echo "$d is at $r"
239                                 cd "$d0"
240                         done
241                 else
242                         for d in $repos; do
243                                 dv=`visible_repo_name "$d"`
244                                 enter "$d0/$d" verbose
245                                 a=
246                                 if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
247                                         echo "Already having this branch in $dv."
248                                 else
249                                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
250                                                 echo "Branch in $dv?"
251                                                 read -r a
252                                         done
253                                         if [ x"$a" = x"y" ]; then
254                                                 verbose git push "$remote" "$srcbranch":"$branch"
255                                                 verbose git checkout --track -b "$branch" "$remote/$branch"
256                                         fi
257                                 fi
258                                 cd "$d0"
259                         done
260                         "$SELF" branch
261                 fi
262                 ;;
263         branches)
264                 for d in $repos; do
265                         enter "$d0/$d"
266                         echo "In $d:"
267                         git branch -a -v -v | cut -c 3- | while read -r BRANCH REV UPSTREAM TEXT; do
268                                 case "$UPSTREAM" in
269                                         \[*)
270                                                 UPSTREAM=${UPSTREAM#\[}
271                                                 UPSTREAM=${UPSTREAM%\]}
272                                                 UPSTREAM=${UPSTREAM%:*}
273                                                 ;;
274                                         *)
275                                                 TEXT="$UPSTREAM $TEXT"
276                                                 UPSTREAM=
277                                                 ;;
278                                 esac
279                                 if [ x"$REV" = x"->" ]; then
280                                         continue
281                                 fi
282                                 BRANCH=${BRANCH#remotes/}
283                                 echo -n "  $BRANCH"
284                                 if [ -n "$UPSTREAM" ]; then
285                                         echo -n " (tracking $UPSTREAM)"
286                                 fi
287                                 #echo " $TEXT"
288                                 echo
289                         done
290                 done
291                 ;;
292         merge)
293                 for d in $repos; do
294                         dv=`visible_repo_name "$d"`
295                         enter "$d0/$d" verbose
296                         r=`git symbolic-ref HEAD`
297                         r=${r#refs/heads/}
298                         if git log HEAD..origin/master | grep .; then
299                                 # we have uncommitted changes
300                                 a=
301                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
302                                         echo "Could merge from \"master\" into \"$r\" in $dv. Do it?"
303                                         read -r a
304                                 done
305                                 if [ x"$a" = x"y" ]; then
306                                         if ! verbose git merge origin/master; then
307                                                 check_mergeconflict "$d"
308                                                 exit 1 # this should ALWAYS be fatal
309                                         fi
310                                 fi
311                         fi
312                         cd "$d0"
313                 done
314                 ;;
315         push|commit)
316                 submit=$1
317                 for d in $repos; do
318                         dv=`visible_repo_name "$d"`
319                         enter "$d0/$d" verbose
320                         r=`git symbolic-ref HEAD`
321                         r=${r#refs/heads/}
322                         if git diff HEAD | grep .; then
323                                 # we have uncommitted changes
324                                 a=
325                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
326                                         echo "Uncommitted changes in \"$r\" in $dv. Commit?"
327                                         read -r a
328                                 done
329                                 if [ x"$a" = x"y" ]; then
330                                         verbose git commit -a
331                                 fi
332                         fi
333                         rem=`git config "branch.$r.remote" || echo origin`
334                         if git log "$rem/$r".."$r" | grep .; then
335                                 a=
336                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
337                                         echo "Push \"$r\" in $dv?"
338                                         read -r a
339                                 done
340                                 if [ x"$a" = x"y" ]; then
341                                         verbose git push "$rem" HEAD
342                                 fi
343                         fi
344                         if [ x"$submit" = x"-s" ]; then
345                                 case "$r" in
346                                         */*)
347                                                 verbose git push "$rem" HEAD:"${r%%/*}/finished/${r#*/}"
348                                                 ;;
349                                 esac
350                         fi
351                         cd "$d0"
352                 done
353                 ;;
354         compile)
355                 if [ -n "$WE_HATE_OUR_USERS" ]; then
356                         TARGETS="sv-debug cl-debug"
357                 else
358                         TARGETS="sv-debug cl-debug sdl-debug"
359                 fi
360                 case "$1" in
361                         sdl)
362                                 TARGETS="sdl-debug"
363                                 shift
364                                 ;;
365                         glx|agl|wgl)
366                                 TARGETS="cl-debug"
367                                 shift
368                                 ;;
369                         dedicated)
370                                 TARGETS="sv-debug"
371                                 shift
372                                 ;;
373                 esac
374                 if [ -z "$MAKEFLAGS" ]; then
375                         if [ -f /proc/cpuinfo ]; then
376                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
377                                 if [ $ncpus -gt 1 ]; then
378                                         MAKEFLAGS=-j$ncpus
379                                 fi
380                         fi
381                 fi
382                 enter "$d0/fteqcc" verbose
383                 verbose make $MAKEFLAGS
384                 enter "$d0/data/xonotic-data.pk3dir" verbose
385                 verbose make FTEQCC="$d0/fteqcc/fteqcc.bin" $MAKEFLAGS
386                 enter "$d0/darkplaces" verbose
387                 for T in $TARGETS; do
388                         verbose make $MAKEFLAGS "$T"
389                 done
390                 ;;
391         run)
392                 if [ -n "$WE_HATE_OUR_USERS" ]; then
393                         client=
394                 else
395                         client=-sdl
396                 fi
397                 case "$1" in
398                         sdl|glx|agl|dedicated)
399                                 client=-$1
400                                 shift
401                                 ;;
402                         wgl)
403                                 client=
404                                 shift
405                                 ;;
406                 esac
407                 if ! [ -x "darkplaces/darkplaces$client" ]; then
408                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
409                                 client=$client.exe
410                         else
411                                 echo "Client darkplaces/darkplaces$client not found, aborting"
412                                 exit 1
413                         fi
414                 fi
415                 #verbose "darkplaces/darkplaces$client" -xonotic "$@"
416                 verbose "darkplaces/darkplaces$client" -nexuiz -customgamename Xonotic -customgamedirname1 data -customgamedirname2 "" -customgamescreenshotname xonotic -customgameuserdirname xonotic "$@"
417                 ;;
418         each|foreach)
419                 for d in $repos; do
420                         enter "$d0/$d" verbose
421                         verbose "$@"
422                         cd "$d0"
423                 done
424                 ;;
425         save-patches)
426                 outfile=$1
427                 patchdir=`mktemp -d -t save-patches.XXXXXX`
428                 for d in $repos; do
429                         enter "$d0/$d" verbose
430                         git branch -v -v | cut -c 3- | {
431                                 i=0
432                                 while read -r BRANCH REV UPSTREAM TEXT; do
433                                         case "$UPSTREAM" in
434                                                 \[*)
435                                                         UPSTREAM=${UPSTREAM#\[}
436                                                         UPSTREAM=${UPSTREAM%\]}
437                                                         UPSTREAM=${UPSTREAM%:*}
438                                                         TRACK=true
439                                                         ;;
440                                                 *)
441                                                         UPSTREAM=origin/master
442                                                         TRACK=false
443                                                         ;;
444                                         esac
445                                         if [ x"$REV" = x"->" ]; then
446                                                 continue
447                                         fi
448                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
449                                                 echo "$d" > "$patchdir/$i/info.txt"
450                                                 echo "$BRANCH" >> "$patchdir/$i/info.txt"
451                                                 echo "$UPSTREAM" >> "$patchdir/$i/info.txt"
452                                                 echo "$TRACK" >> "$patchdir/$i/info.txt"
453                                                 i=$(($i+1))
454                                         else
455                                                 rm -rf "$patchdir/$i"
456                                         fi
457                                 done
458                         }
459                 done
460                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
461                 rm -rf "$patchdir"
462                 ;;
463         restore-patches)
464                 infile=$1
465                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
466                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
467                 # detach the head
468                 for P in "$patchdir"/*/info.txt; do
469                         D=${P%/info.txt}
470                         exec 3<"$P"
471                         read -r d <&3
472                         read -r BRANCH <&3
473                         read -r UPSTREAM <&3
474                         read -r TRACK <&3
475                         verbose git checkout HEAD^0
476                         verbose git branch -D "$BRANCH"
477                         if [ x"$TRACK" = x"true" ]; then
478                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
479                         else
480                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
481                         fi
482                         verbose git am "$D"
483                 done
484                 rm -rf "$patchdir"
485                 ;;
486         admin-merge)
487                 for d in $repos; do
488                         enter "$d0/$d" verbose
489                         git rev-parse "$1/$2" || continue
490                         # 1. review
491                         {
492                                 git log HEAD.."$1/$2"
493                                 git diff HEAD..."$1/$2"
494                         } | less
495                         a=
496                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
497                                 echo "Merge \"$1/$2\" into `git symbolic-ref HEAD` of $d?"
498                                 read -r a
499                         done
500                         if [ x"$a" = x"y" ]; then
501                                 git merge "$1/$2"
502                                 cd "$d0"
503                                 a=
504                                 if ! "$SELF" compile; then
505                                         a=n
506                                 fi
507                                 cd "$d0/$d"
508                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
509                                         echo "Still merge \"$1/$2\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."
510                                         read -r a
511                                 done
512                                 if [ x"$a" = x"y" ]; then
513                                         git push origin HEAD
514                                         git push "$1" :"$2"
515                                 else
516                                         git reset --hard HEAD@{1}
517                                 fi
518                         fi
519                 done
520                 ;;
521         *)
522                 echo "Usage:"
523                 echo "  $SELF pull"
524                 echo "  $SELF merge"
525                 echo "  $SELF push [-s]"
526                 echo "  $SELF branches"
527                 echo "  $SELF branch [<remote>] <branchname>"
528                 echo "  $SELF branch <remote> <branchname> <srcbranchname>"
529                 echo "  $SELF checkout [<remote>] <branchname>"
530                 echo "  $SELF compile"
531                 echo "  $SELF run <client> <options>"
532                 echo "  $SELF each <command>"
533                 ;;
534 esac