1# This shell scriplet is meant to be included by other shell scripts 2# to set up some variables pointing at the normal git directories and 3# a few helper shell functions. 4 5# Source git-sh-i18n for gettext support. 6. git-sh-i18n 7 8# Having this variable in your environment would break scripts because 9# you would cause "cd" to be taken to unexpected places. If you 10# like CDPATH, define it for your interactive shell sessions without 11# exporting it. 12# But we protect ourselves from such a user mistake nevertheless. 13unset CDPATH 14 15# Similarly for IFS, but some shells (e.g. FreeBSD 7.2) are buggy and 16# do not equate an unset IFS with IFS with the default, so here is 17# an explicit SP HT LF. 18IFS=' 19' 20 21git_broken_path_fix () { 22 case ":$PATH:" in 23 *:$1:*) : ok ;; 24 *) 25 PATH=$( 26 SANE_TOOL_PATH="$1" 27 IFS=: path= sep= 28 set x $PATH 29 shift 30 for elem 31 do 32 case "$SANE_TOOL_PATH:$elem" in 33 (?*:/bin | ?*:/usr/bin) 34 path="$path$sep$SANE_TOOL_PATH" 35 sep=: 36 SANE_TOOL_PATH= 37 esac 38 path="$path$sep$elem" 39 sep=: 40 done 41 echo "$path" 42 ) 43 ;; 44 esac 45} 46 47# @@BROKEN_PATH_FIX@@ 48 49die () { 50 die_with_status 1 "$@" 51} 52 53die_with_status () { 54 status=$1 55 shift 56 printf >&2 '%s\n' "$*" 57 exit "$status" 58} 59 60GIT_QUIET= 61 62say () { 63 if test -z "$GIT_QUIET" 64 then 65 printf '%s\n' "$*" 66 fi 67} 68 69if test -n "$OPTIONS_SPEC"; then 70 usage() { 71 "$0" -h 72 exit 1 73 } 74 75 parseopt_extra= 76 [ -n "$OPTIONS_KEEPDASHDASH" ] && 77 parseopt_extra="--keep-dashdash" 78 [ -n "$OPTIONS_STUCKLONG" ] && 79 parseopt_extra="$parseopt_extra --stuck-long" 80 81 eval "$( 82 echo "$OPTIONS_SPEC" | 83 git rev-parse --parseopt $parseopt_extra -- "$@" || 84 echo exit $? 85 )" 86else 87 dashless=$(basename -- "$0" | sed -e 's/-/ /') 88 usage() { 89 die "$(eval_gettext "usage: \$dashless \$USAGE")" 90 } 91 92 if [ -z "$LONG_USAGE" ] 93 then 94 LONG_USAGE="$(eval_gettext "usage: \$dashless \$USAGE")" 95 else 96 LONG_USAGE="$(eval_gettext "usage: \$dashless \$USAGE 97 98$LONG_USAGE")" 99 fi 100 101 case "$1" in 102 -h) 103 echo "$LONG_USAGE" 104 exit 105 esac 106fi 107 108# Set the name of the end-user facing command in the reflog when the 109# script may update refs. When GIT_REFLOG_ACTION is already set, this 110# will not overwrite it, so that a scripted Porcelain (e.g. "git 111# rebase") can set it to its own name (e.g. "rebase") and then call 112# another scripted Porcelain (e.g. "git am") and a call to this 113# function in the latter will keep the name of the end-user facing 114# program (e.g. "rebase") in GIT_REFLOG_ACTION, ensuring whatever it 115# does will be record as actions done as part of the end-user facing 116# operation (e.g. "rebase"). 117# 118# NOTE NOTE NOTE: consequently, after assigning a specific message to 119# GIT_REFLOG_ACTION when calling a "git" command to record a custom 120# reflog message, do not leave that custom value in GIT_REFLOG_ACTION, 121# after you are done. Other callers of "git" commands that rely on 122# writing the default "program name" in reflog expect the variable to 123# contain the value set by this function. 124# 125# To use a custom reflog message, do either one of these three: 126# 127# (a) use a single-shot export form: 128# GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: preparing frotz" \ 129# git command-that-updates-a-ref 130# 131# (b) save the original away and restore: 132# SAVED_ACTION=$GIT_REFLOG_ACTION 133# GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: preparing frotz" 134# git command-that-updates-a-ref 135# GIT_REFLOG_ACITON=$SAVED_ACTION 136# 137# (c) assign the variable in a subshell: 138# ( 139# GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: preparing frotz" 140# git command-that-updates-a-ref 141# ) 142set_reflog_action() { 143 if [ -z "${GIT_REFLOG_ACTION:+set}" ] 144 then 145 GIT_REFLOG_ACTION="$*" 146 export GIT_REFLOG_ACTION 147 fi 148} 149 150git_editor() { 151 if test -z "${GIT_EDITOR:+set}" 152 then 153 GIT_EDITOR="$(git var GIT_EDITOR)" || return $? 154 fi 155 156 eval "$GIT_EDITOR" '"$@"' 157} 158 159git_pager() { 160 if test -t 1 161 then 162 GIT_PAGER=$(git var GIT_PAGER) 163 else 164 GIT_PAGER=cat 165 fi 166 : ${LESS=-FRX} 167 : ${LV=-c} 168 export LESS LV 169 170 eval "$GIT_PAGER" '"$@"' 171} 172 173sane_grep () { 174 GREP_OPTIONS= LC_ALL=C grep @@SANE_TEXT_GREP@@ "$@" 175} 176 177sane_egrep () { 178 GREP_OPTIONS= LC_ALL=C egrep @@SANE_TEXT_GREP@@ "$@" 179} 180 181is_bare_repository () { 182 git rev-parse --is-bare-repository 183} 184 185cd_to_toplevel () { 186 cdup=$(git rev-parse --show-toplevel) && 187 cd "$cdup" || { 188 gettextln "Cannot chdir to \$cdup, the toplevel of the working tree" >&2 189 exit 1 190 } 191} 192 193require_work_tree_exists () { 194 if test "z$(git rev-parse --is-bare-repository)" != zfalse 195 then 196 program_name=$0 197 die "$(gettext "fatal: \$program_name cannot be used without a working tree.")" 198 fi 199} 200 201require_work_tree () { 202 test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true || { 203 program_name=$0 204 die "$(gettext "fatal: \$program_name cannot be used without a working tree.")" 205 } 206} 207 208require_clean_work_tree () { 209 git rev-parse --verify HEAD >/dev/null || exit 1 210 git update-index -q --ignore-submodules --refresh 211 err=0 212 213 if ! git diff-files --quiet --ignore-submodules 214 then 215 action=$1 216 case "$action" in 217 rebase) 218 gettextln "Cannot rebase: You have unstaged changes." >&2 219 ;; 220 "rewrite branches") 221 gettextln "Cannot rewrite branches: You have unstaged changes." >&2 222 ;; 223 "pull with rebase") 224 gettextln "Cannot pull with rebase: You have unstaged changes." >&2 225 ;; 226 *) 227 eval_gettextln "Cannot \$action: You have unstaged changes." >&2 228 ;; 229 esac 230 err=1 231 fi 232 233 if ! git diff-index --cached --quiet --ignore-submodules HEAD -- 234 then 235 if test $err = 0 236 then 237 action=$1 238 case "$action" in 239 rebase) 240 gettextln "Cannot rebase: Your index contains uncommitted changes." >&2 241 ;; 242 "pull with rebase") 243 gettextln "Cannot pull with rebase: Your index contains uncommitted changes." >&2 244 ;; 245 *) 246 eval_gettextln "Cannot \$action: Your index contains uncommitted changes." >&2 247 ;; 248 esac 249 else 250 gettextln "Additionally, your index contains uncommitted changes." >&2 251 fi 252 err=1 253 fi 254 255 if test $err = 1 256 then 257 test -n "$2" && echo "$2" >&2 258 exit 1 259 fi 260} 261 262# Generate a sed script to parse identities from a commit. 263# 264# Reads the commit from stdin, which should be in raw format (e.g., from 265# cat-file or "--pretty=raw"). 266# 267# The first argument specifies the ident line to parse (e.g., "author"), and 268# the second specifies the environment variable to put it in (e.g., "AUTHOR" 269# for "GIT_AUTHOR_*"). Multiple pairs can be given to parse author and 270# committer. 271pick_ident_script () { 272 while test $# -gt 0 273 do 274 lid=$1; shift 275 uid=$1; shift 276 printf '%s' " 277 /^$lid /{ 278 s/'/'\\\\''/g 279 h 280 s/^$lid "'\([^<]*\) <[^>]*> .*$/\1/'" 281 s/.*/GIT_${uid}_NAME='&'/p 282 283 g 284 s/^$lid "'[^<]* <\([^>]*\)> .*$/\1/'" 285 s/.*/GIT_${uid}_EMAIL='&'/p 286 287 g 288 s/^$lid "'[^<]* <[^>]*> \(.*\)$/@\1/'" 289 s/.*/GIT_${uid}_DATE='&'/p 290 } 291 " 292 done 293 echo '/^$/q' 294} 295 296# Create a pick-script as above and feed it to sed. Stdout is suitable for 297# feeding to eval. 298parse_ident_from_commit () { 299 LANG=C LC_ALL=C sed -ne "$(pick_ident_script "$@")" 300} 301 302# Parse the author from a commit given as an argument. Stdout is suitable for 303# feeding to eval to set the usual GIT_* ident variables. 304get_author_ident_from_commit () { 305 encoding=$(git config i18n.commitencoding || echo UTF-8) 306 git show -s --pretty=raw --encoding="$encoding" "$1" -- | 307 parse_ident_from_commit author AUTHOR 308} 309 310# Clear repo-local GIT_* environment variables. Useful when switching to 311# another repository (e.g. when entering a submodule). See also the env 312# list in git_connect() 313clear_local_git_env() { 314 unset $(git rev-parse --local-env-vars) 315} 316 317# Generate a virtual base file for a two-file merge. Uses git apply to 318# remove lines from $1 that are not in $2, leaving only common lines. 319create_virtual_base() { 320 sz0=$(wc -c <"$1") 321 @@DIFF@@ -u -La/"$1" -Lb/"$1" "$1" "$2" | git apply --no-add 322 sz1=$(wc -c <"$1") 323 324 # If we do not have enough common material, it is not 325 # worth trying two-file merge using common subsections. 326 expr $sz0 \< $sz1 \* 2 >/dev/null || : >"$1" 327} 328 329 330# Platform specific tweaks to work around some commands 331case $(uname -s) in 332*MINGW*) 333 # Windows has its own (incompatible) sort and find 334 sort () { 335 /usr/bin/sort "$@" 336 } 337 find () { 338 /usr/bin/find "$@" 339 } 340 # git sees Windows-style pwd 341 pwd () { 342 builtin pwd -W 343 } 344 is_absolute_path () { 345 case "$1" in 346 [/\\]* | [A-Za-z]:*) 347 return 0 ;; 348 esac 349 return 1 350 } 351 ;; 352*) 353 is_absolute_path () { 354 case "$1" in 355 /*) 356 return 0 ;; 357 esac 358 return 1 359 } 360esac 361 362# Make sure we are in a valid repository of a vintage we understand, 363# if we require to be in a git repository. 364git_dir_init () { 365 GIT_DIR=$(git rev-parse --git-dir) || exit 366 if [ -z "$SUBDIRECTORY_OK" ] 367 then 368 test -z "$(git rev-parse --show-cdup)" || { 369 exit=$? 370 gettextln "You need to run this command from the toplevel of the working tree." >&2 371 exit $exit 372 } 373 fi 374 test -n "$GIT_DIR" && GIT_DIR=$(cd "$GIT_DIR" && pwd) || { 375 gettextln "Unable to determine absolute path of git directory" >&2 376 exit 1 377 } 378 : ${GIT_OBJECT_DIRECTORY="$(git rev-parse --git-path objects)"} 379} 380 381if test -z "$NONGIT_OK" 382then 383 git_dir_init 384fi 385 386peel_committish () { 387 case "$1" in 388 :/*) 389 peeltmp=$(git rev-parse --verify "$1") && 390 git rev-parse --verify "${peeltmp}^0" 391 ;; 392 *) 393 git rev-parse --verify "${1}^0" 394 ;; 395 esac 396}