Skip to content

Instantly share code, notes, and snippets.

@theosp
Created October 10, 2010 00:55
Show Gist options
  • Save theosp/618792 to your computer and use it in GitHub Desktop.
Save theosp/618792 to your computer and use it in GitHub Desktop.
#!/bin/bash
# When under a git repository this script adds the bash prompt indicators about
# the repository status.
#
# the status includes the current branch and colored circles that have the
# following meaning:
# Green: there are staged changes,
# Yellow: if there are unstaged changes
# Red: if there are new untracked-yet-unignored files
#
# The idea for this script came from:
# http://briancarper.net/blog/570/git-info-in-your-zsh-prompt
#
# Author: Daniel Chcouri <333222@gmail.com>; http://www.blogy.me/
# License: GPL2
# Colors definitions
black=$(tput setaf 0)
bold_black=$(tput setaf 0; tput bold)
red=$(tput setaf 1)
bold_red=$(tput setaf 1; tput bold)
green=$(tput setaf 2)
bold_green=$(tput setaf 2; tput bold)
yellow=$(tput setaf 3)
bold_yellow=$(tput setaf 3; tput bold)
blue=$(tput setaf 4)
bold_blue=$(tput setaf 4; tput bold)
magenta=$(tput setaf 5)
bold_magenta=$(tput setaf 5; tput bold)
cyan=$(tput setaf 6)
bold_cyan=$(tput setaf 6; tput bold)
white=$(tput setaf 7)
bold_white=$(tput setaf 7; tput bold)
reset_colors=$(tput sgr0)
# git.is_rep(path=".")
#
# Gets a path and returns 0 if it's under a git repository; 1 otherwise
#
# If under git repository it prints the path to the .git dir to stdout
git.is_rep ()
{
local path="${1:-.}"
# First, get the path's absolute path
cd "$path"
path="$(pwd -P)/"
cd - > /dev/null
while [[ "$path" != '' ]]
do
if [[ -e "${path}.git" ]]
then
echo "${path}.git"
return 0
fi
if [[ "$path" == '/' ]]
then
return 1
else
path="${path%/*/}/"
fi
done
}
# git.current_branch()
#
# echo the current git branch
#
# return 1 if not under a git repository, 2 if branch is detached or unknown
git.current_branch ()
{
local dot_git_path branch
if ! dot_git_path="$(git.is_rep)"
then
return 1
fi
# The following was forked from:
# http://aaroncrane.co.uk/2009/03/git_branch_prompt/
head=$(< "$dot_git_path/HEAD")
if [[ $head == ref:\ refs/heads/* ]]; then
branch="${head#*/*/}"
echo "$branch"
return 0
elif [[ $head != '' ]]; then
branch='detached'
echo "$branch"
return 2
else
branch='unknown'
echo "$branch"
return 2
fi
}
# git.current_branch()
#
# return a list of space-separated booleans that represent the current git
# status
#
# Meaning of each position:
# 0 untracked
# 1 updated in index
# 2 added to index
# 3 deleted from index
# 4 renamed in index
# 5 copied in index
# 6 work tree changed since index
# 7 deleted in work tree
# 8 unmerged, both deleted
# 9 unmerged, added by us
# 10 unmerged, deleted by them
# 11 unmerged, added by them
# 12 unmerged, deleted by us
# 13 unmerged, both added
# 14 unmerged, both modified
git.status ()
{
local index="$(git status --porcelain 2> /dev/null)"
local flags=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
while IFS= read -r line; do
case "${line:0:1}"
in
# untracked
"?")
flags[0]=1
;;
# updated in index
"M")
flags[1]=1
;;
# added to index
"A")
flags[2]=1
;;
# deleted from index
"D")
flags[3]=1
;;
# renamed in index
"R")
flags[4]=1
;;
# copied in index
"D")
flags[5]=1
;;
esac
case "${line:1:1}"
in
# work tree changed since index
"M")
flags[6]=1
;;
# deleted in work tree
"D")
flags[7]=1
;;
esac
case "${line:0:2}"
in
# unmerged, both deleted
"DD")
flags[8]=1
;;
# unmerged, added by us
"AU")
flags[9]=1
;;
# unmerged, deleted by them
"UD")
flags[10]=1
;;
# unmerged, added by them
"UA")
flags[11]=1
;;
# unmerged, deleted by us
"DU")
flags[12]=1
;;
# unmerged, both added
"AA")
flags[13]=1
;;
# unmerged, both modified
"UU")
flags[14]=1
;;
esac
done <<< "$index"
echo "${flags[@]}"
return 0
}
prompt_command_git_status ()
{
local result="$bold_blue$(git.current_branch)"
local status=($(git.status))
if (( ${status[1]} == 1 )) || (( ${status[2]} == 2 )) || (( ${status[3]} == 3 )) || (( ${status[4]} == 4 )) || (( ${status[5]} == 5 ))
then
#echo "staged changes"
result+="$bold_green●$reset_colors"
fi
if (( ${status[6]} == 1 )) || (( ${status[7]} == 1 ))
then
#echo "unstaged changes"
result+="$bold_yellow●$reset_colors"
fi
if (( ${status[0]} == 1 ))
then
#echo "untracked changes"
result+="$bold_red●$reset_colors"
fi
echo "$result"
}
export original_ps="$PS1"
PROMPT_COMMAND+="$(cat <<EOF
if git.is_rep > /dev/null
then
export PS1="$bold_green\u@\h $bold_blue\W [$reset_colors\$(prompt_command_git_status)$bold_blue] \$ $reset_colors"
else
export PS1="\$original_ps"
fi
EOF
)"
# vim:ft=bash:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment