mirror of
				https://github.com/ohmyzsh/ohmyzsh.git
				synced 2024-05-11 05:55:17 +00:00 
			
		
		
		
	lib: safety fix and speed-ups for git.zsh prompt functions (#7804)
This commit is contained in:
		
							
								
								
									
										93
									
								
								lib/git.zsh
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								lib/git.zsh
									
									
									
									
									
								
							| @@ -1,9 +1,20 @@ | ||||
| # The git prompt's git commands are read-only and should not interfere with | ||||
| # other processes. This environment variable is equivalent to running with `git | ||||
| # --no-optional-locks`, but falls back gracefully for older versions of git. | ||||
| # See git(1) for and git-status(1) for a description of that flag. | ||||
| # | ||||
| # We wrap in a local function instead of exporting the variable directly in | ||||
| # order to avoid interfering with manually-run git commands by the user. | ||||
| function __git_prompt_git() { | ||||
|   GIT_OPTIONAL_LOCKS=0 command git "$@" | ||||
| } | ||||
|  | ||||
| # Outputs current branch info in prompt format | ||||
| function git_prompt_info() { | ||||
|   local ref | ||||
|   if [[ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then | ||||
|     ref=$(command git symbolic-ref HEAD 2> /dev/null) || \ | ||||
|     ref=$(command git rev-parse --short HEAD 2> /dev/null) || return 0 | ||||
|   if [[ "$(__git_prompt_git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then | ||||
|     ref=$(__git_prompt_git symbolic-ref HEAD 2> /dev/null) || \ | ||||
|     ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) || return 0 | ||||
|     echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX" | ||||
|   fi | ||||
| } | ||||
| @@ -13,7 +24,7 @@ function parse_git_dirty() { | ||||
|   local STATUS | ||||
|   local -a FLAGS | ||||
|   FLAGS=('--porcelain') | ||||
|   if [[ "$(command git config --get oh-my-zsh.hide-dirty)" != "1" ]]; then | ||||
|   if [[ "$(__git_prompt_git config --get oh-my-zsh.hide-dirty)" != "1" ]]; then | ||||
|     if [[ "${DISABLE_UNTRACKED_FILES_DIRTY:-}" == "true" ]]; then | ||||
|       FLAGS+='--untracked-files=no' | ||||
|     fi | ||||
| @@ -27,7 +38,7 @@ function parse_git_dirty() { | ||||
|         FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}" | ||||
|         ;; | ||||
|     esac | ||||
|     STATUS=$(command git status ${FLAGS} 2> /dev/null | tail -n1) | ||||
|     STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -n1) | ||||
|   fi | ||||
|   if [[ -n $STATUS ]]; then | ||||
|     echo "$ZSH_THEME_GIT_PROMPT_DIRTY" | ||||
| @@ -39,10 +50,10 @@ function parse_git_dirty() { | ||||
| # Gets the difference between the local and remote branches | ||||
| function git_remote_status() { | ||||
|     local remote ahead behind git_remote_status git_remote_status_detailed | ||||
|     remote=${$(command git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/} | ||||
|     remote=${$(__git_prompt_git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/} | ||||
|     if [[ -n ${remote} ]]; then | ||||
|         ahead=$(command git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l) | ||||
|         behind=$(command git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l) | ||||
|         ahead=$(__git_prompt_git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l) | ||||
|         behind=$(__git_prompt_git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l) | ||||
|  | ||||
|         if [[ $ahead -eq 0 ]] && [[ $behind -eq 0 ]]; then | ||||
|             git_remote_status="$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE" | ||||
| @@ -71,11 +82,11 @@ function git_remote_status() { | ||||
| # it's not a symbolic ref, but in a Git repo. | ||||
| function git_current_branch() { | ||||
|   local ref | ||||
|   ref=$(command git symbolic-ref --quiet HEAD 2> /dev/null) | ||||
|   ref=$(__git_prompt_git symbolic-ref --quiet HEAD 2> /dev/null) | ||||
|   local ret=$? | ||||
|   if [[ $ret != 0 ]]; then | ||||
|     [[ $ret == 128 ]] && return  # no git repo. | ||||
|     ref=$(command git rev-parse --short HEAD 2> /dev/null) || return | ||||
|     ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) || return | ||||
|   fi | ||||
|   echo ${ref#refs/heads/} | ||||
| } | ||||
| @@ -83,8 +94,8 @@ function git_current_branch() { | ||||
|  | ||||
| # Gets the number of commits ahead from remote | ||||
| function git_commits_ahead() { | ||||
|   if command git rev-parse --git-dir &>/dev/null; then | ||||
|     local commits="$(git rev-list --count @{upstream}..HEAD 2>/dev/null)" | ||||
|   if __git_prompt_git rev-parse --git-dir &>/dev/null; then | ||||
|     local commits="$(__git_prompt_git rev-list --count @{upstream}..HEAD 2>/dev/null)" | ||||
|     if [[ -n "$commits" && "$commits" != 0 ]]; then | ||||
|       echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX" | ||||
|     fi | ||||
| @@ -93,8 +104,8 @@ function git_commits_ahead() { | ||||
|  | ||||
| # Gets the number of commits behind remote | ||||
| function git_commits_behind() { | ||||
|   if command git rev-parse --git-dir &>/dev/null; then | ||||
|     local commits="$(git rev-list --count HEAD..@{upstream} 2>/dev/null)" | ||||
|   if __git_prompt_git rev-parse --git-dir &>/dev/null; then | ||||
|     local commits="$(__git_prompt_git rev-list --count HEAD..@{upstream} 2>/dev/null)" | ||||
|     if [[ -n "$commits" && "$commits" != 0 ]]; then | ||||
|       echo "$ZSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$ZSH_THEME_GIT_COMMITS_BEHIND_SUFFIX" | ||||
|     fi | ||||
| @@ -103,21 +114,21 @@ function git_commits_behind() { | ||||
|  | ||||
| # Outputs if current branch is ahead of remote | ||||
| function git_prompt_ahead() { | ||||
|   if [[ -n "$(command git rev-list origin/$(git_current_branch)..HEAD 2> /dev/null)" ]]; then | ||||
|   if [[ -n "$(__git_prompt_git rev-list origin/$(git_current_branch)..HEAD 2> /dev/null)" ]]; then | ||||
|     echo "$ZSH_THEME_GIT_PROMPT_AHEAD" | ||||
|   fi | ||||
| } | ||||
|  | ||||
| # Outputs if current branch is behind remote | ||||
| function git_prompt_behind() { | ||||
|   if [[ -n "$(command git rev-list HEAD..origin/$(git_current_branch) 2> /dev/null)" ]]; then | ||||
|   if [[ -n "$(__git_prompt_git rev-list HEAD..origin/$(git_current_branch) 2> /dev/null)" ]]; then | ||||
|     echo "$ZSH_THEME_GIT_PROMPT_BEHIND" | ||||
|   fi | ||||
| } | ||||
|  | ||||
| # Outputs if current branch exists on remote or not | ||||
| function git_prompt_remote() { | ||||
|   if [[ -n "$(command git show-ref origin/$(git_current_branch) 2> /dev/null)" ]]; then | ||||
|   if [[ -n "$(__git_prompt_git show-ref origin/$(git_current_branch) 2> /dev/null)" ]]; then | ||||
|     echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS" | ||||
|   else | ||||
|     echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING" | ||||
| @@ -127,62 +138,50 @@ function git_prompt_remote() { | ||||
| # Formats prompt string for current git commit short SHA | ||||
| function git_prompt_short_sha() { | ||||
|   local SHA | ||||
|   SHA=$(command git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" | ||||
|   SHA=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" | ||||
| } | ||||
|  | ||||
| # Formats prompt string for current git commit long SHA | ||||
| function git_prompt_long_sha() { | ||||
|   local SHA | ||||
|   SHA=$(command git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" | ||||
|   SHA=$(__git_prompt_git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" | ||||
| } | ||||
|  | ||||
| # Get the status of the working tree | ||||
| function git_prompt_status() { | ||||
|   emulate -L zsh | ||||
|  | ||||
|   local INDEX STATUS | ||||
|   INDEX=$(command git status --porcelain -b 2> /dev/null) | ||||
|   INDEX=$(__git_prompt_git status --porcelain -b 2> /dev/null) || return 0 | ||||
|   STATUS="" | ||||
|   if $(echo "$INDEX" | command grep -E '^\?\? ' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)\\?\\? ' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^A  ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^M  ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^MM ' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)(A |M |MM) ' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^ M ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^AM ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^MM ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^ T ' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)([ AM]M| T) ' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^R  ' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)R  ' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^ D ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^D  ' &> /dev/null); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" | ||||
|   elif $(echo "$INDEX" | grep '^AD ' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)([A ]D|D ) ' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" | ||||
|   fi | ||||
|   if $(command git rev-parse --verify refs/stash >/dev/null 2>&1); then | ||||
|   if $(__git_prompt_git rev-parse --verify refs/stash >/dev/null 2>&1); then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_STASHED$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^UU ' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)UU ' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^## [^ ]\+ .*ahead' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)## [^ ]\+ .*ahead' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^## [^ ]\+ .*behind' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)## [^ ]\+ .*behind' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS" | ||||
|   fi | ||||
|   if $(echo "$INDEX" | grep '^## [^ ]\+ .*diverged' &> /dev/null); then | ||||
|   if [[ "${INDEX}" =~ $'(^|\n)## [^ ]\+ .*diverged' ]]; then | ||||
|     STATUS="$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS" | ||||
|   fi | ||||
|   echo $STATUS | ||||
| @@ -191,20 +190,20 @@ function git_prompt_status() { | ||||
| # Outputs the name of the current user | ||||
| # Usage example: $(git_current_user_name) | ||||
| function git_current_user_name() { | ||||
|   command git config user.name 2>/dev/null | ||||
|   __git_prompt_git config user.name 2>/dev/null | ||||
| } | ||||
|  | ||||
| # Outputs the email of the current user | ||||
| # Usage example: $(git_current_user_email) | ||||
| function git_current_user_email() { | ||||
|   command git config user.email 2>/dev/null | ||||
|   __git_prompt_git config user.email 2>/dev/null | ||||
| } | ||||
|  | ||||
| # Output the name of the root directory of the git repository | ||||
| # Usage example: $(git_repo_name) | ||||
| function git_repo_name() { | ||||
|   local repo_path | ||||
|   if repo_path="$(git rev-parse --show-toplevel 2>/dev/null)" && [[ -n "$repo_path" ]]; then | ||||
|   if repo_path="$(__git_prompt_git rev-parse --show-toplevel 2>/dev/null)" && [[ -n "$repo_path" ]]; then | ||||
|     echo ${repo_path:t} | ||||
|   fi | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user