70cec22db5
Split former `parse_git_status` function, which was around 60 lines of code, into multiple small functions. Also, instead of polluting the global namespace with a lot of variables, make functions return something through a $REPLY variable. Or the $STATUS variable, in the case of the *new* parse_git_status function.
131 lines
3.0 KiB
Bash
Executable File
131 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/zsh
|
|
|
|
function main() {
|
|
is_in_git_repository || return 1
|
|
|
|
parse_git_status
|
|
local modified="${STATUS[1]}"
|
|
local staged="${STATUS[2]}"
|
|
local deleted="${STATUS[3]}"
|
|
local untracked="${STATUS[4]}"
|
|
unset STATUS
|
|
|
|
git_grab_current_branch
|
|
local branch="$REPLY"
|
|
|
|
git_grab_remote_branch
|
|
local remote="$REPLY"
|
|
|
|
[[ ! -z "$remote" ]] \
|
|
&& get_differences_between_remote_and_local \
|
|
&& local remote_local_diffs="$REPLY"
|
|
|
|
git_determine_color $modified $staged $deleted $untracked
|
|
local color="$REPLY"
|
|
|
|
(( modified > 0 )) \
|
|
&& modified="!$modified "
|
|
(( staged > 0 )) \
|
|
&& staged="+$staged "
|
|
(( deleted > 0 )) \
|
|
&& deleted="-$deleted "
|
|
(( untracked > 0 )) \
|
|
&& untracked="?$untracked"
|
|
|
|
local output="${color}"
|
|
output+=" $branch "
|
|
output+="$local_remote_diffs"
|
|
output+="$modified"
|
|
output+="$staged"
|
|
output+="$deleted"
|
|
output+="$untracked"
|
|
output+=$'\e[0m'
|
|
|
|
sed 's/[ ]+$//' <<<"$output" # remove trailing whitespace
|
|
}
|
|
|
|
###
|
|
# Check if we're in a git repository
|
|
# Globals: none
|
|
# Arguments: none
|
|
###
|
|
function is_in_git_repository()
|
|
{
|
|
git rev-parse --git-dir &>/dev/null || return 1
|
|
}
|
|
|
|
function git_grab_current_branch()
|
|
{
|
|
typeset -g REPLY="$(git branch --show-current)"
|
|
}
|
|
|
|
function git_grab_remote_branch()
|
|
{
|
|
local symbolic_ref="$(git symbolic-ref -q HEAD)"
|
|
typeset -g REPLY="$(git for-each-ref --format='%(upstream:short)' $symbolic_ref)"
|
|
}
|
|
|
|
###
|
|
# Find how many things have changed since last commit
|
|
# Globals: none
|
|
# Arguments: none
|
|
###
|
|
function parse_git_status()
|
|
{
|
|
git status --porcelain=v1 | while IFS= read -r status_line; do
|
|
case "$status_line" in
|
|
' M '*)
|
|
((modified++))
|
|
;;
|
|
'A '*|'M '*)
|
|
((staged++))
|
|
;;
|
|
' D '*)
|
|
((deleted++))
|
|
;;
|
|
'?? '*)
|
|
((untracked++))
|
|
;;
|
|
'MM '*)
|
|
((staged++))
|
|
((modified++))
|
|
;;
|
|
esac
|
|
done
|
|
|
|
typeset -g STATUS=("$modified" "$staged" "$deleted" "$untracked")
|
|
return 0
|
|
}
|
|
|
|
function get_differences_between_remote_and_local()
|
|
{
|
|
local local_branch="$1"
|
|
local remote_branch="$2"
|
|
|
|
local differences="$(git rev-list --left-right --count $local_branch...$remote_branch)"
|
|
local commits_ahead=$(echo -n "$differences" | awk '{print $1}')
|
|
local commits_behind=$(echo -n "$differences" | awk '{print $2}')
|
|
|
|
(( $commits_ahead > 0 )) \
|
|
&& local ahead="↑$commits_ahead"
|
|
(( $commits_behind > 0 )) \
|
|
&& local behind="↓$commits_behind"
|
|
|
|
typeset -g REPLY="$ahead $behind"
|
|
return 0
|
|
}
|
|
|
|
function git_determine_color()
|
|
{
|
|
for i in "$@"; do
|
|
if (( $i > 0 )); then
|
|
typeset -g REPLY=$'\e[93m'
|
|
return 0
|
|
fi
|
|
done
|
|
typeset -g REPLY=$'\e[92m'
|
|
return 0
|
|
}
|
|
|
|
main
|