mailmap: simplify map_user() interface
[gitweb.git] / git-sh-setup.sh
index 8d54b73d3208064829613499580bad541586c725..22f0aed6db366c3d4a291b3ae646c45002ff86c1 100644 (file)
@@ -9,8 +9,12 @@
 # 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
 
+# Similarly for IFS
+unset IFS
+
 git_broken_path_fix () {
        case ":$PATH:" in
        *:$1:*) : ok ;;
@@ -39,9 +43,15 @@ git_broken_path_fix () {
 
 # @@BROKEN_PATH_FIX@@
 
-die() {
-       echo >&2 "$@"
-       exit 1
+die () {
+       die_with_status 1 "$@"
+}
+
+die_with_status () {
+       status=$1
+       shift
+       echo >&2 "$*"
+       exit "$status"
 }
 
 GIT_QUIET=
@@ -84,7 +94,7 @@ $LONG_USAGE"
        fi
 
        case "$1" in
-               -h|--h|--he|--hel|--help)
+               -h)
                echo "$LONG_USAGE"
                exit
        esac
@@ -140,33 +150,93 @@ cd_to_toplevel () {
        }
 }
 
+require_work_tree_exists () {
+       if test "z$(git rev-parse --is-bare-repository)" != zfalse
+       then
+               die "fatal: $0 cannot be used without a working tree."
+       fi
+}
+
 require_work_tree () {
        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/.*/GIT_AUTHOR_NAME='\''&'\''/p
-
-               g
-               s/^author [^<]* <\([^>]*\)> .*$/\1/
-               s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
-
-               g
-               s/^author [^<]* <[^>]*> \(.*\)$/\1/
-               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
@@ -176,6 +246,39 @@ 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"
@@ -195,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