+fix_upstream_rebase()
+{
+ if [ -z "$r_me" ] || [ -z "$r_other" ]; then
+ return
+ 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()
+{
+ 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/*"
+ case ",`repoflags "$d"`," in
+ *,noautocrlf,*)
+ verbose git config --unset core.autocrlf || true
+ ;;
+ *)
+ verbose git config core.autocrlf input
+ ;;
+ esac
+ 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"
+}
+
+mkzip()
+{
+ archive=$1
+ shift
+ ziplist=`mktemp`
+ find "$@" -xtype f \( -executable -or -type l \) -print > "$ziplist"
+ 7za a -tzip -mx=9 -x@"$ziplist" "$archive" "$@" || true
+ zip -9y -@<"$ziplist" "$archive" || true
+ rm -f "$ziplist"
+}
+
+mkzip0()
+{
+ zip -0y "$@"
+}
+
+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
+ { 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*,,'
+ # unit: clock ticks (depends on what "time" returns
+}
+
+bestmirror()
+{
+ pre=$1; shift
+ suf=$1; shift
+
+ if ! { time -p true; } >/dev/null 2>&1; then
+ return 1
+ fi
+
+ bestin=
+ bestt=
+ for in in "$@"; do
+ m=$pre$in$suf
+ if t=`mirrorspeed "$m"`; then
+ msg "$m -> $t ticks"
+ if [ -n "$t" ]; then
+ if [ -z "$bestt" ] || [ "$t" -lt "$bestt" ]; then
+ bestin=$in
+ bestt=$t
+ fi
+ fi
+ else
+ msg "$m -> FAIL"
+ fi
+ done
+ if [ -n "$bestin" ]; then
+ msg "Best mirror seems to be $pre$bestin$suf"
+ $ECHO "$bestin"
+ else
+ return 1
+ fi
+}
+