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# Having this variable in your environment would break scripts because 6# you would cause "cd" to be taken to unexpected places. If you 7# like CDPATH, define it for your interactive shell sessions without 8# exporting it. 9# But we protect ourselves from such a user mistake nevertheless. 10unset CDPATH 11 12# Similarly for IFS, but some shells (e.g. FreeBSD 7.2) are buggy and 13# do not equate an unset IFS with IFS with the default, so here is 14# an explicit SP HT LF. 15IFS=' 16' 17 18git_broken_path_fix () { 19 case ":$PATH:" in 20 *:$1:*) : ok ;; 21 *) 22 PATH=$( 23 SANE_TOOL_PATH="$1" 24 IFS=: path= sep= 25 set x $PATH 26 shift 27 for elem 28 do 29 case "$SANE_TOOL_PATH:$elem" in 30 (?*:/bin | ?*:/usr/bin) 31 path="$path$sep$SANE_TOOL_PATH" 32 sep=: 33 SANE_TOOL_PATH= 34 esac 35 path="$path$sep$elem" 36 sep=: 37 done 38 echo "$path" 39 ) 40 ;; 41 esac 42} 43 44# @@BROKEN_PATH_FIX@@ 45 46# Source git-sh-i18n for gettext support. 47. "$(git --exec-path)/git-sh-i18n" 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 for vardef in @@PAGER_ENV@@ 167 do 168 var=${vardef%%=*} 169 eval ": \"\${$vardef}\" && export $var" 170 done 171 172 eval "$GIT_PAGER" '"$@"' 173} 174 175sane_grep () { 176 GREP_OPTIONS= LC_ALL=C grep @@SANE_TEXT_GREP@@ "$@" 177} 178 179sane_egrep () { 180 GREP_OPTIONS= LC_ALL=C egrep @@SANE_TEXT_GREP@@ "$@" 181} 182 183is_bare_repository () { 184 git rev-parse --is-bare-repository 185} 186 187cd_to_toplevel () { 188 cdup=$(git rev-parse --show-toplevel) && 189 cd "$cdup" || { 190 gettextln "Cannot chdir to \$cdup, the toplevel of the working tree" >&2 191 exit 1 192 } 193} 194 195require_work_tree_exists () { 196 if test "z$(git rev-parse --is-bare-repository)" != zfalse 197 then 198 program_name=$0 199 die "$(eval_gettext "fatal: \$program_name cannot be used without a working tree.")" 200 fi 201} 202 203require_work_tree () { 204 test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true || { 205 program_name=$0 206 die "$(eval_gettext "fatal: \$program_name cannot be used without a working tree.")" 207 } 208} 209 210require_clean_work_tree () { 211 git rev-parse --verify HEAD >/dev/null || exit 1 212 git update-index -q --ignore-submodules --refresh 213 err=0 214 215 if ! git diff-files --quiet --ignore-submodules 216 then 217 action=$1 218 case "$action" in 219 rebase) 220 gettextln "Cannot rebase: You have unstaged changes." >&2 221 ;; 222 "rewrite branches") 223 gettextln "Cannot rewrite branches: You have unstaged changes." >&2 224 ;; 225 "pull with rebase") 226 gettextln "Cannot pull with rebase: You have unstaged changes." >&2 227 ;; 228 *) 229 eval_gettextln "Cannot \$action: You have unstaged changes." >&2 230 ;; 231 esac 232 err=1 233 fi 234 235 if ! git diff-index --cached --quiet --ignore-submodules HEAD -- 236 then 237 if test $err = 0 238 then 239 action=$1 240 case "$action" in 241 rebase) 242 gettextln "Cannot rebase: Your index contains uncommitted changes." >&2 243 ;; 244 "pull with rebase") 245 gettextln "Cannot pull with rebase: Your index contains uncommitted changes." >&2 246 ;; 247 *) 248 eval_gettextln "Cannot \$action: Your index contains uncommitted changes." >&2 249 ;; 250 esac 251 else 252 gettextln "Additionally, your index contains uncommitted changes." >&2 253 fi 254 err=1 255 fi 256 257 if test $err = 1 258 then 259 test -n "$2" && echo "$2" >&2 260 exit 1 261 fi 262} 263 264# Generate a sed script to parse identities from a commit. 265# 266# Reads the commit from stdin, which should be in raw format (e.g., from 267# cat-file or "--pretty=raw"). 268# 269# The first argument specifies the ident line to parse (e.g., "author"), and 270# the second specifies the environment variable to put it in (e.g., "AUTHOR" 271# for "GIT_AUTHOR_*"). Multiple pairs can be given to parse author and 272# committer. 273pick_ident_script () { 274 while test $# -gt 0 275 do 276 lid=$1; shift 277 uid=$1; shift 278 printf '%s' " 279 /^$lid /{ 280 s/'/'\\\\''/g 281 h 282 s/^$lid "'\([^<]*\) <[^>]*> .*$/\1/'" 283 s/.*/GIT_${uid}_NAME='&'/p 284 285 g 286 s/^$lid "'[^<]* <\([^>]*\)> .*$/\1/'" 287 s/.*/GIT_${uid}_EMAIL='&'/p 288 289 g 290 s/^$lid "'[^<]* <[^>]*> \(.*\)$/@\1/'" 291 s/.*/GIT_${uid}_DATE='&'/p 292 } 293 " 294 done 295 echo '/^$/q' 296} 297 298# Create a pick-script as above and feed it to sed. Stdout is suitable for 299# feeding to eval. 300parse_ident_from_commit () { 301 LANG=C LC_ALL=C sed -ne "$(pick_ident_script "$@")" 302} 303 304# Parse the author from a commit given as an argument. Stdout is suitable for 305# feeding to eval to set the usual GIT_* ident variables. 306get_author_ident_from_commit () { 307 encoding=$(git config i18n.commitencoding || echo UTF-8) 308 git show -s --pretty=raw --encoding="$encoding" "$1" -- | 309 parse_ident_from_commit author AUTHOR 310} 311 312# Clear repo-local GIT_* environment variables. Useful when switching to 313# another repository (e.g. when entering a submodule). See also the env 314# list in git_connect() 315clear_local_git_env() { 316 unset $(git rev-parse --local-env-vars) 317} 318 319# Generate a virtual base file for a two-file merge. Uses git apply to 320# remove lines from $1 that are not in $2, leaving only common lines. 321create_virtual_base() { 322 sz0=$(wc -c <"$1") 323 @@DIFF@@ -u -La/"$1" -Lb/"$1" "$1" "$2" | git apply --no-add 324 sz1=$(wc -c <"$1") 325 326 # If we do not have enough common material, it is not 327 # worth trying two-file merge using common subsections. 328 expr $sz0 \< $sz1 \* 2 >/dev/null || : >"$1" 329} 330 331 332# Platform specific tweaks to work around some commands 333case $(uname -s) in 334*MINGW*) 335 # Windows has its own (incompatible) sort and find 336 sort () { 337 /usr/bin/sort "$@" 338 } 339 find () { 340 /usr/bin/find "$@" 341 } 342 # git sees Windows-style pwd 343 pwd () { 344 builtin pwd -W 345 } 346 is_absolute_path () { 347 case "$1" in 348 [/\\]* | [A-Za-z]:*) 349 return 0 ;; 350 esac 351 return 1 352 } 353 ;; 354*) 355 is_absolute_path () { 356 case "$1" in 357 /*) 358 return 0 ;; 359 esac 360 return 1 361 } 362esac 363 364# Make sure we are in a valid repository of a vintage we understand, 365# if we require to be in a git repository. 366git_dir_init () { 367 GIT_DIR=$(git rev-parse --git-dir) || exit 368 if [ -z "$SUBDIRECTORY_OK" ] 369 then 370 test -z "$(git rev-parse --show-cdup)" || { 371 exit=$? 372 gettextln "You need to run this command from the toplevel of the working tree." >&2 373 exit $exit 374 } 375 fi 376 test -n "$GIT_DIR" && GIT_DIR=$(cd "$GIT_DIR" && pwd) || { 377 gettextln "Unable to determine absolute path of git directory" >&2 378 exit 1 379 } 380 : "${GIT_OBJECT_DIRECTORY="$(git rev-parse --git-path objects)"}" 381} 382 383if test -z "$NONGIT_OK" 384then 385 git_dir_init 386fi 387 388peel_committish () { 389 case "$1" in 390 :/*) 391 peeltmp=$(git rev-parse --verify "$1") && 392 git rev-parse --verify "${peeltmp}^0" 393 ;; 394 *) 395 git rev-parse --verify "${1}^0" 396 ;; 397 esac 398}