6166c77cf1d9461bce81868b9eebdf94b89f252b
[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 [ -z "$MAKEFLAGS" ]; then
356                         if [ -f /proc/cpuinfo ]; then
357                                 ncpus=$((`grep -c '^processor   :' /proc/cpuinfo`+0))
358                                 if [ $ncpus -gt 1 ]; then
359                                         MAKEFLAGS=-j$ncpus
360                                 fi
361                         fi
362                 fi
363                 enter "$d0/fteqcc" verbose
364                 verbose make $MAKEFLAGS
365                 enter "$d0/data/xonotic-data.pk3dir" verbose
366                 verbose make FTEQCC="$d0/fteqcc/fteqcc.bin" $MAKEFLAGS
367                 enter "$d0/darkplaces" verbose
368                 verbose make $MAKEFLAGS sv-debug
369                 verbose make $MAKEFLAGS cl-debug
370                 if ! [ -n "$WE_HATE_OUR_USERS" ]; then
371                         verbose make $MAKEFLAGS sdl-debug
372                 fi
373                 ;;
374         run)
375                 if [ -n "$WE_HATE_OUR_USERS" ]; then
376                         client=
377                 else
378                         client=-sdl
379                 fi
380                 case "$1" in
381                         sdl|glx|agl|dedicated)
382                                 client=-$1
383                                 shift
384                                 ;;
385                         wgl)
386                                 client=
387                                 shift
388                                 ;;
389                 esac
390                 if ! [ -x "darkplaces/darkplaces$client" ]; then
391                         if [ -x "darkplaces/darkplaces$client.exe" ]; then
392                                 client=$client.exe
393                         else
394                                 echo "Client darkplaces/darkplaces$client not found, aborting"
395                                 exit 1
396                         fi
397                 fi
398                 #verbose "darkplaces/darkplaces$client" -xonotic "$@"
399                 verbose "darkplaces/darkplaces$client" -nexuiz -customgamename Xonotic -customgamedirname1 data -customgamedirname2 "" -customgamescreenshotname xonotic -customgameuserdirname xonotic "$@"
400                 ;;
401         each|foreach)
402                 for d in $repos; do
403                         enter "$d0/$d" verbose
404                         verbose "$@"
405                         cd "$d0"
406                 done
407                 ;;
408         save-patches)
409                 outfile=$1
410                 patchdir=`mktemp -d -t save-patches.XXXXXX`
411                 for d in $repos; do
412                         enter "$d0/$d" verbose
413                         git branch -v -v | cut -c 3- | {
414                                 i=0
415                                 while read -r BRANCH REV UPSTREAM TEXT; do
416                                         case "$UPSTREAM" in
417                                                 \[*)
418                                                         UPSTREAM=${UPSTREAM#\[}
419                                                         UPSTREAM=${UPSTREAM%\]}
420                                                         UPSTREAM=${UPSTREAM%:*}
421                                                         TRACK=true
422                                                         ;;
423                                                 *)
424                                                         UPSTREAM=origin/master
425                                                         TRACK=false
426                                                         ;;
427                                         esac
428                                         if [ x"$REV" = x"->" ]; then
429                                                 continue
430                                         fi
431                                         if git format-patch -o "$patchdir/$i" "$UPSTREAM".."$BRANCH"; then
432                                                 echo "$d" > "$patchdir/$i/info.txt"
433                                                 echo "$BRANCH" >> "$patchdir/$i/info.txt"
434                                                 echo "$UPSTREAM" >> "$patchdir/$i/info.txt"
435                                                 echo "$TRACK" >> "$patchdir/$i/info.txt"
436                                                 i=$(($i+1))
437                                         else
438                                                 rm -rf "$patchdir/$i"
439                                         fi
440                                 done
441                         }
442                 done
443                 ( cd "$patchdir" && tar cvzf - . ) > "$outfile"
444                 rm -rf "$patchdir"
445                 ;;
446         restore-patches)
447                 infile=$1
448                 patchdir=`mktemp -d -t restore-patches.XXXXXX`
449                 ( cd "$patchdir" && tar xvzf - ) < "$infile"
450                 # detach the head
451                 for P in "$patchdir"/*/info.txt; do
452                         D=${P%/info.txt}
453                         exec 3<"$P"
454                         read -r d <&3
455                         read -r BRANCH <&3
456                         read -r UPSTREAM <&3
457                         read -r TRACK <&3
458                         verbose git checkout HEAD^0
459                         verbose git branch -D "$BRANCH"
460                         if [ x"$TRACK" = x"true" ]; then
461                                 verbose git checkout --track -b "$BRANCH" "$UPSTREAM"
462                         else
463                                 verbose git branch -b "$BRANCH" "$UPSTREAM"
464                         fi
465                         verbose git am "$D"
466                 done
467                 rm -rf "$patchdir"
468                 ;;
469         admin-merge)
470                 for d in $repos; do
471                         enter "$d0/$d" verbose
472                         git rev-parse "$1/$2" || continue
473                         # 1. review
474                         {
475                                 git log HEAD.."$1/$2"
476                                 git diff HEAD..."$1/$2"
477                         } | less
478                         a=
479                         while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
480                                 echo "Merge \"$1/$2\" into `git symbolic-ref HEAD` of $d?"
481                                 read -r a
482                         done
483                         if [ x"$a" = x"y" ]; then
484                                 git merge "$1/$2"
485                                 cd "$d0"
486                                 a=
487                                 if ! "$SELF" compile; then
488                                         a=n
489                                 fi
490                                 cd "$d0/$d"
491                                 while [ x"$a" != x"y" -a x"$a" != x"n" ]; do
492                                         echo "Still merge \"$1/$2\" into `git symbolic-ref HEAD` of $d? Maybe you want to test first."
493                                         read -r a
494                                 done
495                                 if [ x"$a" = x"y" ]; then
496                                         git push origin HEAD
497                                         git push "$1" :"$2"
498                                 else
499                                         git reset --hard HEAD@{1}
500                                 fi
501                         fi
502                 done
503                 ;;
504         *)
505                 echo "Usage:"
506                 echo "  $SELF pull"
507                 echo "  $SELF merge"
508                 echo "  $SELF push [-s]"
509                 echo "  $SELF branches"
510                 echo "  $SELF branch [<remote>] <branchname>"
511                 echo "  $SELF branch <remote> <branchname> <srcbranchname>"
512                 echo "  $SELF checkout [<remote>] <branchname>"
513                 echo "  $SELF compile"
514                 echo "  $SELF run <client> <options>"
515                 echo "  $SELF each <command>"
516                 ;;
517 esac