daabe2a0089ac4f0c3646b5ea92c9efe06cd7ccb

Author
Robby Russell <robby@planetargon.com>
Committer
Robby Russell <robby@planetargon.com>
Date

Message

Merge pull request #4205 from mcornella/fix-git-prompt-plugin

Fix git-prompt plugin

Diff

This diff is truncated to protect this page.

  1diff --git a/plugins/git-prompt/git-prompt.plugin.zsh b/plugins/git-prompt/git-prompt.plugin.zsh
  2index d868a5fe1d1bf6b6117db674b093d1a632f5d0d7..5175bf70f91d0fafddebfd72a74eea5435131213 100644
  3--- a/plugins/git-prompt/git-prompt.plugin.zsh
  4+++ b/plugins/git-prompt/git-prompt.plugin.zsh
  5@@ -1,57 +1,92 @@
  6 # ZSH Git Prompt Plugin from:
  7 # http://github.com/olivierverdier/zsh-git-prompt
  8-#
  9-export __GIT_PROMPT_DIR=$ZSH/plugins/git-prompt
 10 
 11-# Allow for functions in the prompt.
 12-setopt PROMPT_SUBST
 13+__GIT_PROMPT_DIR="${0:A:h}"
 14 
 15-## Enable auto-execution of functions.
 16-typeset -ga preexec_functions
 17-typeset -ga precmd_functions
 18-typeset -ga chpwd_functions
 19-
 20-# Append git functions needed for prompt.
 21-preexec_functions+='preexec_update_git_vars'
 22-precmd_functions+='precmd_update_git_vars'
 23-chpwd_functions+='chpwd_update_git_vars'
 24+## Hook function definitions
 25+function chpwd_update_git_vars() {
 26+    update_current_git_vars
 27+}
 28 
 29-## Function definitions
 30 function preexec_update_git_vars() {
 31     case "$2" in
 32-        git*)
 33+        git*|hub*|gh*|stg*)
 34         __EXECUTED_GIT_COMMAND=1
 35         ;;
 36     esac
 37 }
 38 
 39 function precmd_update_git_vars() {
 40-    if [ -n "$__EXECUTED_GIT_COMMAND" ]; then
 41+    if [ -n "$__EXECUTED_GIT_COMMAND" ] || [ ! -n "$ZSH_THEME_GIT_PROMPT_CACHE" ]; then
 42         update_current_git_vars
 43         unset __EXECUTED_GIT_COMMAND
 44     fi
 45 }
 46 
 47-function chpwd_update_git_vars() {
 48-    update_current_git_vars
 49-}
 50+chpwd_functions+=(chpwd_update_git_vars)
 51+precmd_functions+=(precmd_update_git_vars)
 52+preexec_functions+=(preexec_update_git_vars)
 53+
 54 
 55+## Function definitions
 56 function update_current_git_vars() {
 57     unset __CURRENT_GIT_STATUS
 58 
 59     local gitstatus="$__GIT_PROMPT_DIR/gitstatus.py"
 60-    _GIT_STATUS=`python ${gitstatus}`
 61-    __CURRENT_GIT_STATUS=("${(f)_GIT_STATUS}")
 62+    _GIT_STATUS=$(python ${gitstatus} 2>/dev/null)
 63+     __CURRENT_GIT_STATUS=("${(@s: :)_GIT_STATUS}")
 64+    GIT_BRANCH=$__CURRENT_GIT_STATUS[1]
 65+    GIT_AHEAD=$__CURRENT_GIT_STATUS[2]
 66+    GIT_BEHIND=$__CURRENT_GIT_STATUS[3]
 67+    GIT_STAGED=$__CURRENT_GIT_STATUS[4]
 68+    GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5]
 69+    GIT_CHANGED=$__CURRENT_GIT_STATUS[6]
 70+    GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7]
 71 }
 72 
 73-function prompt_git_info() {
 74+git_super_status() {
 75+    precmd_update_git_vars
 76     if [ -n "$__CURRENT_GIT_STATUS" ]; then
 77-        echo "(%{${fg[red]}%}$__CURRENT_GIT_STATUS[1]%{${fg[default]}%}$__CURRENT_GIT_STATUS[2]%{${fg[magenta]}%}$__CURRENT_GIT_STATUS[3]%{${fg[default]}%})"
 78+      STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH$GIT_BRANCH%{${reset_color}%}"
 79+      if [ "$GIT_BEHIND" -ne "0" ]; then
 80+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_BEHIND$GIT_BEHIND%{${reset_color}%}"
 81+      fi
 82+      if [ "$GIT_AHEAD" -ne "0" ]; then
 83+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_AHEAD$GIT_AHEAD%{${reset_color}%}"
 84+      fi
 85+      STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_SEPARATOR"
 86+      if [ "$GIT_STAGED" -ne "0" ]; then
 87+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STAGED$GIT_STAGED%{${reset_color}%}"
 88+      fi
 89+      if [ "$GIT_CONFLICTS" -ne "0" ]; then
 90+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CONFLICTS$GIT_CONFLICTS%{${reset_color}%}"
 91+      fi
 92+      if [ "$GIT_CHANGED" -ne "0" ]; then
 93+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}"
 94+      fi
 95+      if [ "$GIT_UNTRACKED" -ne "0" ]; then
 96+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED%{${reset_color}%}"
 97+      fi
 98+      if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then
 99+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
100+      fi
101+      STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX"
102+      echo "$STATUS"
103     fi
104 }
105diff --git a/plugins/git-prompt/gitstatus.py b/plugins/git-prompt/gitstatus.py
106index 2568414320a79140ab387ad4fe788d8cd78367fd..a8eb8284b7ad8ed601890d84f0ffbfe92f6c00a1 100644
107--- a/plugins/git-prompt/gitstatus.py
108+++ b/plugins/git-prompt/gitstatus.py
109@@ -1,82 +1,84 @@
110 #!/usr/bin/env python
111-# -*- coding: UTF-8 -*-
112-from subprocess import Popen, PIPE
113-import re
114+from __future__ import print_function
115 
116-# change those symbols to whatever you prefer
117-symbols = {
118-    'ahead of': '↑',
119-    'behind': '↓',
120-    'staged': '♦',
121-    'changed': '‣',
122-    'untracked': '…',
123-    'clean': '⚡',
124-    'unmerged': '≠',
125-    'sha1': ':'
126-}
127+import sys
128+import re
129+import shlex
130+from subprocess import Popen, PIPE, check_output
131 
132-output, error = Popen(
133-    ['git', 'status'], stdout=PIPE, stderr=PIPE, universal_newlines=True).communicate()
134 
135-if error:
136-    import sys
137-    sys.exit(0)
138-lines = output.splitlines()
139+def get_tagname_or_hash():
140+    """return tagname if exists else hash"""
141+    cmd = 'git log -1 --format="%h%d"'
142+    output = check_output(shlex.split(cmd)).decode('utf-8').strip()
143+    hash_, tagname = None, None
144+    # get hash
145+    m = re.search('\(.*\)$', output)
146+    if m:
147+        hash_ = output[:m.start()-1]
148+    # get tagname
149+    m = re.search('tag: .*[,\)]', output)
150+    if m:
151+        tagname = 'tags/' + output[m.start()+len('tag: '): m.end()-1]
152 
153-behead_re = re.compile(
154-    r"^# Your branch is (ahead of|behind) '(.*)' by (\d+) commit")
155-diverge_re = re.compile(r"^# and have (\d+) and (\d+) different")
156+    if tagname:
157+        return tagname
158+    elif hash_:
159+        return hash_
160+    return None
161 
162-status = ''
163-staged = re.compile(r'^# Changes to be committed:$', re.MULTILINE)
164-changed = re.compile(r'^# Changed but not updated:$', re.MULTILINE)
165-untracked = re.compile(r'^# Untracked files:$', re.MULTILINE)
166-unmerged = re.compile(r'^# Unmerged paths:$', re.MULTILINE)
167 
168+# `git status --porcelain --branch` can collect all information
169+# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
170+po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE)
171+stdout, sterr = po.communicate()
172+if po.returncode != 0:
173+    sys.exit(0)  # Not a git repository
174 
175-def execute(*command):
176-    out, err = Popen(stdout=PIPE, stderr=PIPE, *command).communicate()
177-    if not err:
178-        nb = len(out.splitlines())
179+# collect git status information
180+untracked, staged, changed, conflicts = [], [], [], []
181+ahead, behind = 0, 0
182+status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()]
183+for st in status:
184+    if st[0] == '#' and st[1] == '#':
185+        if re.search('Initial commit on', st[2]):
186+            branch = st[2].split(' ')[-1]
187+        elif re.search('no branch', st[2]):  # detached status
188+            branch = get_tagname_or_hash()
189+        elif len(st[2].strip().split('...')) == 1:
190+            branch = st[2].strip()
191+        else:
192+            # current and remote branch info
193+            branch, rest = st[2].strip().split('...')
194+            if len(rest.split(' ')) == 1:
195+                # remote_branch = rest.split(' ')[0]
196+                pass
197+            else:
198+                # ahead or behind
199+                divergence = ' '.join(rest.split(' ')[1:])
200+                divergence = divergence.lstrip('[').rstrip(']')
201+                for div in divergence.split(', '):
202+                    if 'ahead' in div:
203+                        ahead = int(div[len('ahead '):].strip())
204+                    elif 'behind' in div:
205+                        behind = int(div[len('behind '):].strip())
206+    elif st[0] == '?' and st[1] == '?':
207+        untracked.append(st)
208     else: