git/git-sh-setup.sh
Junio C Hamano 785063e02b sh-setup: protect from exported IFS
Many scripted Porcelains rely on being able to split words at the
default $IFS characters, i.e. SP, HT and LF.  If the user exports a
non-default IFS to the environment, what they read from plumbing
commands such as ls-files that use HT to delimit fields may not be
split in the way we expect.

Protect outselves by resetting it, just like we do so against CDPATH
exported to the environment.

Noticed by Andrew Dranse <adranse@oanda.com>.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-08-08 14:36:33 -07:00

272 lines
4.9 KiB
Bash

#!/bin/sh
#
# This is included in commands that either have to be run from the toplevel
# of the repository, or with GIT_DIR environment variable properly.
# If the GIT_DIR does not look like the right correct git-repository,
# it dies.
# Having this variable in your environment would break scripts because
# 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 ;;
*)
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
usage() {
"$0" -h
exit 1
}
parseopt_extra=
[ -n "$OPTIONS_KEEPDASHDASH" ] &&
parseopt_extra="--keep-dashdash"
eval "$(
echo "$OPTIONS_SPEC" |
git rev-parse --parseopt $parseopt_extra -- "$@" ||
echo exit $?
)"
else
dashless=$(basename "$0" | sed -e 's/-/ /')
usage() {
die "Usage: $dashless $USAGE"
}
if [ -z "$LONG_USAGE" ]
then
LONG_USAGE="Usage: $dashless $USAGE"
else
LONG_USAGE="Usage: $dashless $USAGE
$LONG_USAGE"
fi
case "$1" in
-h)
echo "$LONG_USAGE"
exit
esac
fi
set_reflog_action() {
if [ -z "${GIT_REFLOG_ACTION:+set}" ]
then
GIT_REFLOG_ACTION="$*"
export GIT_REFLOG_ACTION
fi
}
git_editor() {
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 () {
git rev-parse --is-bare-repository
}
cd_to_toplevel () {
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
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
}
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"
}
# 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)
}
# 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"
then
GIT_DIR=$(git rev-parse --git-dir) || exit
if [ -z "$SUBDIRECTORY_OK" ]
then
test -z "$(git rev-parse --show-cdup)" || {
exit=$?
echo >&2 "You need to run this command from the toplevel of the working tree."
exit $exit
}
fi
test -n "$GIT_DIR" && GIT_DIR=$(cd "$GIT_DIR" && pwd) || {
echo >&2 "Unable to determine absolute path of git directory"
exit 1
}
: ${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 "$@"
}
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