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