xonotic/misc/tools/all/git.subr

984 lines
23 KiB
Plaintext

initrepo_()
{
if [ x"$3" != x"." ]; then
return
fi
case "$1" in
*$4)
base=${1%$4}
;;
esac
case "$2" in
*$4)
pushbase=${2%$4}
;;
esac
}
initrepo()
{
base=
pushbase=
allrepos initrepo_ "`git config remote.origin.url`" "`git config remote.origin.pushurl`"
if [ -z "$base" ]; then
msg "The main repo is not xonotic.git, what have you done?"
exit 1
fi
msg "Found main repo = $base"
if [ -n "$pushbase" ]; then
msg "Found push repo = $pushbase"
fi
}
matchrepoflag()
{
case ",$2," in
*",$1,"*)
return 0
;;
*)
return 1
;;
esac
}
testrepoflag_()
{
[ x"$1" = x"$3" ] || return
if matchrepoflag "$6" "$2"; then
echo 0
fi
}
testrepoflag()
{
allrepos testrepoflag_ "$1" "$2" | grep ^0 >/dev/null
}
mirrorspeed()
{
# first result is to be ignored, but we use it to check status
git ls-remote "$1" refs/heads/master >/dev/null 2>&1 || return 1
# if we can't time, we only check availability
if ! $have_time; then
echo 0
return
fi
# now actually time it
(
set +x
export REPO="$1" # so that the sh -c subshell can use it
{ measure_time sh -c 'git ls-remote "$REPO" refs/heads/master >/dev/null 2>&1'; } 2>&1 >/dev/null | head -n 1 | cut -d ' ' -f 2 | tr -d . | sed 's,^0*,,' | grep . || echo 0
# unit: clock ticks (depends on what "time" returns
)
}
bestmirror()
{
oldurl="$1"
newprotocol="$2"
newlocation="$3"
oldprotocol=
oldlocation=
testrepo=
bestmirror_firstrepo()
{
if [ -z "$testrepo" ]; then
testrepo=$2
fi
}
allrepos bestmirror_firstrepo
bestmirror_findold()
{
if [ x"$oldurl" = x"$3" ]; then
oldprotocol=$1
oldlocation=$2
fi
}
allmirrors bestmirror_findold
if [ -z "$newprotocol" ]; then
newprotocol=$oldprotocol
fi
if [ -z "$newlocation" ]; then
newlocation=$oldlocation
fi
besturl=
bestlocation=
besttime=
bestcount=
bestmirror_benchmark()
{
bmb_curloc=$1
bmb_proto=$2
bmb_loc=$3
bmb_url=$4
bmb_fudge=$5
if [ -z "$bmb_loc" ]; then
# empty location is not allowed
return
fi
case " $newprotocol " in
*" "*)
# no protocol requested? all match
;;
*" $bmb_proto "*)
;;
*)
return
;;
esac
# prefer location match
case " $newlocation " in
*" $bmb_loc "*)
# bmb_curloc is true in first run, false in second
# so first run gets all matching locations
# so second run gets all non-matching locations
if ! $bmb_curloc; then
return
fi
;;
*)
if $bmb_curloc; then
return
fi
case " $newlocation " in
*" $bestlocation "*)
# worse
return
;;
esac
;;
esac
case " $newlocation " in
*" $bmb_loc "*)
# see below
;;
*)
case " $newlocation " in
*" $bestlocation "*)
# worse
return
;;
esac
;;
esac
msg "Testing speed of $bmb_url..."
# only working mirrors
if ! thistime=`mirrorspeed "$bmb_url$testrepo"`; then
msg "-> FAILED"
return
fi
thistime=$(($thistime $bmb_fudge))
msg "-> $thistime"
# anything is better than nothing
if [ -z "$besttime" ]; then
besturl=$bmb_url
bestlocation=$bmb_loc
besttime=$thistime
bestcount=1
return
fi
# prefer location match
case " $newlocation " in
*" $bmb_loc "*)
case " $newlocation " in
*" $bestlocation "*)
# equality
;;
*)
# better
besturl=$bmb_url
bestlocation=$bmb_loc
besttime=$thistime
bestcount=1
return
;;
esac
;;
*)
# if newlocation matches bestlocation, then we already discarded it above
;;
esac
# if we get here, we must compare mirror speed as we have more than one match
if [ $thistime -gt $besttime ]; then
return
elif [ $thistime -lt $besttime ]; then
besturl=$bmb_url
bestlocation=$bmb_loc
besttime=$thistime
bestcount=1
return
fi
# both location and time match. Random decision.
bestcount=$(($bestcount + 1))
if [ $((($RANDOM + 0) % $bestcount)) -eq 0 ]; then
besturl=$bmb_url
bestlocation=$bmb_loc
fi
}
allmirrors bestmirror_benchmark true
allmirrors bestmirror_benchmark false
echo "$besturl"
}
testrepoflag_()
{
[ x"$1" = x"$3" ] || return
case ",$6," in
*",$2,"*)
echo 0
;;
*)
;;
esac
}
testrepoflag()
{
allrepos testrepoflag_ "$1" "$2" | grep ^0 >/dev/null
}
listrepos_()
{
d=$1
f=$4
p="${d%dir}"
# if we have .no file, skip
if [ -f "$d.no" ]; then
msg "Repository $d disabled by a .no file, delete $d.no to enable"
return
fi
# if .yes file exists, always keep it
if [ -f "$d.yes" ]; then
msg "Repository $d enabled by a .yes file"
$ECHO "$d"
return
fi
# remove broken clones so they don't mess up stuff
if [ x"$d" != x"." ] && [ -d "$d" ] && ! [ -d "$d/.git" ]; then
msg "$d exists but has no .git subdir. Probably a broken clone. Deleting."
verbose rm -rf "$d"
return
fi
# if we have the dir, always keep it
if [ -d "$d" ]; then
msg "Repository $d enabled because it already exists"
$ECHO "$d"
return
fi
# if we have matching pk3, skip
if [ x"$p" != x"$d" ] && [ -f "$p" ]; then
msg "Repository $d disabled by matching .pk3 file, delete $p or create $d.yes to enable"
return
fi
# if "no" flag is set, skip
if matchrepoflag "$f" no; then
msg "Repository $d disabled by default, create $d.yes to enable"
return
fi
# default: enable
msg "Repository $d enabled by default"
$ECHO "$d"
}
listrepos()
{
$ECHO `allrepos listrepos_`
}
initrepo
repos=`listrepos`
ifrepoenabled()
{
eval ire_test=\$$(($1 + 3))
shift
case " $repos " in
*" $ire_test "*)
"$@"
;;
esac
}
check_mergeconflict() # overrides the one in ./all
{
if git ls-files -u | grep ' 1 '; then
$ECHO
$ECHO "MERGE CONFLICT."
$ECHO "change into the \"$1\" project directory, and then:"
$ECHO "- edit the files mentioned above with your favorite editor,"
$ECHO " and fix the conflicts (marked with <<<<<<< blocks)"
$ECHO "- for binary files, you can select the files using"
$ECHO " git checkout --ours or git checkout --theirs"
$ECHO "- when done with a file, 'git add' the file"
$ECHO "- when done, 'git commit'"
$ECHO
exit 1
fi
}
visible_repo_name()
{
case "$1" in
.)
$ECHO "the root directory"
;;
*)
$ECHO "\"$1\""
;;
esac
}
fix_upstream_rebase()
{
if [ -z "$r_me" ] || [ -z "$r_other" ]; then
return
fi
# one of the two sides of the merge should be remote upstream, or all is fine
r_r=`git symbolic-ref HEAD`
r_r=${r_r#refs/heads/}
r_rem=`git config "branch.$r_rem.remote" || $ECHO origin`
r_bra=`git config "branch.$r_bra.merge" || $ECHO "$r_r"`
r_bra=${r_bra#refs/heads/}
if [ x"$r_me" != x"`git rev-parse "$r_rem/$r_bra"`" ]; then
if [ x"$r_other" != x"`git rev-parse "$r_rem/$r_bra"`" ]; then
return
fi
fi
r_base=`git merge-base "$r_me" "$r_other"`
# no merge-base? upstream did filter-branch
if [ -n "$r_base" ]; then
# otherwise, check if the two histories are "similar"
r_l_me=`git log --pretty="format:%s" "$r_other".."$r_me" | grep -v "^Merge" | sort -u`
r_l_other=`git log --pretty="format:%s" "$r_me".."$r_other" | grep -v "^Merge" | sort -u`
# heuristics: upstream rebase/filter-branch if more than 50% of the commits of one of the sides are in the other too
r_lc_me=`$ECHO "$r_l_me" | wc -l`
r_lc_other=`$ECHO "$r_l_other" | wc -l`
r_lc_together=`{ $ECHO "$r_l_me"; $ECHO "$r_l_other"; } | sort -u | wc -l`
r_lc_same=$(($r_lc_me + $r_lc_other - $r_lc_together))
if [ $(( $r_lc_same * 2 )) -gt $(( $r_lc_me )) ] || [ $(( $r_lc_same * 2 )) -gt $(( $r_lc_other )) ]; then
if yesno "Probable upstream rebase detected, automatically fix?" 'git log --oneline --graph --date-order --left-right "$r_other"..."$r_me"'; then
git reset --hard "$r_me"
git pull --rebase
return 1
fi
fi
fi
return 0
}
fix_upstream_rebase_mergeok()
{
r_me=`git rev-parse --revs-only HEAD^1 2>/dev/null || true`
r_other=`git rev-parse --revs-only HEAD^2 2>/dev/null || true`
fix_upstream_rebase
}
fix_upstream_rebase_mergefail()
{
r_me=`git rev-parse --revs-only HEAD 2>/dev/null || true`
r_other=`git rev-parse --revs-only MERGE_HEAD 2>/dev/null || true`
fix_upstream_rebase
}
fix_git_config()
{
if ! [ -f ".git/config" ]; then
$ECHO "Not a git repository. Bailing out to not cause damage."
exit 1
fi
verbose git config remote.origin.url "$1"
if [ -n "$2" ]; then
verbose git config remote.origin.pushurl "$2"
else
verbose git config --unset remote.origin.pushurl || true
fi
verbose git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
if testrepoflag "$d" noautocrlf; then
verbose git config --unset core.autocrlf || true
else
verbose git config core.autocrlf input
fi
if [ -z "`git config push.default || true`" ]; then
verbose git config push.default current # or is tracking better?
fi
verbose git config filter.mapclean.clean "tr -d '\r' | grep '^[^/]'"
verbose git config filter.mapclean.smudge "cat"
}
setrepovars()
{
while [ $# -gt 4 ]; do
shift
done
d=$1
url="$base$2"
if [ -n "$pushbase" ]; then
pushurl="$pushbase$2"
else
pushurl=
fi
branch=$3
f=$4
}
handled=true
case "$cmd" in
fix_upstream_rebase)
fix_upstream_rebase_()
{
setrepovars "$@"
enter "$d0/$d" verbose
verbose fix_upstream_rebase_mergefail && verbose fix_upstream_rebase_mergeok
}
allrepos ifrepoenabled 0 fix_upstream_rebase_
;;
fix_config)
fix_config_()
{
setrepovars "$@"
if [ -f "$d0/$d/.git/config" ]; then
verbose cd "$d0/$d"
fix_git_config "$url" "$pushurl"
cd "$d0"
fi
}
allrepos ifrepoenabled 0 fix_config_
;;
keygen)
if [ -f ~/.ssh/id_rsa.pub ]; then
msg ""
msg "A key already exists and no new one will be generated. If you"
msg "already have done the procedure for getting your key approved, you"
msg "can skip the following paragraph and already use the repository."
msg ""
msg "To get access, your key has to be approved first. For that, visit"
msg "$gitsite_url, then log in, enter the"
msg "\"xonotic\" project, create an \"Issue\" tagged \"Repository Access\""
msg "to apply for access and paste the following output into the issue:"
msg ""
msg "After that, go to your profile settings, \"SSH Keys\", \"Add SSH Key\""
msg "and paste the following output:"
msg ""
msg "`cat ~/.ssh/id_rsa.pub`"
elif [ -f ~/.ssh/id_dsa.pub ]; then
msg ""
msg "A key already exists and no new one will be generated. If you"
msg "already have done the procedure for getting your key approved, you"
msg "can skip the following paragraph and already use the repository."
msg ""
msg "To get access, your key has to be approved first. For that, visit"
msg "$gitsite_url, then log in, enter the"
msg "\"xonotic\" project, create an \"Issue\" tagged \"Repository Access\""
msg "to apply for access and paste the following output into the issue:"
msg ""
msg "After that, go to your profile settings, \"SSH Keys\", \"Add SSH Key\""
msg "and paste the following output:"
msg ""
msg "`cat ~/.ssh/id_dsa.pub`"
else
msg ""
msg "No key has been generated yet. One will be generated now."
msg "If other people are using your computer, it is recommended"
msg "to specify a passphrase. Otherwise you can simply hit ENTER"
msg "when asked for a passphrase."
msg ""
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
msg ""
msg "To get access, your key has to be approved first. For that, visit"
msg "$gitsite_url, then log in, enter the"
msg "\"xonotic\" project, create an \"Issue\" tagged \"Repository Access\""
msg "to apply for access and paste the following output into the issue:"
msg ""
msg "After that, go to your profile settings, \"SSH Keys\", \"Add SSH Key\""
msg "and paste the following output:"
msg ""
msg "`cat ~/.ssh/id_rsa.pub`"
fi
msg ""
msg "Note that you will only have write access to branches that start"
msg "with your user name."
msg
msg "Once you have gotten access, run ./all update -p"
;;
update|pull)
allow_pull=true
need_bestmirror=false
newprotocol=
newpushprotocol=
newlocation=
case "`git config xonotic.all.mirrorselection 2>/dev/null || true`" in
done)
;;
try_same)
need_bestmirror=true
;;
try_all)
newprotocol="git http"
newlocation="any"
need_bestmirror=true
;;
*)
newprotocol= # same protocol
newlocation="any"
need_bestmirror=true
;;
esac
if $need_bestmirror; then
found=false
identifymirror_()
{
if [ x"$base" = x"$3" ]; then
found=true
fi
}
allmirrors identifymirror_
if ! $found; then
msg ""
msg "Current mirror not found = $base"
msg "but the last pull attempt failed."
msg ""
msg "Use ./all update -l any to switch to the best mirror."
msg ""
need_bestmirror=false
fi
fi
while :; do
if [ x"$1" = x"-N" ]; then
allow_pull=false
elif [ x"$1" = x"-p" ]; then
newpushprotocol=ssh
need_bestmirror=true
elif [ x"$1" = x"-s" ]; then
newprotocol=ssh
need_bestmirror=true
elif [ x"$1" = x"-g" ]; then
newprotocol=git
need_bestmirror=true
elif [ x"$1" = x"-h" ]; then
newprotocol=http
need_bestmirror=true
elif [ x"$1" = x"-l" ]; then
newlocation=$2
need_bestmirror=true
shift
else
break
fi
shift
done
if $need_bestmirror; then
newbase=`bestmirror "$base" "$newprotocol" "$newlocation"`
if [ -z "$newbase" ]; then
msg "Could not find any good mirror. Maybe try again later."
git config xonotic.all.mirrorselection try_all
exit 1
fi
if [ -n "$newpushprotocol" ]; then
if [ -n "$pushbase" ]; then
newpushbase=`bestmirror "$pushbase" "$newpushprotocol" "$newlocation"`
else
newpushbase=`bestmirror "$base" "$newpushprotocol" "$newlocation"`
fi
else
newpushbase=$pushbase
fi
if [ x"$base" != x"$newbase" ] || [ x"$pushbase" != x"$newpushbase" ]; then
base=$newbase
pushbase=$newpushbase
seturl_()
{
setrepovars "$@"
if [ x"$d" = x"." ]; then
fix_git_config "$url" "$pushurl"
fi
}
allrepos ifrepoenabled 0 seturl_
fi
git config xonotic.all.mirrorselection done
fi
"$SELF" fix_config
pull_()
{
setrepovars "$@"
if [ -f "$d0/$d/.git/config" ]; then
# if we have .no file, skip
if [ -f "$d0/$d.no" ]; then
msg "Repository $d disabled by a .no file, delete $d.no to enable; thus, not updated"
return
fi
if $allow_pull; then
enter "$d0/$d" verbose
r=`git symbolic-ref HEAD`
r=${r#refs/heads/}
if git config branch.$r.remote >/dev/null 2>&1; then
o=`( cd "$d0" && git config xonotic.all.mirrorselection 2>/dev/null || true )`
( cd "$d0" && git config xonotic.all.mirrorselection try_same )
if ! verbose git pull; then
if fix_upstream_rebase_mergefail; then
check_mergeconflict "$d"
$ECHO "Pulling failed. Press ENTER to continue, or Ctrl-C to abort."
read -r DUMMY
fi
else
( cd "$d0" && git config xonotic.all.mirrorselection "$o" )
fix_upstream_rebase_mergeok || true
fi
fi
cd "$d00"
checkself "$cmd" "$@"
cd "$d0/$d"
verbose git remote prune origin
cd "$d0"
fi
else
if [ -d "$d0/$d" ]; then
if yesno "$d0/$d is in the way, get rid of it and reclone?"; then
verbose rm -rf "$d0/$d"
else
echo "Note: $d0/$d will stay broken."
return
fi
fi
o=`git config xonotic.all.mirrorselection 2>/dev/null || true`
git config xonotic.all.mirrorselection try_same
verbose git clone --branch "$branch" "$url" "$d0/$d"
git config xonotic.all.mirrorselection "$o"
enter "$d0/$d" verbose
fix_git_config "$url" "$pushurl"
cd "$d0"
fi
}
allrepos ifrepoenabled 0 pull_
;;
checkout|switch)
checkoutflags=
if [ x"$1" = x"-f" ]; then
checkoutflags=-f
shift
fi
remote=$1
branch=$2
if [ -z "$branch" ]; then
case "$remote" in
origin/*)
askbranch=${remote#origin/}
remote=origin
;;
*)
askbranch=$remote
remote=origin
;;
esac
fi
if [ -n "$checkoutflags" ]; then
set -- -f "$@" # to make checkself work again
fi
exists=false
checkout_()
{
setrepovars "$@"
enter "$d0/$d" verbose
b=$askbranch
if [ -n "$b" ] && git rev-parse "refs/heads/$b" >/dev/null 2>&1; then
exists=true
verbose git checkout $checkoutflags "$b"
elif [ -n "$b" ] && git rev-parse "refs/remotes/$remote/$b" >/dev/null 2>&1; then
exists=true
verbose git checkout $checkoutflags --track -b "$b" "$remote/$b"
else
b=$branch
if git rev-parse "refs/heads/$b" >/dev/null 2>&1; then
[ -n "$b" ] || exists=true
verbose git checkout $checkoutflags "$b"
elif git rev-parse "refs/remotes/$remote/$b" >/dev/null 2>&1; then
[ -n "$b" ] || exists=true
verbose git checkout $checkoutflags --track -b "$b" "$remote/$b"
else
$ECHO "WTF? Not even branch $b doesn't exist in $d"
exit 1
fi
fi
cd "$d00"
checkself "$cmd" "$@"
cd "$d0"
}
allrepos ifrepoenabled 0 checkout_
if ! $exists; then
$ECHO "The requested branch was not found in any repository."
fi
exec "$SELF" branch
;;
branch)
remote=$1
askbranch=$2
srcbranch=$3
if [ -z "$askbranch" ]; then
askbranch=$remote
remote=origin
fi
branch_show_()
{
setrepovars "$@"
enter "$d0/$d"
r=`git symbolic-ref HEAD`
r=${r#refs/heads/}
dv=`visible_repo_name "$d"`
$ECHO "$dv is at $r"
cd "$d0"
}
if [ -n "$askbranch" ]; then
branch_()
{
setrepovars "$@"
dv=`visible_repo_name "$d"`
enter "$d0/$d" verbose
if git rev-parse "refs/heads/$askbranch" >/dev/null 2>&1; then
$ECHO "Already having this branch in $dv."
else
if yesno "Branch in $dv?"; then
if [ -n "$srcbranch" ]; then
b=$srcbranch
else
b=$branch
verbose git fetch origin || true
fi
verbose git checkout -b "$askbranch" "$b"
verbose git config "branch.$askbranch.remote" "$remote"
verbose git config "branch.$askbranch.merge" "refs/heads/$askbranch"
fi
fi
cd "$d0"
}
allrepos ifrepoenabled 0 branch_
fi
allrepos ifrepoenabled 0 branch_show_
;;
push|commit)
submit=$1
push_()
{
setrepovars "$@"
dv=`visible_repo_name "$d"`
enter "$d0/$d" verbose
r=`git symbolic-ref HEAD`
r=${r#refs/heads/}
diffdata=`git diff --color HEAD`
if [ -n "$diffdata" ]; then
# we have uncommitted changes
if yesno "Uncommitted changes in \"$r\" in $dv. Commit?" '$ECHO "$diffdata" | less -r'; then
verbose git commit -a
fi
fi
rem=`git config "branch.$r.remote" || $ECHO origin`
bra=`git config "branch.$r.merge" || $ECHO "$r"`
upstream="$rem/${bra#refs/heads/}"
if ! git rev-parse "$upstream" >/dev/null 2>&1; then
upstream="origin/$branch"
fi
logdata=`git log --color "$upstream".."$r"`
if [ -n "$logdata" ]; then
if yesno "Push \"$r\" in $dv?" '$ECHO "$logdata" | less -r'; then
verbose git push "$rem" HEAD
fi
fi
if [ x"$submit" = x"-s" ]; then
case "$r" in
*/*)
verbose git push "$rem" HEAD:"${bra%%/*}/finished/${bra#*/}"
;;
esac
fi
cd "$d0"
}
allrepos ifrepoenabled 0 push_
;;
each|foreach)
keep_going=false
if [ x"$1" = x"-k" ]; then
keep_going=true
shift
fi
for d in $repos; do
if verbose cd "$d0/$d"; then
if $keep_going; then
verbose "$@" || true
else
verbose "$@"
fi
cd "$d0"
fi
done
;;
clean)
"$SELF" fix_config
"$SELF" update -N
force=false
gotoupstream=false
fetchupstream=false
gotomaster=false
rmuntracked=false
killbranches=false
# usage:
# ./all clean [-m] [-f | -fu | -fU] [-r] [-D]
# ./all clean --reclone
found=false
for X in "$@"; do
if [ x"$X" = x"--reclone" ]; then
force=true
fetchupstream=true
gotoupstream=true
gotomaster=true
rmuntracked=true
killbranches=true
elif [ x"$X" = x"-f" ]; then
force=true
elif [ x"$X" = x"-u" ]; then
gotoupstream=true
elif [ x"$X" = x"-U" ]; then
gotoupstream=true
fetchupstream=true
elif [ x"$X" = x"-fu" ]; then
force=true
gotoupstream=true
elif [ x"$X" = x"-fU" ]; then
force=true
gotoupstream=true
fetchupstream=true
elif [ x"$X" = x"-m" ]; then
gotomaster=true
elif [ x"$X" = x"-r" ]; then
rmuntracked=true
elif [ x"$X" = x"-D" ]; then
killbranches=true
elif $ECHO "$X" | grep '^-FFFF*UUUU*$' >/dev/null; then
msg ''
msg " _____"
msg " ,--'-\\P/\`\\ FFFFFFF"
msg " __/_ B/,-.\\ FFFFFFF"
msg " / _\\ (// O\\\\ FFFFFF"
msg "| (O \`) _\\._ _)\\ FFFUU"
msg "| |___/.^d0~~\"\\ \\ UUUU"
msg "| |\`~' \\ | UUUU"
msg "| | __,C>|| UUUU"
msg "\\ /_ ,-/,-' | UUUU"
msg " \\\\_ \\_>~' / UUUU-"
msg ''
else
msg "Unknown arg: $X"
fi
found=true
done
if ! $found; then
rmuntracked=true
fi
clean_()
{
setrepovars "$@"
verbose cd "$d0/$d"
if $gotoupstream; then
if ! $force; then
msg "Must also use -f (delete local changes) when using -u"
exit 1
fi
if $gotomaster; then
if $fetchupstream; then
verbose git fetch origin
verbose git remote prune origin
fi
verbose git checkout -f "$branch"
verbose git reset --hard origin/"$branch"
else
r=`git symbolic-ref HEAD`
r=${r#refs/heads/}
rem=`git config "branch.$r.remote" || $ECHO origin`
bra=`git config "branch.$r.merge" || $ECHO "$r"`
upstream="$rem/${bra#refs/heads/}"
if $fetchupstream; then
for t in `git tag -l "xonotic-v"*`; do
verbose git tag -d "$t"
done
verbose git fetch "$rem"
verbose git remote prune "$rem"
fi
if ! git rev-parse "$upstream" >/dev/null 2>&1; then
upstream="origin/$branch"
fi
verbose git reset --hard "$upstream"
fi
elif $gotomaster; then
if $force; then
verbose git checkout -f "$branch"
verbose git reset --hard
else
verbose git checkout "$branch"
fi
elif $force; then
verbose git reset --hard
fi
if $rmuntracked; then
case "$d" in
.)
verbose git clean -df || true
;;
*)
verbose git clean -xdf || true
;;
esac
fi
if $killbranches; then
git for-each-ref --format='%(refname)' refs/heads/ | while IFS= read -r B; do
if [ x"$B" != x"`git symbolic-ref HEAD`" ]; then
verbose git branch -D "${B#refs/heads/}"
fi
done
git rev-parse refs/heads/master >/dev/null 2>&1 || verbose git branch --track master origin/master || true
git rev-parse "refs/heads/$branch" >/dev/null 2>&1 || verbose git branch --track "$branch" origin/"$branch" || true
fi
checkself "$cmd" "$@"
}
allrepos ifrepoenabled 0 clean_
;;
help)
$ECHO " $SELF branch <branch>"
$ECHO " $SELF branch <remote> <branch> [<srcbranch>]"
$ECHO " $SELF checkout|switch <branch>"
$ECHO " $SELF checkout|switch <remote>/<branch>"
$ECHO " $SELF clean [-m] [-f | -fu | -fU] [-r] [-D]"
$ECHO " $SELF clean --reclone"
$ECHO " $SELF each|foreach [-k] command..."
$ECHO " $SELF fix_upstream_rebase"
$ECHO " $SELF keygen"
$ECHO " $SELF push|commit [-s]"
$ECHO " $SELF update|pull [-N] [-s | -h [-p] | -g [-p]] [-l de|nl|default]"
$ECHO " $SELF grep \"<regex>\""
handled=false
;;
grep)
for d in $repos; do
if verbose cd "$d0/$d"; then
git grep -In "$@" || true
cd "$d0"
fi
done
;;
*)
handled=false
;;
esac