Created
February 20, 2021 18:05
-
-
Save toonetown/f7e905f6c730043e84a0b918332fc24d to your computer and use it in GitHub Desktop.
SCM-Prompt script (originally at https://bitbucket.org/facebook/hg-experimental/get/2358e84ae63d.zip)
This file contains 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
# Copyright (C) 2015 Facebook, Inc | |
# Maintained by Ryan McElroy <[email protected]> | |
# | |
# Inspiration and derivation from git-completion.bash by Shawn O. Pearce. | |
# | |
# Distributed under the GNU General Public License, version 2.0. | |
# | |
# ======================================================================== | |
# | |
# Quickly determines the and emits some useful information about the state | |
# of your current mercurial or git repository. Useful for PS1 prompts. | |
# | |
# Design goals: | |
# * Useful for both git and mercurial | |
# * Portable to both zsh and bash | |
# * Portable to both Mac (BSD-based utils) and Linux (GNU-based utils) | |
# * As fast as possible given the above constraints (few command invocations) | |
# * Avoids invoking git or mercurial, which may be slow on large repositories | |
# | |
# To use from zsh: | |
# | |
# NOTE! the single quotes are important; if you use double quotes | |
# then the prompt won't change when you chdir or checkout different | |
# branches! | |
# | |
# . /path/to/scm-prompt | |
# setopt PROMPT_SUBST | |
# export PS1='$(_scm_prompt)$USER@%m:%~%% ' | |
# | |
# To use from bash: | |
# | |
# . /path/to/scm-prompt | |
# export PS1="\$(_scm_prompt)\u@\h:\W\$ " | |
# | |
# NOTE! You *EITHER* need to single-quote the whole thing *OR* back-slash | |
# the $(...) (as above), but not both. Which one you use depends on if | |
# you need the rest of your PS1 to interpolate variables. | |
# | |
# You may additionally pass a format-string to the scm_info command. This | |
# allows you to control the format of the prompt string without interfering | |
# with the prompt outside of a mercurial or git repository. For example: | |
# | |
# $(_scm_prompt "%s") | |
# | |
# The default format string is " (%s)" (note the space) | |
# | |
# ========================================================================= | |
# | |
_scm_prompt() | |
{ | |
# find out if we're in a git or hg repo by looking for the control dir | |
local d git hg fmt | |
fmt=$1 | |
if [[ -z "$fmt" ]]; then | |
if [ -n "$WANT_OLD_SCM_PROMPT" ]; then | |
fmt="%s" | |
else | |
# Be compatable with __git_ps1. In particular: | |
# - provide a space for the user so that they don't have to have | |
# random extra spaces in their prompt when not in a repo | |
# - provide parens so it's differentiated from other crap in their prompt | |
fmt=" (%s)" | |
fi | |
fi | |
d=$PWD | |
while : ; do | |
if test -d "$d/.git" ; then | |
git=$d | |
break | |
elif test -d "$d/.hg" ; then | |
hg=$d | |
break | |
fi | |
test "$d" = / && break | |
# portable "realpath" equivalent | |
d=$(cd -P "$d/.." && echo "$PWD") | |
done | |
local br | |
if test -n "$hg" ; then | |
local extra | |
if [ -f "$hg/.hg/bisect.state" ]; then | |
extra="|BISECT" | |
elif [ -f "$hg/.hg/histedit-state" ]; then | |
extra="|HISTEDIT" | |
elif [ -f "$hg/.hg/graftstate" ]; then | |
extra="|GRAFT" | |
elif [ -f "$hg/.hg/unshelverebasestate" ]; then | |
extra="|UNSHELVE" | |
elif [ -f "$hg/.hg/rebasestate" ]; then | |
extra="|REBASE" | |
elif [ -d "$hg/.hg/merge" ]; then | |
extra="|MERGE" | |
fi | |
local dirstate=$(test -f "$hg/.hg/dirstate" && \ | |
hexdump -vn 20 -e '1/1 "%02x"' "$hg/.hg/dirstate" || \ | |
echo "empty") | |
local current="$hg/.hg/bookmarks.current" | |
if [[ -f "$current" ]]; then | |
br=$(cat "$current") | |
# check to see if active bookmark needs update (eg, moved after pull) | |
local marks="$hg/.hg/bookmarks" | |
if [[ -f "$hg/.hg/sharedpath" && -f "$hg/.hg/shared" ]] && | |
grep -q '^bookmarks$' "$hg/.hg/shared"; then | |
marks="$(cat $hg/.hg/sharedpath)/bookmarks" | |
fi | |
if [[ -z "$extra" ]] && [[ -f "$marks" ]]; then | |
local markstate=$(grep --color=never " $br$" "$marks" | cut -f 1 -d ' ') | |
if [[ $markstate != "$dirstate" ]]; then | |
extra="|UPDATE_NEEDED" | |
fi | |
fi | |
else | |
br=$(echo "$dirstate" | cut -c 1-7) | |
fi | |
local remote="$hg/.hg/remotenames" | |
if [[ -f "$remote" ]]; then | |
local marks=$(grep --color=never "^$dirstate bookmarks" "$remote" | \ | |
cut -f 3 -d ' ' | tr '\n' '|' | sed -e 's/|$//') | |
if [[ -n "$marks" ]]; then | |
br="$br|$marks" | |
fi | |
fi | |
local branch | |
if [[ -f "$hg/.hg/branch" ]]; then | |
branch=$(cat "$hg/.hg/branch") | |
if [[ $branch != "default" ]]; then | |
br="$br|$branch" | |
fi | |
fi | |
br="$br$extra" | |
elif test -n "$git" ; then | |
if test -f "$git/.git/HEAD" ; then | |
read br < "$git/.git/HEAD" | |
case $br in | |
ref:\ refs/heads/*) br=${br#ref: refs/heads/} ;; | |
*) br=$(echo "$br" | cut -c 1-7) ;; | |
esac | |
if [ -f "$git/.git/rebase-merge/interactive" ]; then | |
b="$(cat "$git/.git/rebase-merge/head-name")" | |
b=${b#refs/heads/} | |
br="$br|REBASE-i|$b" | |
elif [ -d "$git/.git/rebase-merge" ]; then | |
b="$(cat "$git/.git/rebase-merge/head-name")" | |
b=${b#refs/heads/} | |
br="$br|REBASE-m|$b" | |
else | |
if [ -d "$git/.git/rebase-apply" ]; then | |
if [ -f "$git/.git/rebase-apply/rebasing" ]; then | |
b="$(cat "$git/.git/rebase-apply/head-name")" | |
b=${b#refs/heads/} | |
br="$br|REBASE|$b" | |
elif [ -f "$git/.git/rebase-apply/applying" ]; then | |
br="$br|AM" | |
else | |
br="$br|AM/REBASE" | |
fi | |
elif [ -f "$git/.git/CHERRY_PICK_HEAD" ]; then | |
br="$br|CHERRY-PICKING" | |
elif [ -f "$git/.git/REVERT_HEAD" ]; then | |
br="$br|REVERTING" | |
elif [ -f "$git/.git/MERGE_HEAD" ]; then | |
br="$br|MERGE" | |
elif [ -f "$git/.git/BISECT_LOG" ]; then | |
br="$br|BISECT" | |
fi | |
fi | |
fi | |
fi | |
if [ -n "$br" ]; then | |
printf "$fmt" "$br" | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment