mailmap: simplify map_user() interface
[gitweb.git] / git-sh-setup.sh
old mode 100755 (executable)
new mode 100644 (file)
index 8382339..22f0aed
@@ -9,11 +9,58 @@
 # you would cause "cd" to be taken to unexpected places.  If you
 # like CDPATH, define it for your interactive shell sessions without
 # exporting it.
+# But we protect ourselves from such a user mistake nevertheless.
 unset CDPATH
 
-die() {
-       echo >&2 "$@"
-       exit 1
+# Similarly for IFS
+unset IFS
+
+git_broken_path_fix () {
+       case ":$PATH:" in
+       *:$1:*) : ok ;;
+       *)
+               PATH=$(
+                       SANE_TOOL_PATH="$1"
+                       IFS=: path= sep=
+                       set x $PATH
+                       shift
+                       for elem
+                       do
+                               case "$SANE_TOOL_PATH:$elem" in
+                               (?*:/bin | ?*:/usr/bin)
+                                       path="$path$sep$SANE_TOOL_PATH"
+                                       sep=:
+                                       SANE_TOOL_PATH=
+                               esac
+                               path="$path$sep$elem"
+                               sep=:
+                       done
+                       echo "$path"
+               )
+               ;;
+       esac
+}
+
+# @@BROKEN_PATH_FIX@@
+
+die () {
+       die_with_status 1 "$@"
+}
+
+die_with_status () {
+       status=$1
+       shift
+       echo >&2 "$*"
+       exit "$status"
+}
+
+GIT_QUIET=
+
+say () {
+       if test -z "$GIT_QUIET"
+       then
+               printf '%s\n' "$*"
+       fi
 }
 
 if test -n "$OPTIONS_SPEC"; then
@@ -47,7 +94,7 @@ $LONG_USAGE"
        fi
 
        case "$1" in
-               -h|--h|--he|--hel|--help)
+               -h)
                echo "$LONG_USAGE"
                exit
        esac
@@ -62,19 +109,33 @@ set_reflog_action() {
 }
 
 git_editor() {
-       : "${GIT_EDITOR:=$(git config core.editor)}"
-       : "${GIT_EDITOR:=${VISUAL:-${EDITOR}}}"
-       case "$GIT_EDITOR,$TERM" in
-       ,dumb)
-               echo >&2 "No editor specified in GIT_EDITOR, core.editor, VISUAL,"
-               echo >&2 "or EDITOR. Tried to fall back to vi but terminal is dumb."
-               echo >&2 "Please set one of these variables to an appropriate"
-               echo >&2 "editor or run $0 with options that will not cause an"
-               echo >&2 "editor to be invoked (e.g., -m or -F for git-commit)."
-               exit 1
-               ;;
-       esac
-       eval "${GIT_EDITOR:=vi}" '"$@"'
+       if test -z "${GIT_EDITOR:+set}"
+       then
+               GIT_EDITOR="$(git var GIT_EDITOR)" || return $?
+       fi
+
+       eval "$GIT_EDITOR" '"$@"'
+}
+
+git_pager() {
+       if test -t 1
+       then
+               GIT_PAGER=$(git var GIT_PAGER)
+       else
+               GIT_PAGER=cat
+       fi
+       : ${LESS=-FRSX}
+       export LESS
+
+       eval "$GIT_PAGER" '"$@"'
+}
+
+sane_grep () {
+       GREP_OPTIONS= LC_ALL=C grep "$@"
+}
+
+sane_egrep () {
+       GREP_OPTIONS= LC_ALL=C egrep "$@"
 }
 
 is_bare_repository () {
@@ -82,54 +143,142 @@ is_bare_repository () {
 }
 
 cd_to_toplevel () {
-       cdup=$(git rev-parse --show-cdup)
-       if test ! -z "$cdup"
+       cdup=$(git rev-parse --show-toplevel) &&
+       cd "$cdup" || {
+               echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
+               exit 1
+       }
+}
+
+require_work_tree_exists () {
+       if test "z$(git rev-parse --is-bare-repository)" != zfalse
        then
-               # The "-P" option says to follow "physical" directory
-               # structure instead of following symbolic links.  When cdup is
-               # "../", this means following the ".." entry in the current
-               # directory instead textually removing a symlink path element
-               # from the PWD shell variable.  The "-P" behavior is more
-               # consistent with the C-style chdir used by most of Git.
-               cd -P "$cdup" || {
-                       echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
-                       exit 1
-               }
+               die "fatal: $0 cannot be used without a working tree."
        fi
 }
 
 require_work_tree () {
-       test $(git rev-parse --is-inside-work-tree) = true ||
+       test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true ||
        die "fatal: $0 cannot be used without a working tree."
 }
 
+require_clean_work_tree () {
+       git rev-parse --verify HEAD >/dev/null || exit 1
+       git update-index -q --ignore-submodules --refresh
+       err=0
+
+       if ! git diff-files --quiet --ignore-submodules
+       then
+               echo >&2 "Cannot $1: You have unstaged changes."
+               err=1
+       fi
+
+       if ! git diff-index --cached --quiet --ignore-submodules HEAD --
+       then
+               if [ $err = 0 ]
+               then
+                   echo >&2 "Cannot $1: Your index contains uncommitted changes."
+               else
+                   echo >&2 "Additionally, your index contains uncommitted changes."
+               fi
+               err=1
+       fi
+
+       if [ $err = 1 ]
+       then
+               test -n "$2" && echo >&2 "$2"
+               exit 1
+       fi
+}
+
+# Generate a sed script to parse identities from a commit.
+#
+# Reads the commit from stdin, which should be in raw format (e.g., from
+# cat-file or "--pretty=raw").
+#
+# The first argument specifies the ident line to parse (e.g., "author"), and
+# the second specifies the environment variable to put it in (e.g., "AUTHOR"
+# for "GIT_AUTHOR_*"). Multiple pairs can be given to parse author and
+# committer.
+pick_ident_script () {
+       while test $# -gt 0
+       do
+               lid=$1; shift
+               uid=$1; shift
+               printf '%s' "
+               /^$lid /{
+                       s/'/'\\\\''/g
+                       h
+                       s/^$lid "'\([^<]*\) <[^>]*> .*$/\1/'"
+                       s/.*/GIT_${uid}_NAME='&'/p
+
+                       g
+                       s/^$lid "'[^<]* <\([^>]*\)> .*$/\1/'"
+                       s/.*/GIT_${uid}_EMAIL='&'/p
+
+                       g
+                       s/^$lid "'[^<]* <[^>]*> \(.*\)$/@\1/'"
+                       s/.*/GIT_${uid}_DATE='&'/p
+               }
+               "
+       done
+       echo '/^$/q'
+}
+
+# Create a pick-script as above and feed it to sed. Stdout is suitable for
+# feeding to eval.
+parse_ident_from_commit () {
+       LANG=C LC_ALL=C sed -ne "$(pick_ident_script "$@")"
+}
+
+# Parse the author from a commit given as an argument. Stdout is suitable for
+# feeding to eval to set the usual GIT_* ident variables.
 get_author_ident_from_commit () {
-       pick_author_script='
-       /^author /{
-               s/'\''/'\''\\'\'\''/g
-               h
-               s/^author \([^<]*\) <[^>]*> .*$/\1/
-               s/'\''/'\''\'\'\''/g
-               s/.*/GIT_AUTHOR_NAME='\''&'\''/p
-
-               g
-               s/^author [^<]* <\([^>]*\)> .*$/\1/
-               s/'\''/'\''\'\'\''/g
-               s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
-
-               g
-               s/^author [^<]* <[^>]*> \(.*\)$/\1/
-               s/'\''/'\''\'\'\''/g
-               s/.*/GIT_AUTHOR_DATE='\''&'\''/p
-
-               q
-       }
-       '
        encoding=$(git config i18n.commitencoding || echo UTF-8)
        git show -s --pretty=raw --encoding="$encoding" "$1" -- |
-       LANG=C LC_ALL=C sed -ne "$pick_author_script"
+       parse_ident_from_commit author AUTHOR
+}
+
+# Clear repo-local GIT_* environment variables. Useful when switching to
+# another repository (e.g. when entering a submodule). See also the env
+# list in git_connect()
+clear_local_git_env() {
+       unset $(git rev-parse --local-env-vars)
 }
 
+
+# Platform specific tweaks to work around some commands
+case $(uname -s) in
+*MINGW*)
+       # Windows has its own (incompatible) sort and find
+       sort () {
+               /usr/bin/sort "$@"
+       }
+       find () {
+               /usr/bin/find "$@"
+       }
+       # git sees Windows-style pwd
+       pwd () {
+               builtin pwd -W
+       }
+       is_absolute_path () {
+               case "$1" in
+               [/\\]* | [A-Za-z]:*)
+                       return 0 ;;
+               esac
+               return 1
+       }
+       ;;
+*)
+       is_absolute_path () {
+               case "$1" in
+               /*)
+                       return 0 ;;
+               esac
+               return 1
+       }
+esac
+
 # Make sure we are in a valid repository of a vintage we understand,
 # if we require to be in a git repository.
 if test -z "$NONGIT_OK"
@@ -149,16 +298,3 @@ then
        }
        : ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
 fi
-
-# Fix some commands on Windows
-case $(uname -s) in
-*MINGW*)
-       # Windows has its own (incompatible) sort and find
-       sort () {
-               /usr/bin/sort "$@"
-       }
-       find () {
-               /usr/bin/find "$@"
-       }
-       ;;
-esac