aboutsummaryrefslogtreecommitdiffstats
path: root/hyperterm/core/git.sh
diff options
context:
space:
mode:
Diffstat (limited to 'hyperterm/core/git.sh')
-rw-r--r--hyperterm/core/git.sh332
1 files changed, 332 insertions, 0 deletions
diff --git a/hyperterm/core/git.sh b/hyperterm/core/git.sh
new file mode 100644
index 0000000..17bb575
--- /dev/null
+++ b/hyperterm/core/git.sh
@@ -0,0 +1,332 @@
+#!/bin/bash
+
+# Set up symbols
+function _symbols() {
+
+ # Import colors
+ _colors_bash "$@"
+
+ _synced_symbol="$(printf '%b\u2714' "${BOLD}${CYAN}")" # ✔
+ _dirty_synced_symbol="$(printf '%b\u002A' "${BOLD}${RED}")" # ∗
+ _unpushed_symbol="$(printf '%b\u2191' "${BOLD}${CYAN}")" # ↑
+ _dirty_unpushed_symbol="$(printf '%b\u25B2' "${BOLD}${YELLOW}")" # ▲
+ _unpulled_symbol="$(printf '%b\u25BD' "${BOLD}${GREEN}")" # ▽
+ _dirty_unpulled_symbol="$(printf '%b\u25BC' "${BOLD}${RED}")" # ▼
+ _stage_symbol="$(printf '%b\u2192\u004D' "${BOLD}${CYAN}")" # →M
+ _unstage_symbol="$(printf '%b\u2190\u004D' "${BOLD}${RED}")" # ←M
+ _untracked_symbol="$(printf '%b\u003F' "${BOLD}${RED}")" # ?
+ _newfile_symbol="$(printf '%b\u002B' "${BOLD}${CYAN}")" # +
+ _deleted_file_symbol="$(printf '%b\u2013' "${BOLD}${RED}")" # –
+ _renamed_symbol="$(printf '%b\u2387 ' "${BOLD}${RED}")" # ⎇
+ _unpushed_unpulled_symbol="$(printf '%b\u2B21' "${BOLD}${RED}")" # ⬡
+ _dirty_unpushed_unpulled_symbol="$(printf '%b\u2B22' "${BOLD}${RED}")" # ⬢
+}
+
+function _get_git_branch() {
+ # On branches, this will return the branch name
+ # On non-branches, (no branch)
+ ref="$(git symbolic-ref HEAD 2> /dev/null | sed -e 's/refs\/heads\///')"
+ if [[ -n $ref ]]; then
+ printf '%s' "$ref"
+ else
+ printf "(no branch)"
+ fi
+}
+
+function _get_git_progress() {
+ # Detect in-progress actions (e.g. merge, rebase)
+ # https://github.com/git/git/blob/v1.9-rc2/wt-status.c#L1199-L1241
+ git_dir="$(git rev-parse --git-dir)"
+
+ # git merge
+ if [[ -f "$git_dir/MERGE_HEAD" ]]; then
+ printf " [merge]"
+ elif [[ -d "$git_dir/rebase-apply" ]]; then
+ # git am
+ if [[ -f "$git_dir/rebase-apply/applying" ]]; then
+ printf " [am]"
+ # git rebase
+ else
+ printf " [rebase]"
+ fi
+ elif [[ -d "$git_dir/rebase-merge" ]]; then
+ # git rebase --interactive/--merge
+ printf " [rebase]"
+ elif [[ -f "$git_dir/CHERRY_PICK_HEAD" ]]; then
+ # git cherry-pick
+ printf " [cherry-pick]"
+ fi
+ if [[ -f "$git_dir/BISECT_LOG" ]]; then
+ # git bisect
+ printf " [bisect]"
+ fi
+ if [[ -f "$git_dir/REVERT_HEAD" ]]; then
+ # git revert --no-commit
+ printf " [revert]"
+ fi
+}
+
+_prompt_is_branch1_behind_branch2 () {
+ # $ git log origin/master..master -1
+ # commit 4a633f715caf26f6e9495198f89bba20f3402a32
+ # Author: Todd Wolfson <todd@twolfson.com>
+ # Date: Sun Jul 7 22:12:17 2013 -0700
+ #
+ # Unsynced commit
+
+ # Find the first log (if any) that is in branch1 but not branch2
+ first_log="$(git log "$1..$2" -1 2> /dev/null)"
+
+ # Exit with 0 if there is a first log, 1 if there is not
+ [[ -n "$first_log" ]]
+}
+
+_prompt_branch_exists () {
+ # List remote branches | # Find our branch and exit with 0 or 1 if found/not found
+ git branch --remote 2> /dev/null | grep --quiet "$1"
+}
+
+_prompt_parse_git_ahead () {
+ # Grab the local and remote branch
+ branch="$(_get_git_branch)"
+ remote="$(git config --get "branch.${branch}.remote" || echo -n "origin")"
+ remote_branch="$remote/$branch"
+
+ # $ git log origin/master..master
+ # commit 4a633f715caf26f6e9495198f89bba20f3402a32
+ # Author: Todd Wolfson <todd@twolfson.com>
+ # Date: Sun Jul 7 22:12:17 2013 -0700
+ #
+ # Unsynced commit
+
+ # If the remote branch is behind the local branch
+ # or it has not been merged into origin (remote branch doesn't exist)
+ if (_prompt_is_branch1_behind_branch2 "$remote_branch" "$branch" ||
+ ! _prompt_branch_exists "$remote_branch"); then
+ # printf our character
+ printf '%s' '0'
+ fi
+}
+
+_prompt_parse_git_behind() {
+ # Grab the branch
+ branch="$(_get_git_branch)"
+ remote="$(git config --get "branch.${branch}.remote" || echo -n "origin")"
+ remote_branch="$remote/$branch"
+
+ # $ git log master..origin/master
+ # commit 4a633f715caf26f6e9495198f89bba20f3402a32
+ # Author: Todd Wolfson <todd@twolfson.com>
+ # Date: Sun Jul 7 22:12:17 2013 -0700
+ #
+ # Unsynced commit
+
+ # If the local branch is behind the remote branch
+ if _prompt_is_branch1_behind_branch2 "$branch" "$remote_branch"; then
+ # printf our character
+ printf '%s' '0'
+ fi
+}
+
+function _prompt_parse_git_dirty() {
+ # If the git status has *any* changes (e.g. dirty), printf our character
+ if [[ -n "$(git status --porcelain 2> /dev/null)" ]]; then
+ printf '%s' '0'
+ fi
+}
+
+# start counter on git
+function _git_dirty_count() {
+ local _dirty_status
+ local _git_status
+ _dirty_status="$(_prompt_parse_git_dirty)"
+ _git_status="$(git status --porcelain 2> /dev/null)"
+ if [[ "$_dirty_status" == 0 ]]; then
+ local change_count
+ change_count="$(echo "$_git_status" | wc -l | tr -d '[:space:]')"
+ if [[ "$change_count" == 1 ]]; then
+ printf '%b\u2022%s' "${BOLD}${GREY}" "$change_count"
+ elif [[ "$change_count" == 2 ]]; then
+ printf '%b\u2236%s' "${BOLD}${GREY}" "$change_count"
+ elif [[ "$change_count" == 3 ]]; then
+ printf '%b\u2026%s' "${BOLD}${GREY}" "$change_count"
+ else
+ printf '%b\u00BB%s' "${BOLD}${GREY}" "$change_count"
+ fi
+ else
+ printf ''
+ fi
+}
+# ends counter on git
+
+function _prompt_parse_git_untracked() {
+ local untracked
+ local evaltask
+ untracked="$(git status 2>&1 | tee)"
+ grep -E 'Untracked files:' <<<"$untracked" &> /dev/null
+ evaltask=$?
+ if [ "$evaltask" -eq 0 ]; then
+ printf '%s' '0'
+ else
+ printf '%s' '1'
+ fi
+}
+
+function _prompt_parse_git_newfile() {
+ local newfile
+ local evaltask
+ newfile="$(git status 2>&1 | tee)"
+ grep -E 'new file:' <<<"$newfile" &> /dev/null
+ evaltask=$?
+ if [ "$evaltask" -eq 0 ]; then
+ printf '%s' '0'
+ else
+ printf '%s' '1'
+ fi
+}
+
+function _prompt_parse_git_deleted_file() {
+ local deleted_file
+ local evaltask
+ deleted_file="$(git status 2>&1 | tee)"
+ grep -E 'deleted:' <<<"$deleted_file" &> /dev/null
+ evaltask=$?
+ if [ "$evaltask" -eq 0 ]; then
+ printf '%s' '0'
+ else
+ printf '%s' '1'
+ fi
+}
+
+function _prompt_parse_git_renamed() {
+ local renamed
+ local evaltask
+ renamed="$(git status 2>&1 | tee)"
+ grep -E 'renamed:' <<<"$renamed" &> /dev/null
+ evaltask=$?
+ if [ "$evaltask" -eq 0 ]; then
+ printf '%s' '0'
+ else
+ printf '%s' '1'
+ fi
+}
+
+function _prompt_parse_git_unstage() {
+ local unstage
+ local evaltask
+ unstage="$(git status 2>&1 | tee)"
+ grep -E 'not staged' <<<"$unstage" &> /dev/null
+ evaltask=$?
+ if [ "$evaltask" -eq 0 ]; then
+ printf '%s' '0'
+ else
+ printf '%s' '1'
+ fi
+}
+
+function _prompt_parse_git_stage() {
+ local stage
+ local evaltask
+ stage="$(git status -s 2>&1 | tee)"
+ grep -E 'M' <<<"$stage" &> /dev/null
+ evaltask=$?
+ if [ "$evaltask" -eq 0 ]; then
+ printf '%s' '0'
+ else
+ printf '%s' '1'
+ fi
+}
+
+function _prompt_is_on_git() {
+ git rev-parse 2> /dev/null
+}
+
+function _prompt_get_git_status() {
+
+ _symbols "$@"
+
+ # Grab the git dirty and git behind
+ git_count="$(_git_dirty_count)"
+ dirty_branch="$(_prompt_parse_git_dirty)"
+ branch_ahead="$(_prompt_parse_git_ahead)"
+ branch_behind="$(_prompt_parse_git_behind)"
+ branch_stage="$(_prompt_parse_git_stage)"
+ branch_unstage="$(_prompt_parse_git_unstage)"
+ branch_untracked="$(_prompt_parse_git_untracked)"
+ branch_newfile="$(_prompt_parse_git_newfile)"
+ branch_deleted_file="$(_prompt_parse_git_deleted_file)"
+ branch_renamed="$(_prompt_parse_git_renamed)"
+
+ # Iterate through all the cases and if it matches, then printf
+ if [[ "$dirty_branch" == 0 && "$branch_ahead" == 0 && "$branch_behind" == 0 ]]; then
+ printf '%s%s' "$_dirty_unpushed_unpulled_symbol" "$git_count"
+
+ elif [[ "$branch_ahead" == 0 && "$branch_behind" == 0 ]]; then
+ printf '%s%s' "$_unpushed_unpulled_symbol" "$git_count"
+
+ elif [[ "$dirty_branch" == 0 && "$branch_ahead" == 0 ]]; then
+ printf '%s%s' "$_dirty_unpushed_symbol" "$git_count"
+
+ elif [[ "$branch_ahead" == 0 ]]; then
+ printf '%s%s' "$_unpushed_symbol" "$git_count"
+
+ elif [[ "$dirty_branch" == 0 && "$branch_behind" == 0 ]]; then
+ printf '%s%s' "$_dirty_unpulled_symbol" "$git_count"
+
+ elif [[ "$branch_behind" == 0 ]]; then
+ printf '%s%s' "$_unpulled_symbol" "$git_count"
+
+ elif [[ "$branch_unstage" == 0 && "$branch_untracked" == 0 ]]; then
+ printf '%s%s' "${_unstage_symbol}${_untracked_symbol}" "$git_count"
+
+ elif [[ "$branch_stage" == 0 && "$branch_untracked" == 0 ]]; then
+ printf '%s%s' "${_stage_symbol}${_untracked_symbol}" "$git_count"
+
+ elif [[ "$branch_stage" == 0 && "$branch_unstage" == 0 ]]; then
+ printf '%s%s' "$_unstage_symbol" "$git_count"
+
+ elif [[ "$branch_newfile" == 0 && "$branch_untracked" == 0 ]]; then
+ printf '%s%s' "${_newfile_symbol}${_untracked_symbol}" "$git_count"
+
+ elif [[ "$branch_untracked" == 0 ]]; then
+ printf '%s%s' "$_untracked_symbol" "$git_count"
+
+ elif [[ "$branch_stage" == 0 ]]; then
+ printf '%s%s' "$_stage_symbol" "$git_count"
+
+ elif [[ "$branch_newfile" == 0 ]]; then
+ printf '%s%s' "$_newfile_symbol" "$git_count"
+
+ elif [[ "$branch_deleted_file" == 0 ]]; then
+ printf '%s%s' "$_deleted_file_symbol" "$git_count"
+
+ elif [[ "$branch_renamed" == 0 ]]; then
+ printf '%s%s' "$_renamed_symbol" "$git_count"
+
+ elif [[ "$dirty_branch" == 0 ]]; then
+ printf '%s%s' "$_dirty_synced_symbol" "$git_count"
+
+ else # clean
+ printf '%s' "$_synced_symbol"
+ fi
+}
+
+_prompt_get_git_info() {
+ # Import colors
+ _colors_bash "$@"
+
+ # Grab the branch
+ branch="$(_get_git_branch)"
+
+ # If there are any branches
+ if [[ -n $branch ]]; then
+ # Printf the branch
+ output="$branch"
+
+ # Add on the git status
+ output="$output$(_prompt_get_git_status "$@")"
+
+ # Printf our output
+ printf '%b%s%b' "${BOLD}${LEMON}" "git:($output" "${BOLD}${LEMON})"
+ fi
+}