772 lines
24 KiB
Bash
772 lines
24 KiB
Bash
|
#!/usr/bin/env bash
|
|||
|
|
|||
|
# bash/zsh cross compatibility notes:
|
|||
|
# - always use ${array[@]:offset:length} syntax for array indexing
|
|||
|
|
|||
|
function async_run() {
|
|||
|
{
|
|||
|
eval "$@" &> /dev/null
|
|||
|
}&
|
|||
|
}
|
|||
|
|
|||
|
function async_run_zsh() {
|
|||
|
{
|
|||
|
eval "$@" &> /dev/null
|
|||
|
|
|||
|
# `true` is used here to allow bash to parse the script, as the zsh `&!` syntax will otherwise stop parsing prior to any execution.
|
|||
|
}&! true
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function set_git_prompt_dir() {
|
|||
|
# code thanks to http://stackoverflow.com/questions/59895
|
|||
|
if [ -z "$__GIT_PROMPT_DIR" ]; then
|
|||
|
__GIT_PROMPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function echoc() {
|
|||
|
echo -e "${1}${2}${ResetColor}" | sed 's/\\\]//g' | sed 's/\\\[//g'
|
|||
|
}
|
|||
|
|
|||
|
function get_theme() {
|
|||
|
local CUSTOM_THEME_FILE="${HOME}/.git-prompt-colors.sh"
|
|||
|
if [[ ! (-z "${GIT_PROMPT_THEME_FILE:+x}" ) ]]; then
|
|||
|
CUSTOM_THEME_FILE="${GIT_PROMPT_THEME_FILE}"
|
|||
|
fi
|
|||
|
local DEFAULT_THEME_FILE="${__GIT_PROMPT_DIR}/themes/default.bgptheme"
|
|||
|
|
|||
|
if [[ -z "${GIT_PROMPT_THEME+x}" ]]; then
|
|||
|
if [[ -r "${CUSTOM_THEME_FILE}" ]]; then
|
|||
|
GIT_PROMPT_THEME="Custom"
|
|||
|
__GIT_PROMPT_THEME_FILE="${CUSTOM_THEME_FILE}"
|
|||
|
else
|
|||
|
GIT_PROMPT_THEME="default"
|
|||
|
__GIT_PROMPT_THEME_FILE="${DEFAULT_THEME_FILE}"
|
|||
|
fi
|
|||
|
else
|
|||
|
if [[ "${GIT_PROMPT_THEME}" = "Custom" ]]; then
|
|||
|
GIT_PROMPT_THEME="Custom"
|
|||
|
__GIT_PROMPT_THEME_FILE="${CUSTOM_THEME_FILE}"
|
|||
|
|
|||
|
if [[ ! (-r "${__GIT_PROMPT_THEME_FILE}") ]]; then
|
|||
|
GIT_PROMPT_THEME="default"
|
|||
|
__GIT_PROMPT_THEME_FILE="${DEFAULT_THEME_FILE}"
|
|||
|
fi
|
|||
|
else
|
|||
|
local theme=""
|
|||
|
|
|||
|
# use default theme, if theme was not found
|
|||
|
for themefile in "${__GIT_PROMPT_DIR}/themes/"*.bgptheme; do
|
|||
|
local basename=${themefile##*/}
|
|||
|
if [[ "${basename%.bgptheme}" = "${GIT_PROMPT_THEME}" ]]; then
|
|||
|
theme="${GIT_PROMPT_THEME}"
|
|||
|
break
|
|||
|
fi
|
|||
|
done
|
|||
|
|
|||
|
if [[ "${theme}" = "" ]]; then
|
|||
|
GIT_PROMPT_THEME="default"
|
|||
|
fi
|
|||
|
|
|||
|
__GIT_PROMPT_THEME_FILE="${__GIT_PROMPT_DIR}/themes/${GIT_PROMPT_THEME}.bgptheme"
|
|||
|
fi
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function git_prompt_load_colors() {
|
|||
|
if gp_set_file_var __PROMPT_COLORS_FILE prompt-colors.sh ; then
|
|||
|
# outsource the color defs
|
|||
|
source "${__PROMPT_COLORS_FILE}"
|
|||
|
else
|
|||
|
echo 1>&2 "Cannot find prompt-colors.sh!"
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function git_prompt_load_theme() {
|
|||
|
get_theme
|
|||
|
local DEFAULT_THEME_FILE="${__GIT_PROMPT_DIR}/themes/default.bgptheme"
|
|||
|
source "${DEFAULT_THEME_FILE}"
|
|||
|
source "${__GIT_PROMPT_THEME_FILE}"
|
|||
|
}
|
|||
|
|
|||
|
function git_prompt_list_themes() {
|
|||
|
git_prompt_load_colors
|
|||
|
get_theme
|
|||
|
|
|||
|
for themefile in "${__GIT_PROMPT_DIR}/themes/"*.bgptheme; do
|
|||
|
local basename="${themefile##*/}"
|
|||
|
local theme="${basename%.bgptheme}"
|
|||
|
if [[ "${GIT_PROMPT_THEME}" = "${theme}" ]]; then
|
|||
|
echoc "${Red}" "*${theme}"
|
|||
|
else
|
|||
|
echo "${theme}"
|
|||
|
fi
|
|||
|
done
|
|||
|
|
|||
|
# if [[ "${GIT_PROMPT_THEME}" = "Custom" ]]; then
|
|||
|
# echoc "${Magenta}" "*Custom"
|
|||
|
# else
|
|||
|
# echoc "${Blue}" "Custom"
|
|||
|
# fi
|
|||
|
}
|
|||
|
|
|||
|
# function git_prompt_make_custom_theme() {
|
|||
|
# if [[ -r "${HOME}/.git-prompt-colors.sh" ]]; then
|
|||
|
# echoc "${Red}" "You have already created a custom theme!"
|
|||
|
# else
|
|||
|
# local base="Default"
|
|||
|
# if [[ -n "${1}" && -r "${__GIT_PROMPT_DIR}/themes/${1}.bgptheme" ]]; then
|
|||
|
# base="${1}"
|
|||
|
# echoc "${Green}" "Using theme ${Magenta}\"${base}\"${Green} as base theme!"
|
|||
|
# else
|
|||
|
# echoc "${Green}" "Using theme ${Magenta}\"Default\"${Green} as base theme!"
|
|||
|
# fi
|
|||
|
#
|
|||
|
# if [[ "${base}" = "Custom" ]]; then
|
|||
|
# echoc "${Red}" "You cannot use the custom theme as base"
|
|||
|
# else
|
|||
|
# echoc "${Green}" "Creating new custom theme in \"${HOME}/.git-prompt-colors.sh\""
|
|||
|
# echoc "${DimYellow}" "Please add ${Magenta}\"GIT_PROMPT_THEME=Custom\"${DimYellow} to your .bashrc to use this theme"
|
|||
|
# if [[ "${base}" == "Default" ]]; then
|
|||
|
# cp "${__GIT_PROMPT_DIR}/themes/Custom.bgptemplate" "${HOME}/.git-prompt-colors.sh"
|
|||
|
# else
|
|||
|
# cp "${__GIT_PROMPT_DIR}/themes/${base}.bgptheme" "${HOME}/.git-prompt-colors.sh"
|
|||
|
# fi
|
|||
|
# fi
|
|||
|
# fi
|
|||
|
# }
|
|||
|
|
|||
|
# gp_set_file_var ENVAR SOMEFILE
|
|||
|
#
|
|||
|
# If ENVAR is set, check that it's value exists as a readable file. Otherwise,
|
|||
|
# Set ENVAR to the path to SOMEFILE, based on $HOME, $__GIT_PROMPT_DIR, and the
|
|||
|
# directory of the current script. The SOMEFILE can be prefixed with '.', or
|
|||
|
# not.
|
|||
|
#
|
|||
|
# Return 0 (success) if ENVAR not already defined, 1 (failure) otherwise.
|
|||
|
|
|||
|
function gp_set_file_var() {
|
|||
|
local envar="${1}"
|
|||
|
local file="${2}"
|
|||
|
if eval "[[ -n \"\${${envar}+x}\" && -r \"\${${envar}+x}\" ]]" ; then # is envar set to a readable file?
|
|||
|
local basefile
|
|||
|
eval "basefile=\"\`basename \\\"\${${envar}}\\\"\`\"" # assign basefile
|
|||
|
if [[ "${basefile}" = "${file}" || "${basefile}" = ".${file}" ]]; then
|
|||
|
return 0
|
|||
|
fi
|
|||
|
else # envar is not set, or it's set to a different file than requested
|
|||
|
eval "${envar}=" # set empty envar
|
|||
|
gp_maybe_set_envar_to_path "${envar}" "${HOME}/.${file}" "${HOME}/${file}" "${HOME}/lib/${file}" && return 0
|
|||
|
gp_maybe_set_envar_to_path "${envar}" "${__GIT_PROMPT_DIR}/${file}" "${0##*/}/${file}" && return 0
|
|||
|
fi
|
|||
|
return 1
|
|||
|
}
|
|||
|
|
|||
|
# gp_maybe_set_envar_to_path ENVAR FILEPATH ...
|
|||
|
#
|
|||
|
# return 0 (true) if any FILEPATH is readable, set ENVAR to it
|
|||
|
# return 1 (false) if not
|
|||
|
|
|||
|
function gp_maybe_set_envar_to_path() {
|
|||
|
local envar="${1}"
|
|||
|
shift
|
|||
|
local file
|
|||
|
for file in "${@}" ; do
|
|||
|
if [[ -r "${file}" ]]; then
|
|||
|
eval "${envar}=\"${file}\""
|
|||
|
return 0
|
|||
|
fi
|
|||
|
done
|
|||
|
return 1
|
|||
|
}
|
|||
|
|
|||
|
# git_prompt_reset
|
|||
|
#
|
|||
|
# unsets selected GIT_PROMPT variables, causing the next prompt callback to
|
|||
|
# recalculate them from scratch.
|
|||
|
|
|||
|
git_prompt_reset() {
|
|||
|
local var
|
|||
|
for var in GIT_PROMPT_DIR __GIT_PROMPT_COLORS_FILE __PROMPT_COLORS_FILE __GIT_STATUS_CMD GIT_PROMPT_THEME_NAME; do
|
|||
|
unset ${var}
|
|||
|
done
|
|||
|
}
|
|||
|
|
|||
|
# gp_format_exit_status RETVAL
|
|||
|
#
|
|||
|
# echos the symbolic signal name represented by RETVAL if the process was
|
|||
|
# signalled, otherwise echos the original value of RETVAL
|
|||
|
|
|||
|
gp_format_exit_status() {
|
|||
|
local RETVAL="${1}"
|
|||
|
local SIGNAL
|
|||
|
# Suppress STDERR in case RETVAL is not an integer (in such cases, RETVAL
|
|||
|
# is echoed verbatim)
|
|||
|
if [[ "${RETVAL}" -gt 128 ]] 2>/dev/null; then
|
|||
|
SIGNAL=$(( RETVAL - 128 ))
|
|||
|
kill -l "${SIGNAL}" 2>/dev/null || echo "${RETVAL}"
|
|||
|
else
|
|||
|
echo "${RETVAL}"
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function gp_format_username_repo() {
|
|||
|
git config --get remote.origin.url | sed 's|^.*//||; s/.*@//; s/[^:/]\+[:/]//; s/.git$//'
|
|||
|
}
|
|||
|
|
|||
|
function git_prompt_config() {
|
|||
|
#Checking if root to change output
|
|||
|
_isroot=false
|
|||
|
[[ "${UID}" -eq 0 ]] && _isroot=true
|
|||
|
|
|||
|
# There are two files related to colors:
|
|||
|
#
|
|||
|
# prompt-colors.sh -- sets generic color names suitable for bash 'PS1' prompt
|
|||
|
# git-prompt-colors.sh -- sets the GIT_PROMPT color scheme, using names from prompt-colors.sh
|
|||
|
git_prompt_load_colors
|
|||
|
|
|||
|
# source the user's ~/.git-prompt-colors.sh file, or the one that should be
|
|||
|
# sitting in the same directory as this script
|
|||
|
git_prompt_load_theme
|
|||
|
|
|||
|
if is_function prompt_callback; then
|
|||
|
prompt_callback="prompt_callback"
|
|||
|
else
|
|||
|
prompt_callback="prompt_callback_default"
|
|||
|
fi
|
|||
|
|
|||
|
if [[ "${GIT_PROMPT_LAST_COMMAND_STATE:-0}" = 0 ]]; then
|
|||
|
LAST_COMMAND_INDICATOR="${GIT_PROMPT_COMMAND_OK}";
|
|||
|
else
|
|||
|
LAST_COMMAND_INDICATOR="${GIT_PROMPT_COMMAND_FAIL}";
|
|||
|
fi
|
|||
|
|
|||
|
# replace _LAST_COMMAND_STATE_ token with the actual state
|
|||
|
GIT_PROMPT_LAST_COMMAND_STATE=$(gp_format_exit_status "${GIT_PROMPT_LAST_COMMAND_STATE}")
|
|||
|
LAST_COMMAND_INDICATOR="${LAST_COMMAND_INDICATOR//_LAST_COMMAND_STATE_/${GIT_PROMPT_LAST_COMMAND_STATE}}"
|
|||
|
|
|||
|
# Do this only once to define PROMPT_START and PROMPT_END
|
|||
|
|
|||
|
if [[ -z "${PROMPT_START:+x}" || -z "${PROMPT_END:+x}" ]]; then
|
|||
|
|
|||
|
if [[ -z "${GIT_PROMPT_START:+x}" ]] ; then
|
|||
|
if ${_isroot}; then
|
|||
|
PROMPT_START="${GIT_PROMPT_START_ROOT-}"
|
|||
|
else
|
|||
|
PROMPT_START="${GIT_PROMPT_START_USER-}"
|
|||
|
fi
|
|||
|
else
|
|||
|
PROMPT_START="${GIT_PROMPT_START-}"
|
|||
|
fi
|
|||
|
|
|||
|
if [[ -z "${GIT_PROMPT_END:+x}" ]] ; then
|
|||
|
if $_isroot; then
|
|||
|
PROMPT_END="${GIT_PROMPT_END_ROOT-}"
|
|||
|
else
|
|||
|
PROMPT_END="${GIT_PROMPT_END_USER-}"
|
|||
|
fi
|
|||
|
else
|
|||
|
PROMPT_END="${GIT_PROMPT_END-}"
|
|||
|
fi
|
|||
|
fi
|
|||
|
|
|||
|
# set GIT_PROMPT_LEADING_SPACE to 0 if you want to have no leading space in front of the GIT prompt
|
|||
|
if [[ "${GIT_PROMPT_LEADING_SPACE:-1}" = "0" ]]; then
|
|||
|
PROMPT_LEADING_SPACE=""
|
|||
|
else
|
|||
|
PROMPT_LEADING_SPACE=" "
|
|||
|
fi
|
|||
|
|
|||
|
if [[ "${GIT_PROMPT_ONLY_IN_REPO:-0}" == 1 ]]; then
|
|||
|
EMPTY_PROMPT="${OLD_GITPROMPT}"
|
|||
|
elif [[ "${GIT_PROMPT_WITH_VIRTUAL_ENV:-1}" == 1 ]]; then
|
|||
|
if [[ "${GIT_PROMPT_VIRTUAL_ENV_AFTER_PROMPT:-0}" == "0" ]]; then
|
|||
|
local ps="$(gp_add_virtualenv_to_prompt)${PROMPT_START}$(${prompt_callback})${PROMPT_END}"
|
|||
|
else
|
|||
|
local ps="${PROMPT_START}$(${prompt_callback})$(gp_add_virtualenv_to_prompt)${PROMPT_END}"
|
|||
|
fi
|
|||
|
EMPTY_PROMPT="${ps//_LAST_COMMAND_INDICATOR_/${LAST_COMMAND_INDICATOR}}"
|
|||
|
else
|
|||
|
local ps="${PROMPT_START}$(${prompt_callback})${PROMPT_END}"
|
|||
|
EMPTY_PROMPT="${ps//_LAST_COMMAND_INDICATOR_/${LAST_COMMAND_INDICATOR}}"
|
|||
|
fi
|
|||
|
|
|||
|
# fetch remote revisions every other $GIT_PROMPT_FETCH_TIMEOUT (default 5) minutes
|
|||
|
if [[ -z "${GIT_PROMPT_FETCH_TIMEOUT:+x}" ]]; then
|
|||
|
GIT_PROMPT_FETCH_TIMEOUT="5"
|
|||
|
fi
|
|||
|
if [[ -z "${__GIT_STATUS_CMD:+x}" ]] ; then # if GIT_STATUS_CMD not defined..
|
|||
|
if ! gp_maybe_set_envar_to_path __GIT_STATUS_CMD "${__GIT_PROMPT_DIR}/${GIT_PROMPT_STATUS_COMMAND}" ; then
|
|||
|
echo 1>&2 "Cannot find ${GIT_PROMPT_STATUS_COMMAND}!"
|
|||
|
fi
|
|||
|
# __GIT_STATUS_CMD defined
|
|||
|
fi
|
|||
|
unset GIT_BRANCH
|
|||
|
}
|
|||
|
|
|||
|
function setLastCommandState() {
|
|||
|
GIT_PROMPT_LAST_COMMAND_STATE="${?}"
|
|||
|
return ${GIT_PROMPT_LAST_COMMAND_STATE}
|
|||
|
}
|
|||
|
|
|||
|
function we_are_on_repo() {
|
|||
|
if [[ -e "$(git rev-parse --git-dir 2> /dev/null)" ]]; then
|
|||
|
echo 1
|
|||
|
else
|
|||
|
echo 0
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function update_old_git_prompt() {
|
|||
|
if [[ "${GIT_PROMPT_OLD_DIR_WAS_GIT:-0}" = 0 ]]; then
|
|||
|
OLD_PROMPT_START="${PROMPT_START}"
|
|||
|
OLD_PROMPT_END="${PROMPT_END}"
|
|||
|
OLD_GITPROMPT="${PS1}"
|
|||
|
fi
|
|||
|
|
|||
|
GIT_PROMPT_OLD_DIR_WAS_GIT=$(we_are_on_repo)
|
|||
|
}
|
|||
|
|
|||
|
function setGitPrompt() {
|
|||
|
update_old_git_prompt
|
|||
|
|
|||
|
local repo=$(git rev-parse --show-toplevel 2> /dev/null)
|
|||
|
if [[ ! -e "${repo}" ]] && [[ "${GIT_PROMPT_ONLY_IN_REPO-}" = 1 ]]; then
|
|||
|
# we do not permit bash-git-prompt outside git repos, so nothing to do
|
|||
|
PROMPT_START=${OLD_PROMPT_START}
|
|||
|
PROMPT_END=${OLD_PROMPT_END}
|
|||
|
PS1="${OLD_GITPROMPT}"
|
|||
|
return
|
|||
|
fi
|
|||
|
|
|||
|
local EMPTY_PROMPT
|
|||
|
local __GIT_STATUS_CMD
|
|||
|
|
|||
|
git_prompt_config
|
|||
|
|
|||
|
if [[ ! -e "${repo}" ]] || [[ "${GIT_PROMPT_DISABLE-}" = 1 ]]; then
|
|||
|
PS1="${EMPTY_PROMPT}"
|
|||
|
return
|
|||
|
fi
|
|||
|
|
|||
|
local FETCH_REMOTE_STATUS=1
|
|||
|
if [[ "${GIT_PROMPT_FETCH_REMOTE_STATUS}" = 0 ]]; then
|
|||
|
FETCH_REMOTE_STATUS=0
|
|||
|
fi
|
|||
|
|
|||
|
unset GIT_PROMPT_IGNORE
|
|||
|
OLD_GIT_PROMPT_SHOW_UNTRACKED_FILES="${GIT_PROMPT_SHOW_UNTRACKED_FILES}"
|
|||
|
unset GIT_PROMPT_SHOW_UNTRACKED_FILES
|
|||
|
|
|||
|
OLD_GIT_PROMPT_IGNORE_SUBMODULES="${GIT_PROMPT_IGNORE_SUBMODULES}"
|
|||
|
unset GIT_PROMPT_IGNORE_SUBMODULES
|
|||
|
|
|||
|
OLD_GIT_PROMPT_SHOW_TRACKING=${GIT_PROMPT_SHOW_TRACKING}
|
|||
|
unset GIT_PROMPT_SHOW_TRACKING
|
|||
|
|
|||
|
if [[ -e "${repo}/.bash-git-rc" ]]; then
|
|||
|
# The config file can only contain variable declarations on the form A_B=0 or G_P=all
|
|||
|
local CONFIG_SYNTAX="^(FETCH_REMOTE_STATUS|GIT_PROMPT_SHOW_UNTRACKED_FILES|GIT_PROMPT_IGNORE_SUBMODULES|GIT_PROMPT_SHOW_TRACKING|GIT_PROMPT_IGNORE)=[0-9a-z]+$"
|
|||
|
if grep -q -v -E "${CONFIG_SYNTAX}" "${repo}/.bash-git-rc"; then
|
|||
|
echo ".bash-git-rc can only contain variable values on the form NAME=value. Ignoring file." >&2
|
|||
|
else
|
|||
|
source "${repo}/.bash-git-rc"
|
|||
|
fi
|
|||
|
fi
|
|||
|
|
|||
|
if [[ -z "${GIT_PROMPT_SHOW_UNTRACKED_FILES+x}" ]]; then
|
|||
|
GIT_PROMPT_SHOW_UNTRACKED_FILES="${OLD_GIT_PROMPT_SHOW_UNTRACKED_FILES}"
|
|||
|
fi
|
|||
|
unset OLD_GIT_PROMPT_SHOW_UNTRACKED_FILES
|
|||
|
|
|||
|
if [[ -z "${GIT_PROMPT_IGNORE_SUBMODULES+x}" ]]; then
|
|||
|
GIT_PROMPT_IGNORE_SUBMODULES="${OLD_GIT_PROMPT_IGNORE_SUBMODULES}"
|
|||
|
fi
|
|||
|
unset OLD_GIT_PROMPT_IGNORE_SUBMODULES
|
|||
|
|
|||
|
if [[ -z "${GIT_PROMPT_SHOW_TRACKING+x}" ]]; then
|
|||
|
GIT_PROMPT_SHOW_TRACKING=${OLD_GIT_PROMPT_SHOW_TRACKING}
|
|||
|
fi
|
|||
|
unset OLD_GIT_PROMPT_SHOW_TRACKING
|
|||
|
|
|||
|
if [[ "${GIT_PROMPT_IGNORE-}" = 1 ]]; then
|
|||
|
PS1="${EMPTY_PROMPT}"
|
|||
|
return
|
|||
|
fi
|
|||
|
|
|||
|
if [[ "${FETCH_REMOTE_STATUS}" = 1 ]]; then
|
|||
|
checkUpstream
|
|||
|
fi
|
|||
|
|
|||
|
updatePrompt
|
|||
|
}
|
|||
|
|
|||
|
# some versions of find do not have -mmin
|
|||
|
_have_find_mmin=1
|
|||
|
|
|||
|
function olderThanMinutes() {
|
|||
|
local matches
|
|||
|
local find_exit_code
|
|||
|
|
|||
|
if [[ -z "${_find_command+x}" ]]; then
|
|||
|
if command -v gfind > /dev/null; then
|
|||
|
_find_command="gfind"
|
|||
|
else
|
|||
|
_find_command="find"
|
|||
|
fi
|
|||
|
fi
|
|||
|
|
|||
|
if [[ "${_have_find_mmin}" = 1 ]]; then
|
|||
|
matches=$("${_find_command}" "${1}" -mmin +"${2}" 2> /dev/null)
|
|||
|
find_exit_code="${?}"
|
|||
|
if [[ -n "${matches}" ]]; then
|
|||
|
return 0
|
|||
|
else
|
|||
|
if [[ "${find_exit_code}" != 0 ]]; then
|
|||
|
_have_find_mmin=0
|
|||
|
else
|
|||
|
return 1
|
|||
|
fi
|
|||
|
fi
|
|||
|
fi
|
|||
|
|
|||
|
# try perl, solaris ships with perl
|
|||
|
if command -v perl > /dev/null; then
|
|||
|
perl -e '((time - (stat("'"${1}"'"))[9]) / 60) > '"${2}"' && exit(0) || exit(1)'
|
|||
|
return "${?}"
|
|||
|
else
|
|||
|
echo >&2
|
|||
|
echo "[1;31mWARNING[0m: neither a find that supports -mmin (such as GNU find) or perl is available, disabling remote status checking. Install GNU find as gfind or perl to enable this feature, or set GIT_PROMPT_FETCH_REMOTE_STATUS=0 to disable this warning." >&2
|
|||
|
echo >&2
|
|||
|
GIT_PROMPT_FETCH_REMOTE_STATUS=0
|
|||
|
return 1
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function checkUpstream() {
|
|||
|
local GIT_PROMPT_FETCH_TIMEOUT
|
|||
|
git_prompt_config
|
|||
|
|
|||
|
local FETCH_HEAD="${repo}/.git/FETCH_HEAD"
|
|||
|
# Fech repo if local is stale for more than $GIT_FETCH_TIMEOUT minutes
|
|||
|
if [[ ! -e "${FETCH_HEAD}" ]] || olderThanMinutes "${FETCH_HEAD}" "${GIT_PROMPT_FETCH_TIMEOUT}"
|
|||
|
then
|
|||
|
if [[ -n $(git remote show) ]]; then
|
|||
|
(
|
|||
|
if [ -n "$ZSH_VERSION" ]; then
|
|||
|
async_run_zsh "GIT_TERMINAL_PROMPT=0 git fetch --quiet"
|
|||
|
else
|
|||
|
async_run "GIT_TERMINAL_PROMPT=0 git fetch --quiet"
|
|||
|
disown -h
|
|||
|
fi
|
|||
|
)
|
|||
|
fi
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function replaceSymbols() {
|
|||
|
# Disable globbing, so a * could be used as symbol here
|
|||
|
set -f
|
|||
|
|
|||
|
if [[ -z ${GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING+x} ]]; then
|
|||
|
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING=L
|
|||
|
fi
|
|||
|
|
|||
|
local VALUE="${1//_AHEAD_/${GIT_PROMPT_SYMBOLS_AHEAD}}"
|
|||
|
local VALUE1="${VALUE//_BEHIND_/${GIT_PROMPT_SYMBOLS_BEHIND}}"
|
|||
|
local VALUE2="${VALUE1//_NO_REMOTE_TRACKING_/${GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING}}"
|
|||
|
local VALUE3="${VALUE2//_PRETAG_/${GIT_PROMPT_SYMBOLS_PRETAG}}"
|
|||
|
|
|||
|
echo "${VALUE3//_PREHASH_/${GIT_PROMPT_SYMBOLS_PREHASH}}"
|
|||
|
|
|||
|
# reenable globbing symbols
|
|||
|
set +f
|
|||
|
}
|
|||
|
|
|||
|
function createPrivateIndex {
|
|||
|
# Create a copy of the index to avoid conflicts with parallel git commands, e.g. git rebase.
|
|||
|
local __GIT_INDEX_FILE
|
|||
|
local __GIT_INDEX_PRIVATE
|
|||
|
if [[ -z "${GIT_INDEX_FILE+x}" ]]; then
|
|||
|
__GIT_INDEX_FILE="$(git rev-parse --git-dir)/index"
|
|||
|
else
|
|||
|
__GIT_INDEX_FILE="${GIT_INDEX_FILE}"
|
|||
|
fi
|
|||
|
__GIT_INDEX_PRIVATE="${TMPDIR:-/tmp}/git-index-private$$"
|
|||
|
command cp "${__GIT_INDEX_FILE}" "${__GIT_INDEX_PRIVATE}" 2>/dev/null
|
|||
|
echo "${__GIT_INDEX_PRIVATE}"
|
|||
|
}
|
|||
|
|
|||
|
function get_branch_prefix() {
|
|||
|
local GIT_BRANCH="${1}"
|
|||
|
local DETACHED_HEAD="${2}"
|
|||
|
|
|||
|
case "$GIT_BRANCH" in
|
|||
|
${GIT_PROMPT_MASTER_BRANCHES})
|
|||
|
local IS_MASTER_BRANCH=1
|
|||
|
;;
|
|||
|
*)
|
|||
|
local IS_MASTER_BRANCH=0
|
|||
|
;;
|
|||
|
esac
|
|||
|
|
|||
|
if [[ "$IS_MASTER_BRANCH" == "1" ]]; then
|
|||
|
echo "$GIT_PROMPT_MASTER_BRANCH"
|
|||
|
elif [[ "$DETACHED_HEAD" = "1" ]]; then
|
|||
|
echo "$GIT_PROMPT_DETACHED_HEAD"
|
|||
|
else
|
|||
|
echo "$GIT_PROMPT_BRANCH"
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function updatePrompt() {
|
|||
|
local LAST_COMMAND_INDICATOR
|
|||
|
local PROMPT_LEADING_SPACE
|
|||
|
local PROMPT_START
|
|||
|
local PROMPT_END
|
|||
|
local EMPTY_PROMPT
|
|||
|
local Blue="\[\033[0;34m\]"
|
|||
|
if [ -n "$ZSH_VERSION" ]; then
|
|||
|
Blue='%{fg[blue]%}'
|
|||
|
fi
|
|||
|
|
|||
|
git_prompt_config
|
|||
|
|
|||
|
export __GIT_PROMPT_IGNORE_STASH="${GIT_PROMPT_IGNORE_STASH:-0}"
|
|||
|
export __GIT_PROMPT_SHOW_UPSTREAM="${GIT_PROMPT_SHOW_UPSTREAM:-0}"
|
|||
|
export __GIT_PROMPT_IGNORE_SUBMODULES="${GIT_PROMPT_IGNORE_SUBMODULES:-0}"
|
|||
|
export __GIT_PROMPT_WITH_USERNAME_AND_REPO="${GIT_PROMPT_WITH_USERNAME_AND_REPO:-0}"
|
|||
|
export __GIT_PROMPT_SHOW_TRACKING=${GIT_PROMPT_SHOW_TRACKING:-1}
|
|||
|
export __GIT_PROMPT_SHOW_UNTRACKED_FILES="${GIT_PROMPT_SHOW_UNTRACKED_FILES-normal}"
|
|||
|
export __GIT_PROMPT_SHOW_CHANGED_FILES_COUNT="${GIT_PROMPT_SHOW_CHANGED_FILES_COUNT:-1}"
|
|||
|
|
|||
|
local GIT_INDEX_PRIVATE="$(createPrivateIndex)"
|
|||
|
#important to define GIT_INDEX_FILE as local: This way it only affects this function (and below) - even with the export afterwards
|
|||
|
local GIT_INDEX_FILE
|
|||
|
export GIT_INDEX_FILE="${GIT_INDEX_PRIVATE}"
|
|||
|
|
|||
|
local -a git_status_fields
|
|||
|
while IFS=$'\n' read -r line; do git_status_fields+=("${line}"); done < <("${__GIT_STATUS_CMD}" 2>/dev/null)
|
|||
|
|
|||
|
export GIT_BRANCH=$(replaceSymbols "${git_status_fields[@]:0:1}")
|
|||
|
if [[ $__GIT_PROMPT_SHOW_TRACKING != "0" ]]; then
|
|||
|
local GIT_REMOTE="$(replaceSymbols "${git_status_fields[@]:1:1}")"
|
|||
|
if [[ "." == "${GIT_REMOTE}" ]]; then
|
|||
|
unset GIT_REMOTE
|
|||
|
fi
|
|||
|
fi
|
|||
|
local GIT_REMOTE_USERNAME_REPO="$(replaceSymbols "${git_status_fields[@]:2:1}")"
|
|||
|
if [[ "." == "${GIT_REMOTE_USERNAME_REPO}" ]]; then
|
|||
|
unset GIT_REMOTE_USERNAME_REPO
|
|||
|
fi
|
|||
|
|
|||
|
local GIT_FORMATTED_UPSTREAM
|
|||
|
local GIT_UPSTREAM_PRIVATE="${git_status_fields[@]:3:1}"
|
|||
|
if [[ "${__GIT_PROMPT_SHOW_UPSTREAM:-0}" != "1" || "^" == "${GIT_UPSTREAM_PRIVATE}" ]]; then
|
|||
|
unset GIT_FORMATTED_UPSTREAM
|
|||
|
else
|
|||
|
GIT_FORMATTED_UPSTREAM="${GIT_PROMPT_UPSTREAM//_UPSTREAM_/${GIT_UPSTREAM_PRIVATE}}"
|
|||
|
fi
|
|||
|
|
|||
|
local GIT_STAGED="${git_status_fields[@]:4:1}"
|
|||
|
local GIT_CONFLICTS="${git_status_fields[@]:5:1}"
|
|||
|
local GIT_CHANGED="${git_status_fields[@]:6:1}"
|
|||
|
local GIT_UNTRACKED="${git_status_fields[@]:7:1}"
|
|||
|
local GIT_STASHED="${git_status_fields[@]:8:1}"
|
|||
|
local GIT_CLEAN="${git_status_fields[@]:9:1}"
|
|||
|
local GIT_DETACHED_HEAD="${git_status_fields[@]:10:1}"
|
|||
|
|
|||
|
local NEW_PROMPT="${EMPTY_PROMPT}"
|
|||
|
if [[ "${#git_status_fields[@]}" -gt 0 ]]; then
|
|||
|
|
|||
|
if [[ -z "${GIT_REMOTE_USERNAME_REPO+x}" ]]; then
|
|||
|
local GIT_PROMPT_PREFIX_FINAL="${GIT_PROMPT_PREFIX//_USERNAME_REPO_/${ResetColor}}"
|
|||
|
else
|
|||
|
if [[ -z "${GIT_PROMPT_USERNAME_REPO_SEPARATOR+x}" ]]; then
|
|||
|
local GIT_PROMPT_PREFIX_FINAL="${GIT_PROMPT_PREFIX//_USERNAME_REPO_/${GIT_REMOTE_USERNAME_REPO}${ResetColor}}"
|
|||
|
else
|
|||
|
local GIT_PROMPT_PREFIX_FINAL="${GIT_PROMPT_PREFIX//_USERNAME_REPO_/${GIT_REMOTE_USERNAME_REPO}${ResetColor}${GIT_PROMPT_USERNAME_REPO_SEPARATOR}}"
|
|||
|
fi
|
|||
|
fi
|
|||
|
|
|||
|
local BRANCH_PREFIX="$(get_branch_prefix $GIT_BRANCH $GIT_DETACHED_HEAD)"
|
|||
|
local STATUS_PREFIX="${PROMPT_LEADING_SPACE}${GIT_PROMPT_PREFIX_FINAL}${BRANCH_PREFIX}\${GIT_BRANCH}${ResetColor}${GIT_FORMATTED_UPSTREAM}"
|
|||
|
local STATUS=""
|
|||
|
|
|||
|
# __add_status KIND VALEXPR INSERT
|
|||
|
# eg: __add_status 'STAGED' '-ne 0'
|
|||
|
|
|||
|
__chk_gitvar_status() {
|
|||
|
local v
|
|||
|
if [[ "${2-}" = "-n" ]] ; then
|
|||
|
v="${2} \"\${GIT_${1}-}\""
|
|||
|
else
|
|||
|
v="\${GIT_${1}-} ${2}"
|
|||
|
fi
|
|||
|
if eval "[[ ${v} ]]" ; then
|
|||
|
if [[ "${3-}" != '-' ]] && [[ "${__GIT_PROMPT_SHOW_CHANGED_FILES_COUNT}" == "1" || "${1-}" == "REMOTE" ]]; then
|
|||
|
__add_status "\${GIT_PROMPT_${1}}\${GIT_${1}}\${ResetColor}"
|
|||
|
else
|
|||
|
__add_status "\${GIT_PROMPT_${1}}\${ResetColor}"
|
|||
|
fi
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
__add_gitvar_status() {
|
|||
|
__add_status "\${GIT_PROMPT_${1}}\${GIT_${1}}\${ResetColor}"
|
|||
|
}
|
|||
|
|
|||
|
# __add_status SOMETEXT
|
|||
|
__add_status() {
|
|||
|
eval "STATUS=\"${STATUS}${1}\""
|
|||
|
}
|
|||
|
|
|||
|
__chk_gitvar_status 'REMOTE' '-n'
|
|||
|
if [[ "${GIT_CLEAN}" -eq 0 ]] || [[ "${GIT_PROMPT_CLEAN}" != "" ]]; then
|
|||
|
__add_status "${GIT_PROMPT_SEPARATOR}"
|
|||
|
__chk_gitvar_status 'STAGED' '!= "0" && ${GIT_STAGED-} != "^"'
|
|||
|
__chk_gitvar_status 'CONFLICTS' '!= "0"'
|
|||
|
__chk_gitvar_status 'CHANGED' '!= "0"'
|
|||
|
__chk_gitvar_status 'UNTRACKED' '!= "0"'
|
|||
|
__chk_gitvar_status 'STASHED' '!= "0"'
|
|||
|
__chk_gitvar_status 'CLEAN' '= "1"' -
|
|||
|
fi
|
|||
|
__add_status "${ResetColor}${GIT_PROMPT_SUFFIX}"
|
|||
|
|
|||
|
if [[ "${GIT_PROMPT_VIRTUAL_ENV_AFTER_PROMPT:-0}" == "0" ]]; then
|
|||
|
NEW_PROMPT="$(gp_add_virtualenv_to_prompt)${PROMPT_START}$(${prompt_callback})${STATUS_PREFIX}${STATUS}${PROMPT_END}"
|
|||
|
else
|
|||
|
NEW_PROMPT="${PROMPT_START}$(${prompt_callback})$(gp_add_virtualenv_to_prompt)${STATUS_PREFIX}${STATUS}${PROMPT_END}"
|
|||
|
fi
|
|||
|
else
|
|||
|
NEW_PROMPT="${EMPTY_PROMPT}"
|
|||
|
fi
|
|||
|
|
|||
|
PS1="${NEW_PROMPT//_LAST_COMMAND_INDICATOR_/${LAST_COMMAND_INDICATOR}${ResetColor}}"
|
|||
|
command rm "${GIT_INDEX_PRIVATE}" 2>/dev/null
|
|||
|
}
|
|||
|
|
|||
|
# Helper function that returns virtual env information to be set in prompt
|
|||
|
# Honors virtualenvs own setting VIRTUAL_ENV_DISABLE_PROMPT
|
|||
|
function gp_add_virtualenv_to_prompt {
|
|||
|
local ACCUMULATED_VENV_PROMPT=""
|
|||
|
local VENV=""
|
|||
|
if [[ -n "${VIRTUAL_ENV-}" && -z "${VIRTUAL_ENV_DISABLE_PROMPT+x}" ]]; then
|
|||
|
if [[ -n "${VIRTUAL_ENV_PROMPT-}" ]]; then
|
|||
|
# first trim any starting white space and parenthesis, and then do the same to the end
|
|||
|
VENV="${VIRTUAL_ENV_PROMPT#"${VIRTUAL_ENV_PROMPT%%[![:space:]]*}("}"
|
|||
|
VENV="${VENV%")${VENV##*[![:space:]]}"}"
|
|||
|
else
|
|||
|
VENV=$(basename "${VIRTUAL_ENV}")
|
|||
|
fi
|
|||
|
ACCUMULATED_VENV_PROMPT="${ACCUMULATED_VENV_PROMPT}${GIT_PROMPT_VIRTUALENV//_VIRTUALENV_/${VENV}}"
|
|||
|
fi
|
|||
|
if [[ -n "${NODE_VIRTUAL_ENV-}" && -z "${NODE_VIRTUAL_ENV_DISABLE_PROMPT+x}" ]]; then
|
|||
|
VENV=$(basename "${NODE_VIRTUAL_ENV}")
|
|||
|
ACCUMULATED_VENV_PROMPT="${ACCUMULATED_VENV_PROMPT}${GIT_PROMPT_VIRTUALENV//_VIRTUALENV_/${VENV}}"
|
|||
|
fi
|
|||
|
if [[ -n "${CONDA_DEFAULT_ENV-}" ]]; then
|
|||
|
VENV=$(basename "${CONDA_DEFAULT_ENV}")
|
|||
|
ACCUMULATED_VENV_PROMPT="${ACCUMULATED_VENV_PROMPT}${GIT_PROMPT_VIRTUALENV//_VIRTUALENV_/${VENV}}"
|
|||
|
fi
|
|||
|
echo "${ACCUMULATED_VENV_PROMPT}"
|
|||
|
}
|
|||
|
|
|||
|
# Use exit status from declare command to determine whether input argument is a
|
|||
|
# bash function
|
|||
|
function is_function {
|
|||
|
declare -Ff "${1}" >/dev/null;
|
|||
|
}
|
|||
|
|
|||
|
# Helper function that truncates $PWD depending on window width
|
|||
|
# Optionally specify maximum length as parameter (defaults to 1/3 of terminal)
|
|||
|
function gp_truncate_pwd {
|
|||
|
local tilde="~"
|
|||
|
local newPWD="${PWD/#${HOME}/${tilde}}"
|
|||
|
local pwdmaxlen="${1:-$((${COLUMNS:-80}/3))}"
|
|||
|
[[ "${#newPWD}" -gt "${pwdmaxlen}" ]] && newPWD="...${newPWD:3-$pwdmaxlen}"
|
|||
|
echo -n "${newPWD}"
|
|||
|
}
|
|||
|
|
|||
|
# Sets the window title to the given argument string
|
|||
|
function gp_set_window_title {
|
|||
|
echo -ne "\[\033]0;$1\007\]"
|
|||
|
}
|
|||
|
|
|||
|
function prompt_callback_default {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
# toggle gitprompt
|
|||
|
function git_prompt_toggle() {
|
|||
|
if [[ "${GIT_PROMPT_DISABLE:-0}" = 1 ]]; then
|
|||
|
GIT_PROMPT_DISABLE=0
|
|||
|
else
|
|||
|
GIT_PROMPT_DISABLE=1
|
|||
|
fi
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
function make_prompt_command_clean() {
|
|||
|
PROMPT_COMMAND="${PROMPT_COMMAND//$'\n'/;}" # convert all new lines to semi-colons
|
|||
|
PROMPT_COMMAND="${PROMPT_COMMAND#\;}" # remove leading semi-colon
|
|||
|
PROMPT_COMMAND="${PROMPT_COMMAND%% }" # remove trailing spaces
|
|||
|
PROMPT_COMMAND="${PROMPT_COMMAND%\;}" # remove trailing semi-colon
|
|||
|
}
|
|||
|
|
|||
|
function add_prompt_command() {
|
|||
|
local new_entry="$1"
|
|||
|
local insert_before="$2"
|
|||
|
|
|||
|
if [[ ";${PROMPT_COMMAND};" == *";${new_entry};"* ]]; then
|
|||
|
return 0
|
|||
|
fi
|
|||
|
|
|||
|
if [[ -z "$PROMPT_COMMAND" ]]; then
|
|||
|
PROMPT_COMMAND="$new_entry"
|
|||
|
return 0
|
|||
|
fi
|
|||
|
|
|||
|
if [[ "$insert_before" == "true" ]]; then
|
|||
|
PROMPT_COMMAND="${new_entry};${PROMPT_COMMAND}"
|
|||
|
else
|
|||
|
PROMPT_COMMAND="${PROMPT_COMMAND};${new_entry}"
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
function add_to_beginning_of_prompt_command() {
|
|||
|
add_prompt_command "$1" "true"
|
|||
|
}
|
|||
|
|
|||
|
function add_to_end_of_prompt_command() {
|
|||
|
add_prompt_command "$1" "false"
|
|||
|
}
|
|||
|
|
|||
|
function gp_install_prompt {
|
|||
|
# 5.1 supports PROMPT_COMMAND as an array
|
|||
|
if ((BASH_VERSINFO[0] > 5 || BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1)); then
|
|||
|
if [[ $(declare -p PROMPT_COMMAND 2>/dev/null) == "declare --"* ]]; then
|
|||
|
make_prompt_command_clean
|
|||
|
add_to_end_of_prompt_command "setGitPrompt"
|
|||
|
add_to_beginning_of_prompt_command "setLastCommandState"
|
|||
|
else
|
|||
|
if [[ "${PROMPT_COMMAND[*]}" != *setGitPrompt* ]]; then
|
|||
|
PROMPT_COMMAND+=(setGitPrompt)
|
|||
|
fi
|
|||
|
if [[ "${PROMPT_COMMAND[*]}" != *setLastCommandState* ]]; then
|
|||
|
PROMPT_COMMAND=(setLastCommandState "${PROMPT_COMMAND[@]}")
|
|||
|
fi
|
|||
|
fi
|
|||
|
else
|
|||
|
make_prompt_command_clean
|
|||
|
add_to_end_of_prompt_command "setGitPrompt"
|
|||
|
add_to_beginning_of_prompt_command "setLastCommandState"
|
|||
|
fi
|
|||
|
|
|||
|
set_git_prompt_dir
|
|||
|
# source "${__GIT_PROMPT_DIR}/git-prompt-help.sh"
|
|||
|
}
|
|||
|
|
|||
|
gp_install_prompt
|