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