1 check_mergeconflict() # overrides the one in ./all
3 if git ls-files -u | grep ' 1 '; then
5 $ECHO "MERGE CONFLICT."
6 $ECHO "change into the \"$1\" project directory, and then:"
7 $ECHO "- edit the files mentioned above with your favorite editor,"
8 $ECHO " and fix the conflicts (marked with <<<<<<< blocks)"
9 $ECHO "- for binary files, you can select the files using"
10 $ECHO " git checkout --ours or git checkout --theirs"
11 $ECHO "- when done with a file, 'git add' the file"
12 $ECHO "- when done, 'git commit'"
22 $ECHO "the root directory"
32 if [ -z "$r_me" ] || [ -z "$r_other" ]; then
36 # one of the two sides of the merge should be remote upstream, or all is fine
37 r_r=`git symbolic-ref HEAD`
38 r_r=${r_r#refs/heads/}
39 r_rem=`git config "branch.$r_rem.remote" || $ECHO origin`
40 r_bra=`git config "branch.$r_bra.merge" || $ECHO "$r_r"`
41 r_bra=${r_bra#refs/heads/}
42 if [ x"$r_me" != x"`git rev-parse "$r_rem/$r_bra"`" ]; then
43 if [ x"$r_other" != x"`git rev-parse "$r_rem/$r_bra"`" ]; then
48 r_base=`git merge-base "$r_me" "$r_other"`
50 # no merge-base? upstream did filter-branch
51 if [ -n "$r_base" ]; then
52 # otherwise, check if the two histories are "similar"
53 r_l_me=`git log --pretty="format:%s" "$r_other".."$r_me" | grep -v "^Merge" | sort -u`
54 r_l_other=`git log --pretty="format:%s" "$r_me".."$r_other" | grep -v "^Merge" | sort -u`
56 # heuristics: upstream rebase/filter-branch if more than 50% of the commits of one of the sides are in the other too
57 r_lc_me=`$ECHO "$r_l_me" | wc -l`
58 r_lc_other=`$ECHO "$r_l_other" | wc -l`
59 r_lc_together=`{ $ECHO "$r_l_me"; $ECHO "$r_l_other"; } | sort -u | wc -l`
60 r_lc_same=$(($r_lc_me + $r_lc_other - $r_lc_together))
62 if [ $(( $r_lc_same * 2 )) -gt $(( $r_lc_me )) ] || [ $(( $r_lc_same * 2 )) -gt $(( $r_lc_other )) ]; then
63 if yesno "Probable upstream rebase detected, automatically fix?" 'git log --oneline --graph --date-order --left-right "$r_other"..."$r_me"'; then
64 git reset --hard "$r_me"
74 fix_upstream_rebase_mergeok()
76 r_me=`git rev-parse --revs-only HEAD^1 2>/dev/null || true`
77 r_other=`git rev-parse --revs-only HEAD^2 2>/dev/null || true`
81 fix_upstream_rebase_mergefail()
83 r_me=`git rev-parse --revs-only HEAD 2>/dev/null || true`
84 r_other=`git rev-parse --revs-only MERGE_HEAD 2>/dev/null || true`
90 if ! [ -f ".git/config" ]; then
91 $ECHO "Not a git repository. Bailing out to not cause damage."
94 verbose git config remote.origin.url "$1"
96 verbose git config remote.origin.pushurl "$2"
98 verbose git config --unset remote.origin.pushurl || true
100 verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
101 case ",`repoflags "$d"`," in
103 verbose git config --unset core.autocrlf || true
106 verbose git config core.autocrlf input
109 if [ -z "`git config push.default || true`" ]; then
110 verbose git config push.default current # or is tracking better?
112 verbose git config filter.mapclean.clean "tr -d '\r' | grep '^[^/]'"
113 verbose git config filter.mapclean.smudge "cat"
118 # first result is to be ignored, but we use it to check status
119 git ls-remote "$1" refs/heads/master >/dev/null 2>&1 || return 1
120 { time -p git ls-remote "$1" refs/heads/master; } 2>&1 >/dev/null | head -n 1 | cut -d ' ' -f 2 | tr -d . | sed 's,^0*,,'
121 # unit: clock ticks (depends on what "time" returns
129 if ! { time -p true; } >/dev/null 2>&1; then
130 msg "Cannot do timing in this shell"
148 if t=`mirrorspeed "$m"`; then
150 tt=$(($t$op)) # fudge factor
151 msg "$m -> $t$op = $tt ticks"
152 if [ -z "$bestt" ] || [ "$tt" -lt "$bestt" ]; then
163 if [ -n "$bestin" ]; then
164 msg "Best mirror seems to be $pre$bestin$suf"
175 enter "$d0/$d" verbose
176 verbose fix_upstream_rebase_mergefail && verbose fix_upstream_rebase_mergeok
182 pushurl=`repopushurl "$d"`
183 branch=`repobranch "$d"`
184 if [ -f "$d0/$d/.git/config" ]; then
186 fix_git_config "$url" "$pushurl"
192 # enable the ssh URL for pushing
195 if [ -f ~/.ssh/id_rsa.pub ]; then
197 msg "A key already exists and no new one will be generated. If you"
198 msg "already have done the procedure for getting your key approved, you"
199 msg "can skip the following paragraph and already use the repository."
201 msg "To get access, your key has to be approved first. For that, visit"
202 msg "$devsite_url, then log in, create a \"New Issue\" on"
203 msg "the \"Support\" tracker in the \"Repository\" category where you"
204 msg "apply for access and paste the following output into the issue:"
206 msg "`cat ~/.ssh/id_rsa.pub`"
208 msg "Note that you will only have write access to branches that start"
209 msg "with your user name."
210 elif [ -f ~/.ssh/id_dsa.pub ]; then
212 msg "A key already exists and no new one will be generated. If you"
213 msg "already have done the procedure for getting your key approved, you"
214 msg "can skip the following paragraph and already use the repository."
216 msg "To get access, your key has to be approved first. For that, visit"
217 msg "$devsite_url, then log in, create a \"New Issue\" on"
218 msg "the \"Support\" tracker in the \"Repository\" category where you"
219 msg "apply for access and paste the following output into the issue:"
221 msg "`cat ~/.ssh/id_dsa.pub`"
223 msg "Note that you will only have write access to branches that start"
224 msg "with your user name."
227 msg "No key has been generated yet. One will be generated now."
228 msg "If other people are using your computer, it is recommended"
229 msg "to specify a passphrase. Otherwise you can simply hit ENTER"
230 msg "when asked for a passphrase."
232 ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
234 msg "To get access, your key has to be approved first. For that, visit"
235 msg "$devsite_url, then log in, create a \"New Issue\" on"
236 msg "the \"Support\" tracker in the \"Repository\" category where you"
237 msg "apply for access and paste the following output into the issue:"
239 msg "`cat ~/.ssh/id_rsa.pub`"
241 msg "Note that you will only have write access to branches that start"
242 msg "with your user name."
249 oldpushbase=$pushbase
251 if [ x"$1" = x"-N" ]; then
253 elif [ x"$1" = x"-p" ]; then
254 pushbase=$pushsite_url
255 elif [ x"$1" = x"-ps" ]; then
256 pushbase=$pushsite_url
257 elif [ x"$1" = x"-ph" ]; then
258 pushbase=$httppushsite_url
259 elif [ x"$1" = x"-s" ]; then
261 elif [ x"$1" = x"-g" ]; then
264 elif [ x"$1" = x"-h" ]; then
267 elif [ x"$1" = x"-l" ]; then
275 msg "Invalid location!"
276 msg "Possible locations for the -l option:"
277 msg " nl (Netherlands, run by merlijn)"
278 msg " de (Germany, run by divVerent)"
279 msg " us (United States of America, run by detrate)"
280 msg " best (find automatically)"
281 msg " default (currently nl)"
294 if [ x"`git config xonotic.all.mirrorselection 2>/dev/null || true`" != x"done" ]; then
301 # if we fetched via ssh://, switch to git:// for fetching and keep using ssh:// for pushing
308 newbase=`$ECHO "$base" | sed "s,://\(.*\.\)\?git.xonotic.org/,:// .git.xonotic.org/,"`
311 if location=`bestmirror $newbase"xonotic.git" de us nl:'*6/5'`; then # 20% malus to the NL server to not overload it too much
312 git config xonotic.all.mirrorselection done
329 *://*.git.xonotic.org/*)
330 location=${base%%.git.xonotic.org/*}
331 location=${location##*://}
339 if [ -n "$location" ]; then
340 base=`$ECHO "$base" | sed "s,://\(.*\.\)\?git.xonotic.org/,://$location.git.xonotic.org/,"`
342 base=`$ECHO "$base" | sed "s,://\(.*\.\)\?git.xonotic.org/,://git.xonotic.org/,"`
344 pushbase=`$ECHO "$pushbase" | sed "s,://\(.*\.\)\?git.xonotic.org/,://xonotic@push.git.xonotic.org/,"`
345 if [ x"$base" != x"$oldbase" ] || [ x"$pushbase" != x"$oldpushbase" ]; then
347 pushurl=`repopushurl .`
348 fix_git_config "$url" "$pushurl"
350 elif $allow_pull; then
355 pushurl=`repopushurl "$d"`
356 branch=`repobranch "$d"`
357 if [ -f "$d0/$d/.git/config" ]; then
358 # if we have .no file, skip
359 if [ -f "$d0/$d.no" ]; then
360 msg "Repository $d disabled by a .no file, delete $d.no to enable; thus, not updated"
364 enter "$d0/$d" verbose
365 r=`git symbolic-ref HEAD`
367 if git config branch.$r.remote >/dev/null 2>&1; then
368 if ! verbose git pull; then
369 fix_upstream_rebase_mergefail || true
370 check_mergeconflict "$d"
371 $ECHO "Pulling failed. Press ENTER to continue, or Ctrl-C to abort."
374 fix_upstream_rebase_mergeok || true
379 checkself "$cmd" "$@"
381 verbose git remote prune origin
385 if [ -d "$d0/$d" ]; then
386 if yesno "$d0/$d is in the way, get rid of it and reclone?"; then
387 verbose rm -rf "$d0/$d"
389 echo "Note: $d0/$d will stay broken."
393 verbose git clone "$url" "$d0/$d"
394 enter "$d0/$d" verbose
395 fix_git_config "$url" "$pushurl"
396 if [ "$branch" != "master" ]; then
397 verbose git checkout --track -b "$branch" origin/"$branch"
405 if [ x"$1" = x"-f" ]; then
411 if [ -z "$branch" ]; then
414 branch=${remote#origin/}
423 if [ -n "$checkoutflags" ]; then
424 set -- -f "$@" # to make checkself work again
428 enter "$d0/$d" verbose
430 if [ -n "$b" ] && git rev-parse "refs/heads/$b" >/dev/null 2>&1; then
432 verbose git checkout $checkoutflags "$b"
433 elif [ -n "$b" ] && git rev-parse "refs/remotes/$remote/$b" >/dev/null 2>&1; then
435 verbose git checkout $checkoutflags --track -b "$b" "$remote/$b"
438 if git rev-parse "refs/heads/$b" >/dev/null 2>&1; then
439 verbose git checkout $checkoutflags "$b"
440 elif git rev-parse "refs/remotes/$remote/$b" >/dev/null 2>&1; then
441 verbose git checkout $checkoutflags --track -b "$b" "$remote/$b"
443 $ECHO "WTF? Not even branch $b doesn't exist in $d"
448 checkself "$cmd" "$@"
452 $ECHO "The requested branch was not found in any repository."
460 if [ -z "$branch" ]; then
464 if [ -z "$branch" ]; then
467 r=`git symbolic-ref HEAD`
474 dv=`visible_repo_name "$d"`
475 enter "$d0/$d" verbose
476 if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then
477 $ECHO "Already having this branch in $dv."
479 if yesno "Branch in $dv?"; then
480 if [ -n "$srcbranch" ]; then
483 b=origin/"`repobranch "$d"`"
484 verbose git fetch origin || true
486 # TODO do this without pushing
487 verbose git checkout -b "$branch" "$b"
488 verbose git config "branch.$branch.remote" "$remote"
489 verbose git config "branch.$branch.merge" "refs/heads/$branch"
499 cd "$d0/$d" # am in a pipe, shouldn't use enter
500 git branch -r -v -v | cut -c 3- | sed "s/^(no branch)/(no_branch)/" | sed "s,^,$d ,"
505 while read -r d BRANCH REV TEXT; do
506 if [ x"$BRANCH" = x"`repobranch "$d"`" ]; then
509 if [ x"$REV" = x"->" ]; then
512 BRANCH=${BRANCH#remotes/}
513 ID=`$ECHO "$BRANCH" | tr -c "A-Za-z0-9." "_"`
514 branches_list="$branches_list $BRANCH" # TEH SORT MAKEZ IT UNIEQ
515 eval "r=\$branches_repos_$ID"
517 eval "branches_repos_$ID=\$r"
519 $ECHO -n "$branches_list" | xargs -n 1 $ECHO | sort -u | while IFS= read -r BRANCH; do
520 ID=`$ECHO "$BRANCH" | tr -c "A-Za-z0-9." "_"`
521 eval "r=\$branches_repos_$ID"
522 printf "%-60s %s\n" "$BRANCH" "$r"
530 dv=`visible_repo_name "$d"`
531 enter "$d0/$d" verbose
532 r=`git symbolic-ref HEAD`
534 diffdata=`git diff --color HEAD`
535 if [ -n "$diffdata" ]; then
536 # we have uncommitted changes
537 if yesno "Uncommitted changes in \"$r\" in $dv. Commit?" '$ECHO "$diffdata" | less -r'; then
538 verbose git commit -a
541 rem=`git config "branch.$r.remote" || $ECHO origin`
542 bra=`git config "branch.$r.merge" || $ECHO "$r"`
543 upstream="$rem/${bra#refs/heads/}"
544 if ! git rev-parse "$upstream" >/dev/null 2>&1; then
545 upstream="origin/`repobranch "$d"`"
547 logdata=`git log --color "$upstream".."$r"`
548 if [ -n "$logdata" ]; then
549 if yesno "Push \"$r\" in $dv?" '$ECHO "$logdata" | less -r'; then
550 verbose git push "$rem" HEAD
553 if [ x"$submit" = x"-s" ]; then
556 verbose git push "$rem" HEAD:"${bra%%/*}/finished/${bra#*/}"
565 if [ x"$1" = x"-k" ]; then
570 if verbose cd "$d0/$d"; then
590 # ./all clean [-m] [-f | -fu | -fU] [-r] [-D]
591 # ./all clean --reclone
594 if [ x"$X" = x"--reclone" ]; then
601 elif [ x"$X" = x"-f" ]; then
603 elif [ x"$X" = x"-u" ]; then
605 elif [ x"$X" = x"-U" ]; then
608 elif [ x"$X" = x"-fu" ]; then
611 elif [ x"$X" = x"-fU" ]; then
615 elif [ x"$X" = x"-m" ]; then
617 elif [ x"$X" = x"-r" ]; then
619 elif [ x"$X" = x"-D" ]; then
621 elif $ECHO "$X" | grep '^-FFFF*UUUU*$' >/dev/null; then
624 msg " ,--'-\\P/\`\\ FFFFFFF"
625 msg " __/_ B/,-.\\ FFFFFFF"
626 msg " / _\\ (// O\\\\ FFFFFF"
627 msg "| (O \`) _\\._ _)\\ FFFUU"
628 msg "| |___/.^d0~~\"\\ \\ UUUU"
629 msg "| |\`~' \\ | UUUU"
630 msg "| | __,C>|| UUUU"
631 msg "\\ /_ ,-/,-' | UUUU"
632 msg " \\\\_ \\_>~' / UUUU-"
635 msg "Unknown arg: $X"
644 if $gotoupstream; then
646 msg "Must also use -f (delete local changes) when using -u"
650 if $fetchupstream; then
651 verbose git fetch origin
652 verbose git remote prune origin
654 verbose git checkout -f "`repobranch "$d"`"
655 verbose git reset --hard origin/"`repobranch "$d"`"
657 r=`git symbolic-ref HEAD`
659 rem=`git config "branch.$r.remote" || $ECHO origin`
660 bra=`git config "branch.$r.merge" || $ECHO "$r"`
661 upstream="$rem/${bra#refs/heads/}"
662 if $fetchupstream; then
663 for t in `git tag`; do
664 verbose git tag -d "$t"
666 verbose git fetch "$rem"
667 verbose git remote prune "$rem"
669 if ! git rev-parse "$upstream" >/dev/null 2>&1; then
670 upstream="origin/`repobranch "$d"`"
672 verbose git reset --hard "$upstream"
674 elif $gotomaster; then
676 verbose git checkout -f "`repobranch "$d"`"
677 verbose git reset --hard
679 verbose git checkout "`repobranch "$d"`"
682 verbose git reset --hard
684 if $rmuntracked; then
687 verbose git clean -df || true
690 verbose git clean -xdf || true
694 if $killbranches; then
695 git for-each-ref --format='%(refname)' refs/heads/ | while IFS= read -r B; do
696 if [ x"$B" != x"`git symbolic-ref HEAD`" ]; then
697 verbose git branch -D "${B#refs/heads/}"
700 git rev-parse refs/heads/master >/dev/null 2>&1 || verbose git branch --track master origin/master || true
701 git rev-parse "refs/heads/`repobranch "$d"`" >/dev/null 2>&1 || verbose git branch --track "`repobranch "$d"`" origin/"`repobranch "$d"`" || true
703 checkself "$cmd" "$@"
707 $ECHO " $SELF branch <branch>"
708 $ECHO " $SELF branch <remote> <branch> [<srcbranch>]"
709 $ECHO " $SELF branches"
710 $ECHO " $SELF checkout|switch <branch>"
711 $ECHO " $SELF checkout|switch <remote>/<branch>"
712 $ECHO " $SELF clean [-m] [-f | -fu | -fU] [-r] [-D]"
713 $ECHO " $SELF clean --reclone"
714 $ECHO " $SELF each|foreach [-k] command..."
715 $ECHO " $SELF fix_upstream_rebase"
716 $ECHO " $SELF keygen"
717 $ECHO " $SELF push|commit [-s]"
718 $ECHO " $SELF update|pull [-N] [-s | -h [-p] | -g [-p]] [-l de|nl|default]"