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" 104exit 105esac 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() { 143if[-z"${GIT_REFLOG_ACTION:+set}"] 144then 145 GIT_REFLOG_ACTION="$*" 146export GIT_REFLOG_ACTION 147fi 148} 149 150git_editor() { 151iftest -z"${GIT_EDITOR:+set}" 152then 153 GIT_EDITOR="$(git var GIT_EDITOR)"||return $? 154fi 155 156eval"$GIT_EDITOR"'"$@"' 157} 158 159git_pager() { 160iftest -t1 161then 162 GIT_PAGER=$(git var GIT_PAGER) 163else 164 GIT_PAGER=cat 165fi 166for vardef in @@PAGER_ENV@@ 167do 168 var=${vardef%%=*} 169eval":\"\${$vardef}\"&& export$var" 170done 171 172eval"$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)&& 189cd"$cdup"|| { 190 gettextln "Cannot chdir to \$cdup, the toplevel of the working tree">&2 191exit1 192} 193} 194 195require_work_tree_exists () { 196iftest"z$(git rev-parse --is-bare-repository)"!= zfalse 197then 198 program_name=$0 199 die "$(gettext "fatal: \$program_name cannot be used without a working tree.")" 200fi 201} 202 203require_work_tree () { 204test"$(git rev-parse --is-inside-work-tree 2>/dev/null)"= true || { 205 program_name=$0 206 die "$(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 ||exit1 212 git update-index -q --ignore-submodules --refresh 213 err=0 214 215if! git diff-files --quiet --ignore-submodules 216then 217 action=$1 218case"$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;; 231esac 232 err=1 233fi 234 235if! git diff-index --cached --quiet --ignore-submodules HEAD -- 236then 237iftest$err=0 238then 239 action=$1 240case"$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;; 250esac 251else 252 gettextln "Additionally, your index contains uncommitted changes.">&2 253fi 254 err=1 255fi 256 257iftest$err=1 258then 259test -n"$2"&&echo"$2">&2 260exit1 261fi 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 () { 274whiletest$#-gt0 275do 276 lid=$1;shift 277 uid=$1;shift 278printf'%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 " 294done 295echo'/^$/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() { 316unset$(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. 328expr$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 336sort() { 337/usr/bin/sort"$@" 338} 339find() { 340/usr/bin/find"$@" 341} 342# git sees Windows-style pwd 343pwd() { 344builtin pwd -W 345} 346 is_absolute_path () { 347case"$1"in 348[/\\]* | [A-Za-z]:*) 349return0;; 350esac 351return1 352} 353;; 354*) 355 is_absolute_path () { 356case"$1"in 357/*) 358return0;; 359esac 360return1 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 368if[-z"$SUBDIRECTORY_OK"] 369then 370test -z"$(git rev-parse --show-cdup)"|| { 371exit=$? 372 gettextln "You need to run this command from the toplevel of the working tree.">&2 373exit$exit 374} 375fi 376test -n"$GIT_DIR"&& GIT_DIR=$(cd "$GIT_DIR" && pwd)|| { 377 gettextln "Unable to determine absolute path of git directory">&2 378exit1 379} 380:"${GIT_OBJECT_DIRECTORY="$(git rev-parse --git-path objects)"}" 381} 382 383iftest -z"$NONGIT_OK" 384then 385 git_dir_init 386fi 387 388peel_committish () { 389case"$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;; 397esac 398}