Skip to content

Instantly share code, notes, and snippets.

@tkuennen
Last active April 24, 2017 17:04
Show Gist options
  • Save tkuennen/a573432e0584a185e2e1eb8b2bc7b584 to your computer and use it in GitHub Desktop.
Save tkuennen/a573432e0584a185e2e1eb8b2bc7b584 to your computer and use it in GitHub Desktop.
# GIT #
# Get the branch name of the current directory
_lp_git_branch()
{
(( LP_ENABLE_GIT )) || return
\git rev-parse --is-inside-work-tree >/dev/null 2>&1 || return
local branch
# Recent versions of Git support the --short option for symbolic-ref, but
# not 1.7.9 (Ubuntu 12.04)
if branch="$(\git symbolic-ref -q HEAD)"; then
_lp_escape "${branch#refs/heads/}"
else
# In detached head state, use commit instead
# No escape needed
\git rev-parse --short -q HEAD
fi
}
# Display additional information if HEAD is in merging, rebasing
# or cherry-picking state
_lp_git_head_status() {
local gitdir
gitdir="$(\git rev-parse --git-dir 2>/dev/null)"
if [[ -f "${gitdir}/MERGE_HEAD" ]]; then
echo " MERGING"
elif [[ -d "${gitdir}/rebase-apply" || -d "${gitdir}/rebase-merge" ]]; then
echo " REBASING"
elif [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]]; then
echo " CHERRY-PICKING"
fi
}
# Set a color depending on the branch state:
# - green if the repository is up to date
# - yellow if there is some commits not pushed
# - red if there is changes to commit
#
# Add the number of pending commits and the impacted lines.
_lp_git_branch_color()
{
(( LP_ENABLE_GIT )) || return
local branch
branch="$(_lp_git_branch)"
if [[ -n "$branch" ]]; then
local end
end="${LP_COLOR_CHANGES}$(_lp_git_head_status)${NO_COL}"
if LC_ALL=C \git status --porcelain 2>/dev/null | \grep -Eq '^\?\?'; then
end="$LP_COLOR_CHANGES$LP_MARK_UNTRACKED$end"
fi
if [[ -n "$(\git stash list -n 1 2>/dev/null)" ]]; then
end="$LP_COLOR_COMMITS$LP_MARK_STASH$end"
fi
local remote
remote="$(\git config --get branch.${branch}.remote 2>/dev/null)"
local has_commit=""
local commit_ahead
local commit_behind
if [[ -n "$remote" ]]; then
local remote_branch
remote_branch="$(\git config --get branch.${branch}.merge)"
if [[ -n "$remote_branch" ]]; then
remote_branch=${remote_branch/refs\/heads/refs\/remotes\/$remote}
commit_ahead="$(\git rev-list --count $remote_branch..HEAD 2>/dev/null)"
commit_behind="$(\git rev-list --count HEAD..$remote_branch 2>/dev/null)"
if [[ "$commit_ahead" -ne "0" && "$commit_behind" -ne "0" ]]; then
has_commit="${LP_COLOR_COMMITS}+$commit_ahead${NO_COL}/${LP_COLOR_COMMITS_BEHIND}-$commit_behind${NO_COL}"
elif [[ "$commit_ahead" -ne "0" ]]; then
has_commit="${LP_COLOR_COMMITS}$commit_ahead${NO_COL}"
elif [[ "$commit_behind" -ne "0" ]]; then
has_commit="${LP_COLOR_COMMITS_BEHIND}-$commit_behind${NO_COL}"
fi
fi
fi
local ret
local shortstat # only to check for uncommitted changes
shortstat="$(LC_ALL=C \git diff --shortstat HEAD 2>/dev/null)"
if [[ -n "$shortstat" ]]; then
local u_stat # shorstat of *unstaged* changes
u_stat="$(LC_ALL=C \git diff --shortstat 2>/dev/null)"
u_stat=${u_stat/*changed, /} # removing "n file(s) changed"
local i_lines # inserted lines
if [[ "$u_stat" = *insertion* ]]; then
i_lines=${u_stat/ inser*}
else
i_lines=0
fi
local d_lines # deleted lines
if [[ "$u_stat" = *deletion* ]]; then
d_lines=${u_stat/*\(+\), }
d_lines=${d_lines/ del*/}
else
d_lines=0
fi
local has_lines
has_lines="+$i_lines/-$d_lines"
if [[ -n "$has_commit" ]]; then
# Changes to commit and commits to push
ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${NO_COL},$has_commit)"
else
ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${NO_COL})" # changes to commit
fi
elif [[ -n "$has_commit" ]]; then
# some commit(s) to push
if [[ "$commit_behind" -gt "0" ]]; then
ret="${LP_COLOR_COMMITS_BEHIND}${branch}${NO_COL}($has_commit)"
else
ret="${LP_COLOR_COMMITS}${branch}${NO_COL}($has_commit)"
fi
else
ret="${LP_COLOR_UP}${branch}" # nothing to commit or push
fi
echo -nE "$ret$end"
fi
}
# Search upwards through a directory structure looking for a file/folder with
# the given name. Used to avoid invoking 'hg' and 'bzr'.
_lp_upwards_find()
{
local dir
dir="$PWD"
while [[ -n "$dir" ]]; do
[[ -d "$dir/$1" ]] && return 0
dir="${dir%/*}"
done
return 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment