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