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