141 lines
3.9 KiB
Bash
Executable File
141 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# -*- coding: UTF-8 -*-
|
|
# gitstatus.sh -- produce the current git repo status on STDOUT
|
|
# Functionally equivalent to 'gitstatus.py', but written in bash (not python).
|
|
#
|
|
# Alan K. Stebbens <aks@stebbens.org> [http://github.com/aks]
|
|
|
|
# helper functions
|
|
count_lines() { echo "${1}" | egrep -c "^${2}" ; }
|
|
all_lines() { echo "${1}" | grep -v "^$" | wc -l ; }
|
|
|
|
if [[ -z "${__GIT_PROMPT_DIR-}" ]]; then
|
|
SOURCE="${BASH_SOURCE[0]}"
|
|
while [[ -h "${SOURCE}" ]]; do
|
|
DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )"
|
|
SOURCE="$(readlink "${SOURCE}")"
|
|
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
|
|
done
|
|
__GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )"
|
|
fi
|
|
|
|
if [[ "${__GIT_PROMPT_WITH_USERNAME_AND_REPO}" == "1" ]]; then
|
|
# returns "user/repo" from remote.origin.url git variable
|
|
#
|
|
# supports urls:
|
|
# https://user@bitbucket.org/user/repo.git
|
|
# https://github.com/user/repo.git
|
|
# git@github.com:user/repo.git
|
|
#
|
|
remote_url=$(git config --get remote.origin.url | sed 's|^.*//||; s/.*@//; s/[^:/]\+[:/]//; s/.git$//')
|
|
else
|
|
remote_url='.'
|
|
fi
|
|
|
|
gitsym=$( git symbolic-ref HEAD 2>/dev/null )
|
|
|
|
#If exit status OK, we have a branch
|
|
if [[ "${?}" == 0 ]]; then
|
|
# the current branch is the tail end of the symbolic reference
|
|
branch="${gitsym##refs/heads/}" # get the basename after "refs/heads/"
|
|
fi
|
|
|
|
gitstatus=$( git diff --name-status 2>&1 )
|
|
|
|
# if the diff is fatal, exit now
|
|
if [[ "${?}" != 0 ]]; then exit 0; fi
|
|
|
|
staged_files=$( git diff --staged --name-status )
|
|
|
|
num_changed=$(( $( all_lines "${gitstatus}" ) - $( count_lines "${gitstatus}" U ) ))
|
|
num_conflicts=$( count_lines "${staged_files}" U )
|
|
num_staged=$(( $( all_lines "${staged_files}" ) - num_conflicts ))
|
|
num_untracked=$( git ls-files --others --exclude-standard $(git rev-parse --show-cdup) | wc -l )
|
|
|
|
num_stashed=0
|
|
if [[ "${__GIT_PROMPT_IGNORE_STASH}" != "1" ]]; then
|
|
stash_file="$( git rev-parse --git-dir )/logs/refs/stash"
|
|
if [[ -e "${stash_file}" ]]; then
|
|
while IFS='' read -r wcline || [[ -n "${wcline}" ]]; do
|
|
((num_stashed++))
|
|
done < "${stash_file}"
|
|
fi
|
|
fi
|
|
|
|
clean=0
|
|
if (( num_changed == 0 && num_staged == 0 && num_untracked == 0 && num_stashed == 0 && num_conflicts == 0 )) ; then
|
|
clean=1
|
|
fi
|
|
|
|
remote=""
|
|
upstream=""
|
|
|
|
if [[ -z "${branch-}" ]]; then
|
|
tag=$( git describe --tags --exact-match 2>/dev/null )
|
|
if [[ -n "${tag}" ]]; then
|
|
branch="${tag}"
|
|
else
|
|
branch="_PREHASH_$( git rev-parse --short HEAD )"
|
|
fi
|
|
else
|
|
remote_name=$( git config "branch.${branch}.remote" )
|
|
|
|
if [[ -n "$remote_name" ]]; then
|
|
merge_name=$( git config "branch.${branch}.merge" )
|
|
else
|
|
remote_name='origin'
|
|
merge_name="refs/heads/${branch}"
|
|
fi
|
|
|
|
if [[ "${remote_name}" == '.' ]]; then
|
|
remote_ref="${merge_name}"
|
|
else
|
|
remote_ref="refs/remotes/${remote_name}/${merge_name##refs/heads/}"
|
|
fi
|
|
|
|
# detect if the local branch have a remote tracking branch
|
|
upstream=$( git rev-parse --abbrev-ref "${branch}"@{upstream} 2>&1 )
|
|
|
|
if [[ "${?}" == 0 ]]; then
|
|
# get the revision list, and count the leading "<" and ">"
|
|
revgit=$( git rev-list --left-right "${remote_ref}...HEAD" 2>/dev/null )
|
|
if [[ "${?}" == 0 ]]; then
|
|
num_revs=$( all_lines "${revgit}" )
|
|
num_ahead=$( count_lines "${revgit}" "^>" )
|
|
num_behind=$(( num_revs - num_ahead ))
|
|
if (( num_behind > 0 )) ; then
|
|
remote="${remote}_BEHIND_${num_behind}"
|
|
fi
|
|
if (( num_ahead > 0 )) ; then
|
|
remote="${remote}_AHEAD_${num_ahead}"
|
|
fi
|
|
fi
|
|
else
|
|
remote='_NO_REMOTE_TRACKING_'
|
|
remote_url='.'
|
|
unset upstream
|
|
fi
|
|
fi
|
|
|
|
if [[ -z "${remote:+x}" ]] ; then
|
|
remote='.'
|
|
fi
|
|
|
|
if [[ -z "${upstream:+x}" ]] ; then
|
|
upstream='^'
|
|
fi
|
|
|
|
printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" \
|
|
"${branch}" \
|
|
"${remote}" \
|
|
"${remote_url}" \
|
|
"${upstream}" \
|
|
"${num_staged}" \
|
|
"${num_conflicts}" \
|
|
"${num_changed}" \
|
|
"${num_untracked// /}" \
|
|
"${num_stashed}" \
|
|
"${clean}"
|
|
|
|
exit
|