ohmyzsh/lib/git.zsh
Frank Gruellich f804958710 working version
2014-09-04 15:24:07 +02:00

219 lines
8.2 KiB
Bash

autoload -U add-zsh-hook
add-zsh-hook chpwd update_git_vars
add-zsh-hook preexec schedule_update_git_vars_if_git_cmd
add-zsh-hook precmd update_git_vars_if_scheduled
function schedule_update_git_vars_if_git_cmd() {
case "$2" in
git*)
__UPDATE_GIT_VARS_NEEDED="true"
;;
esac
}
function update_git_vars_if_scheduled() {
if [ "$__UPDATE_GIT_VARS_NEEDED" == "true" ]
then
update_git_vars
unset __UPDATE_GIT_VARS_NEEDED
fi
}
function update_git_vars() {
local output merge_ref remote_ref remote
local _branch _ahead _behind _staged _conflict _changed _untracked
local branch ahead behind staged conflict changed untracked
unset GIT_STATUS
output="`git symbolic-ref HEAD 2>/dev/null`" || \
output="`git rev-parse --short HEAD 2>/dev/null`" || return 0
_branch="${output#refs/heads/}"
output="`git config branch.$_branch.remote 2>/dev/null`"
if [ -n "$output" ]
then
remote="$output"
merge_ref="`git config branch.$_branch.merge`"
if [ "$remote" == "." ]
then
remote_ref="$merge_ref"
else
remote_ref="refs/remotes/$remote/${merge_ref#refs/heads/}"
fi
output="`git rev-list --left-right $remote_ref..HEAD`" || \
output="`git rev-list --left-right $merge_ref..HEAD`"
_ahead="`echo -n $output |grep -c '^>'`"
output="`echo -n ${output} |grep -c '.*'`"
_behind="`expr $output - $_ahead`"
fi
output="`git diff --name-status --staged`"
_staged="`echo -n $output |grep -c -v -e '^U\>'`"
_conflict="`echo -n $output |grep -c -e '^U\>'`"
_changed="`git diff --name-status |grep -c -v -e '^U\>'`"
_untracked="`git status --porcelain |grep -c -e '^??'`"
clean="${ZSH_THEME_GIT_PROMPT_CLEAN_PREFIX}c${ZSH_THEME_GIT_PROMPT_CLEAN_SUFFIX}"
test -n "${_branch}" && branch="${ZSH_THEME_GIT_PROMPT_BRANCH_PREFIX}${_branch}${ZSH_THEME_GIT_PROMPT_BRANCH_SUFFIX}"
test -n "${_behind}" -a "${_behind}" != "0" && behind="${ZSH_THEME_GIT_PROMPT_BEHIND_PREFIX}${_behind}${ZSH_THEME_GIT_PROMPT_BEHIND_SUFFIX}"
test -n "${_ahead}" -a "${_ahead}" != "0" && ahead="${ZSH_THEME_GIT_PROMPT_AHEAD_PREFIX}${_ahead}${ZSH_THEME_GIT_PROMPT_AHEAD_SUFFIX}"
test -n "${_staged}" -a "${_staged}" != "0" && { clean=""; staged="${ZSH_THEME_GIT_PROMPT_STAGED_PREFIX}${_staged}${ZSH_THEME_GIT_PROMPT_STAGED_SUFFIX}"; }
test -n "${_conflict}" -a "${_conflict}" != "0" && { clean=""; conflict="${ZSH_THEME_GIT_PROMPT_CONFLICT_PREFIX}${_conflict}${ZSH_THEME_GIT_PROMPT_CONFLICT_SUFFIX}"; }
test -n "${_changed}" -a "${_changed}" != "0" && { clean=""; changed="${ZSH_THEME_GIT_PROMPT_CHANGED_PREFIX}${_changed}${ZSH_THEME_GIT_PROMPT_CHANGED_SUFFIX}"; }
test -n "${_untracked}" -a "${_untracked}" != "0" && { clean=""; untracked="${ZSH_THEME_GIT_PROMPT_UNTRACKED_PREFIX}${_untracked}${ZSH_THEME_GIT_PROMPT_UNTRACKED_SUFFIX}"; }
git_status
GIT_STATUS="${ZSH_THEME_GIT_PROMPT_PREFIX}${GIT_STATUS}${ZSH_THEME_GIT_PROMPT_SUFFIX}"
}
function git_prompt_info() {
if [ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]
then
if [ -n "${__UPDATE_GIT_VARS_NEEDED}" ]
then
update_git_vars
fi
echo -n "${GIT_STATUS}"
fi
}
# Checks if working tree is dirty
parse_git_dirty() {
local SUBMODULE_SYNTAX=''
local GIT_STATUS=''
local CLEAN_MESSAGE='nothing to commit (working directory clean)'
if [[ "$(command git config --get oh-my-zsh.hide-status)" != "1" ]]; then
if [[ $POST_1_7_2_GIT -gt 0 ]]; then
SUBMODULE_SYNTAX="--ignore-submodules=dirty"
fi
if [[ "$DISABLE_UNTRACKED_FILES_DIRTY" == "true" ]]; then
GIT_STATUS=$(command git status -s ${SUBMODULE_SYNTAX} -uno 2> /dev/null | tail -n1)
else
GIT_STATUS=$(command git status -s ${SUBMODULE_SYNTAX} 2> /dev/null | tail -n1)
fi
if [[ -n $GIT_STATUS ]]; then
echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
else
echo "$ZSH_THEME_GIT_PROMPT_CLEAN"
fi
else
echo "$ZSH_THEME_GIT_PROMPT_CLEAN"
fi
}
# get the difference between the local and remote branches
git_remote_status() {
remote=${$(command git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/}
if [[ -n ${remote} ]] ; then
ahead=$(command git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
behind=$(command git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
if [ $ahead -eq 0 ] && [ $behind -gt 0 ]
then
echo "$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE"
elif [ $ahead -gt 0 ] && [ $behind -eq 0 ]
then
echo "$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE"
elif [ $ahead -gt 0 ] && [ $behind -gt 0 ]
then
echo "$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE"
fi
fi
}
# Checks if there are commits ahead from remote
function git_prompt_ahead() {
if $(echo "$(command git log @{upstream}..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then
echo "$ZSH_THEME_GIT_PROMPT_AHEAD"
fi
}
# Gets the number of commits ahead from remote
function git_commits_ahead() {
if $(echo "$(command git log @{upstream}..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then
COMMITS=$(command git log @{upstream}..HEAD | grep '^commit' | wc -l | tr -d ' ')
echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$COMMITS$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX"
fi
}
# Formats prompt string for current git commit short SHA
function git_prompt_short_sha() {
SHA=$(command git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
}
# Formats prompt string for current git commit long SHA
function git_prompt_long_sha() {
SHA=$(command git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
}
# Get the status of the working tree
git_prompt_status() {
INDEX=$(command git status --porcelain -b 2> /dev/null)
STATUS=""
if $(echo "$INDEX" | grep -E '^\?\? ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS"
fi
if $(echo "$INDEX" | grep '^A ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
elif $(echo "$INDEX" | grep '^M ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
fi
if $(echo "$INDEX" | grep '^ M ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
elif $(echo "$INDEX" | grep '^AM ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
elif $(echo "$INDEX" | grep '^ T ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
fi
if $(echo "$INDEX" | grep '^R ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS"
fi
if $(echo "$INDEX" | grep '^ D ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
elif $(echo "$INDEX" | grep '^D ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
elif $(echo "$INDEX" | grep '^AD ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
fi
if $(command git rev-parse --verify refs/stash >/dev/null 2>&1); then
STATUS="$ZSH_THEME_GIT_PROMPT_STASHED$STATUS"
fi
if $(echo "$INDEX" | grep '^UU ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS"
fi
if $(echo "$INDEX" | grep '^## .*ahead' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS"
fi
if $(echo "$INDEX" | grep '^## .*behind' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS"
fi
if $(echo "$INDEX" | grep '^## .*diverged' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS"
fi
echo $STATUS
}
#compare the provided version of git to the version installed and on path
#prints 1 if input version <= installed version
#prints -1 otherwise
function git_compare_version() {
local INPUT_GIT_VERSION=$1;
local INSTALLED_GIT_VERSION
INPUT_GIT_VERSION=(${(s/./)INPUT_GIT_VERSION});
INSTALLED_GIT_VERSION=($(command git --version 2>/dev/null));
INSTALLED_GIT_VERSION=(${(s/./)INSTALLED_GIT_VERSION[3]});
for i in {1..3}; do
if [[ $INSTALLED_GIT_VERSION[$i] -lt $INPUT_GIT_VERSION[$i] ]]; then
echo -1
return 0
fi
done
echo 1
}
#this is unlikely to change so make it all statically assigned
POST_1_7_2_GIT=$(git_compare_version "1.7.2")
#clean up the namespace slightly by removing the checker function
unset -f git_compare_version