Last active
December 15, 2021 01:34
-
-
Save PhilippeCarphin/eff52f2ed7eee924b6b8ff2a955f33ae to your computer and use it in GitHub Desktop.
Example use of git-prompt.sh with some nice features
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Download the official git-prompt.sh with | |
# wget https://raw.githubusercontent.com/git/git/v$(git --version | awk '{print $3}')/contrib/completion/git-prompt.sh -O ~/.git-prompt.sh | |
# Gives the __git_ps1 function used in __my_git_ps1 | |
source ~/.git-prompt.sh | |
GIT_PS1_SHOWUNTRACKEDFILES=true | |
GIT_PS1_SHOWUPSTREAM=verbose | |
GIT_PS1_SHOWCOLORHINTS=true | |
GIT_PS1_SHOWDIRTYSTATE=true | |
PROMPT_COMMAND=__my_git_ps1 | |
################################################################################ | |
# Calls __git_ps1 which sets PS1 | |
# Uses the 3 argument form which results in something like | |
# PS1=$1$(printf -- $3 $gitstring)$2 | |
# Note only the 2 and 3 argument forms set PS1. | |
################################################################################ | |
function __my_git_ps1(){ | |
# save exit code of previous command to use in prompt | |
previous_exit_code=$? | |
# Color of the non-git part | |
c="\[\033[35m\]" | |
nc="\[\033[0m\]" | |
ps1_exit_code=$(__ps1_format_exit_code $previous_exit_code) | |
# Arguments for the 3 arg form of __git_ps1 | |
pre="${ps1_exit_code}${c}\u@\h:$(git_pwd)${nc}" | |
post="${c} \\\$${nc} " | |
gitstring_format=" (%s$(__git_time_since_last_commit))" | |
# This sets PS1 (something like PS1=$1$(printf -- $3 $gitstring)$2) | |
# the '%s' in gitstring_format gets replaced with $gitstring | |
# which has all the info produced by __git_ps1 | |
__git_ps1 "${pre}" "${post}" "${gitstring_format}" | |
} | |
################################################################################ | |
# Prints $PWD when outside a git repo and a shortened version of PWD when | |
# inside a git repo. | |
# | |
# When in a git repo, strip everything from PWD up to but excluding the | |
# basename of the directory that is the root of the repo: | |
# | |
# Shortens | |
# /home/phc001/Repositories/gitlab.science.gc.ca/phc001/my-git-repo/a/b/c | |
# to | |
# my-git-repo/a/b/c | |
################################################################################ | |
function git_pwd() { | |
if [[ $(git rev-parse --is-inside-work-tree 2>/dev/null) == true ]] ; then | |
local repo_dir=$(git rev-parse --show-toplevel 2>/dev/null) | |
local outer=$(basename $repo_dir) | |
local inner=$(git rev-parse --show-prefix 2>/dev/null) | |
echo "${outer}/${inner}" | |
else | |
echo '\w' | |
fi | |
} | |
################################################################################ | |
# Print an exit code supplied as an argument. | |
# Zero is printed in bold green, anything else is printed in bold red | |
################################################################################ | |
function __ps1_format_exit_code(){ | |
local previous_exit_code=$1 | |
if [[ $previous_exit_code == 0 ]] ; then | |
color="\[\033[1;32m\]" | |
else | |
color="\[\033[1;31m\]" | |
fi | |
printf " ${color}$previous_exit_code\[\033[0m\] " | |
} | |
################################################################################ | |
# Print time since last commit in a format based on the length of time | |
################################################################################ | |
__git_time_since_last_commit() { | |
# This checks if we are in a repo an that there is a commit | |
if ! git log -n 1 > /dev/null 2>&1; then | |
return | |
fi | |
# If inside GIT_DIR, we can't do the git diff commands to determine | |
# wheher or not to show the time. So we would like to CD to the repo | |
# root to run those git diff commands. | |
# To get the repo root from inside .git, we assume the GIT_DIR is called | |
# .git and that '/.git' does not occur somewhere else in the path. | |
# This is a reasonable assumption | |
local hackish_toplevel=${PWD%%/\.git*} | |
# Don't show anything if there are no staged or unstaged changes | |
if (cd ${hackish_toplevel} && git diff --no-ext-diff --quiet && git diff --no-ext-diff --cached --quiet) ; then | |
return | |
fi | |
last_commit_unix_timestamp=$(git log --pretty=format:'%at' -1 2> /dev/null) | |
now_unix_timestamp=$(date +%s) | |
seconds_since_last_commit=$(($now_unix_timestamp - $last_commit_unix_timestamp)) | |
format_seconds $seconds_since_last_commit | |
} | |
################################################################################ | |
# Formats a duration in seconds to DD:HH:MM or HH:MM if the number of days is 0. | |
# | |
# Because this is used for the time since the last commit, seconds are irrelevant | |
# and the time is rounded to a whole minute. | |
################################################################################ | |
format_seconds(){ | |
local seconds=$1 | |
# Totals | |
local MINUTES=$(($seconds / 60)) | |
local HOURS=$(($seconds /3600)) | |
# Sub-hours and sub-minutes | |
local seconds_per_day=$((60*60*24)) | |
local DAYS=$(($seconds / $seconds_per_day)) | |
local SUB_HOURS=$(( $HOURS % 24)) | |
local SUB_MINUTES=$(( $MINUTES % 60)) | |
# Display | |
if [ "$DAYS" -gt 1 ]; then | |
echo " ${DAYS}d${SUB_HOURS}h${SUB_MINUTES}m" | |
elif [ "$HOURS" -gt 0 ]; then | |
echo " ${HOURS}h${SUB_MINUTES}m" | |
else | |
echo " ${MINUTES}m" | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment