Skip to content

Commit

Permalink
git: add support for tgitstatus
Browse files Browse the repository at this point in the history
gitstatus is faster especially on large repositories with many changes.
This is an alternative to untracked cache and fsmonitor.
  • Loading branch information
SuperSandro2000 committed Oct 12, 2020
1 parent f5d0b29 commit 2cb8ee6
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 28 deletions.
1 change: 1 addition & 0 deletions config/settings.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ SBP_THEME_COLOR=${SBP_THEME_COLOR:-'default-256'}
SBP_THEME_LAYOUT=${SBP_THEME_LAYOUT:-'plain'}

# Default segment settings
SEGMENTS_GIT_GITSTATUS=${SEGMENTS_GIT_GITSTATUS:-"false"}
SEGMENTS_K8S_DEFAULT_USER=${SEGMENTS_K8S_DEFAULT_USER:-"$USER"}
SEGMENTS_K8S_HIDE_CLUSTER=${SEGMENTS_K8S_HIDE_CLUSTER:-0}
SEGMENTS_LOAD_THRESHOLD=${SEGMENTS_LOAD_THRESHOLD:-50}
Expand Down
1 change: 1 addition & 0 deletions config/settings.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ else
fi

# Segment specific settings
SEGMENTS_GIT_GITSTATUS='false'
SEGMENTS_K8S_DEFAULT_USER="$USER"
SEGMENTS_K8S_HIDE_CLUSTER=0
SEGMENTS_LOAD_THRESHOLD=50
Expand Down
5 changes: 2 additions & 3 deletions sbp.bash
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ _sbp_set_prompt() {
title="${HOSTNAME:-ssh}:${title}"
fi
printf '\e]2;%s\007' "$title"

PS1=$(bash "${SBP_PATH}/src/main.bash" "$command_status" "$command_duration")
# gitstatus.plugin.sh requires an interactive shell
PS1=$(bash --noediting -noprofile --norc -i "${SBP_PATH}/src/main.bash" "$command_status" "$command_duration" "$GITSTATUS_DIR" "$GITSTATUS_DAEMON_PID" "$_GITSTATUS_REQ_FD" "$_GITSTATUS_RESP_FD")
[[ -n "$SBP_DEBUG" ]] && debug::tick_timer "Done"

}

_sbp_pre_exec() {
Expand Down
11 changes: 10 additions & 1 deletion src/main.bash
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
#! /usr/bin/env bash
#!/usr/bin/env bash

# turn off history to not pollute the users history with our commands
# first turn of the history file to not add the set afterwards to it
export HISTFILE=/dev/null
set +o history

# shellcheck source=src/debug.bash
source "${SBP_PATH}/src/debug.bash"
Expand All @@ -13,6 +18,10 @@ configure::load_config

readonly COMMAND_EXIT_CODE=$1
readonly COMMAND_DURATION=$2
readonly GITSTATUS_DIR=$3
readonly GITSTATUS_DAEMON_PID=$4
readonly _GITSTATUS_REQ_FD=$5
readonly _GITSTATUS_RESP_FD=$6

main::main() {
execute::execute_prompt_hooks
Expand Down
96 changes: 72 additions & 24 deletions src/segments/git.bash
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
#! /usr/bin/env bash

segments::git() {
local max_length=$SEGMENTS_MAX_LENGTH

local incoming_icon="${SEGMENTS_GIT_INCOMING_ICON:-↓}"
local outgoing_icon="${SEGMENTS_GIT_OUTGOING_ICON:-↑}"

local branch_only="${SEGMENTS_GIT_BRANCH_ONLY:-false}"

local path=${PWD}
while [[ $path ]]; do
if [[ -d "${path}/.git" ]]; then
local git_folder="${path}/.git"
break
fi
path=${path%/*}
done

[[ -z "$git_folder" ]] && exit 0
if [[ "$PWD" == "$git_folder" ]]; then
print_themed_segment 'normal' '.git/'
return 0
fi

segments::git::native() {
if [[ "$branch_only" == false ]]; then
local git_status="$(git status --porcelain --branch 2>/dev/null)"

Expand Down Expand Up @@ -61,10 +39,11 @@ segments::git() {
outgoing_filled="${upstream_stripped/ahead / ${outgoing_icon}}"
upstream_status="${outgoing_filled/behind / ${incoming_icon}}"
fi
;;
esac
done <<< "$git_status"

local git_state="${additions_icon}${additions#0}${modifications_icon}${modifications#0}${deletions_icon}${deletions#0}${untracked_icon}${untracked#0}"
git_state="${additions_icon}${additions#0}${modifications_icon}${modifications#0}${deletions_icon}${deletions#0}${untracked_icon}${untracked#0}"

# git status does not support detached head
if [[ "$branch" != 'HEAD' ]]; then
Expand All @@ -75,6 +54,75 @@ segments::git() {
else
git_head=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
fi
}

segments::git::gitstatus() {
# TODO: keep the source from sbp.bash
if [[ -n ${GITSTATUS_DIR:-} ]]; then
source "$GITSTATUS_DIR" || return
elif [[ ${BASH_SOURCE[0]} == */* ]]; then
source "${BASH_SOURCE[0]%/*}/gitstatus.plugin.sh" || return
else
source gitstatus.plugin.sh || return
fi

gitstatus_query "$@" || return 1 # error
[[ $VCS_STATUS_RESULT == ok-sync ]] || return 0 # not a git repo

git_head="${VCS_STATUS_LOCAL_BRANCH:-${VCS_STATUS_TAG:-${VCS_STATUS_COMMIT:-}}}"

if [[ "$branch_only" == false ]]; then
VCS_STATUS_DELETED=$((VCS_STATUS_NUM_STAGED_DELETED + VCS_STATUS_NUM_UNSTAGED_DELETED))

if [[ $VCS_STATUS_NUM_STAGED_NEW -gt 0 ]]; then
git_state=' +'${VCS_STATUS_NUM_STAGED_NEW#0}
fi
if [[ $VCS_STATUS_NUM_UNSTAGED -gt 0 ]]; then
git_state=$git_state' ~'${VCS_STATUS_NUM_UNSTAGED#0}
fi
if [[ $VCS_STATUS_DELETED -gt 0 ]]; then
git_state=$git_state' -'${VCS_STATUS_DELETED#0}
fi
if [[ $VCS_STATUS_NUM_UNTRACKED -gt 0 ]]; then
git_state=$git_state' ?'${VCS_STATUS_NUM_UNTRACKED#0}
fi
if [[ $VCS_STATUS_COMMITS_AHEAD -gt 0 ]]; then
upstream_status="$outgoing_icon$VCS_STATUS_COMMITS_AHEAD "
fi
if [[ $VCS_STATUS_COMMITS_BEHIND -gt 0 ]]; then
upstream_status="$upstream_status $incoming_icon$VCS_STATUS_COMMITS_BEHIND"
fi
fi
}

segments::git() {
max_length=$SEGMENTS_MAX_LENGTH

incoming_icon="${SEGMENTS_GIT_INCOMING_ICON:-↓}"
outgoing_icon="${SEGMENTS_GIT_OUTGOING_ICON:-↑}"

branch_only="${SEGMENTS_GIT_BRANCH_ONLY:-false}"

local path=${PWD}
while [[ $path ]]; do
if [[ -d "${path}/.git" ]]; then
local git_folder="${path}/.git"
break
fi
path=${path%/*}
done

[[ -z "$git_folder" ]] && exit 0
if [[ "$PWD" == "$git_folder" ]]; then
print_themed_segment 'normal' '.git/'
return 0
fi

if [[ $SEGMENTS_GIT_GITSTATUS == true ]]; then
segments::git::gitstatus
else
segments::git::native
fi

git_size=$(( ${#git_state} + ${#SEGMENTS_GIT_ICON} + ${#git_head} + ${#upstream_status} ))

Expand Down

0 comments on commit 2cb8ee6

Please sign in to comment.