From 54162e71d0f696dd2a977fda0ee625d08c83e792 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Sun, 20 Sep 2015 11:41:45 -0500 Subject: [PATCH 01/26] Use `git status --porcelain --branch` to improve performance Based off of changes by @wkentaro to zsh-git-prompt see: https://github.com/olivierverdier/zsh-git-prompt/pull/65 --- gitstatus.py | 174 ++++++++++++++++++++++++++++----------------------- gitstatus.sh | 89 +++++++++----------------- 2 files changed, 126 insertions(+), 137 deletions(-) diff --git a/gitstatus.py b/gitstatus.py index f350409..423619a 100755 --- a/gitstatus.py +++ b/gitstatus.py @@ -32,93 +32,109 @@ except SyntaxError: w(str(a)) w(kwd.get("end", "\n")) - # change those symbols to whatever you prefer symbols = {'ahead of': '↑·', 'behind': '↓·', 'prehash':':'} -from subprocess import Popen, PIPE - import sys -gitsym = Popen(['git', 'symbolic-ref', 'HEAD'], stdout=PIPE, stderr=PIPE) -branch, error = gitsym.communicate() - -error_string = error.decode('utf-8') - -if 'fatal: Not a git repository' in error_string: - sys.exit(0) - -branch = branch.decode('utf-8').strip()[11:] - -res, err = Popen(['git','diff','--name-status'], stdout=PIPE, stderr=PIPE).communicate() -err_string = err.decode('utf-8') - -if 'fatal' in err_string: - sys.exit(0) - -changed_files = [namestat[0] for namestat in res.splitlines()] -staged_files = [namestat[0] for namestat in Popen(['git','diff', '--staged','--name-status'], stdout=PIPE).communicate()[0].splitlines()] -nb_changed = len(changed_files) - changed_files.count('U') -nb_U = staged_files.count('U') -nb_staged = len(staged_files) - nb_U -staged = str(nb_staged) -conflicts = str(nb_U) -changed = str(nb_changed) -status_lines = Popen(['git','status','-s','-uall'],stdout=PIPE).communicate()[0].splitlines() -untracked_lines = [a for a in map(lambda s: s.decode('utf-8'), status_lines) if a.startswith("??")] -nb_untracked = len(untracked_lines) -untracked = str(nb_untracked) -stashes = Popen(['git','stash','list'],stdout=PIPE).communicate()[0].splitlines() -nb_stashed = len(stashes) -stashed = str(nb_stashed) - -if not nb_changed and not nb_staged and not nb_U and not nb_untracked and not nb_stashed: - clean = '1' -else: - clean = '0' - +import re +import shlex +from subprocess import Popen, PIPE, check_output + + +def get_tagname_or_hash(): + """return tagname if exists else hash""" + cmd = 'git log -1 --format="%h%d"' + output = check_output(shlex.split(cmd)).decode('utf-8').strip() + hash_, tagname = None, None + # get hash + m = re.search('\(.*\)$', output) + if m: + hash_ = output[:m.start()-1] + # get tagname + m = re.search('tag: .*[,\)]', output) + if m: + tagname = 'tags/' + output[m.start()+len('tag: '): m.end()-1] + + if tagname: + return tagname + elif hash_: + return hash_ + return None + +def get_stash(): + cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE) + so, se = cmd.communicate() + stashFile = '%s%s' % (so.decode('utf-8').rstrip(),'/logs/refs/stash') + + try: + with open(stashFile) as f: + return sum(1 for _ in f) + except IOError: + return 0 + +# `git status --porcelain --branch` can collect all information +# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind +po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE) +stdout, sterr = po.communicate() +if po.returncode != 0: + sys.exit(0) # Not a git repository + +# collect git status information +untracked, staged, changed, conflicts = [], [], [], [] +ahead, behind = 0, 0 remote = '' - -tag, tag_error = Popen(['git', 'describe', '--exact-match'], stdout=PIPE, stderr=PIPE).communicate() - -if not branch: # not on any branch - if tag: # if we are on a tag, print the tag's name - branch = tag - else: - branch = symbols['prehash']+ Popen(['git','rev-parse','--short','HEAD'], stdout=PIPE).communicate()[0].decode('utf-8')[:-1] +status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()] +for st in status: + if st[0] == '#' and st[1] == '#': + if re.search('Initial commit on', st[2]): + branch = st[2].split(' ')[-1] + elif re.search('no branch', st[2]): # detached status + branch = get_tagname_or_hash() + elif len(st[2].strip().split('...')) == 1: + branch = st[2].strip() + else: + # current and remote branch info + branch, rest = st[2].strip().split('...') + if len(rest.split(' ')) == 1: + # remote_branch = rest.split(' ')[0] + pass + else: + # ahead or behind + divergence = ' '.join(rest.split(' ')[1:]) + divergence = divergence.lstrip('[').rstrip(']') + for div in divergence.split(', '): + if 'ahead' in div: + ahead = int(div[len('ahead '):].strip()) + remote += '%s%s' % (symbols['ahead of'], ahead) + elif 'behind' in div: + behind = int(div[len('behind '):].strip()) + remote += '%s%s' % (symbols['behind'], behind) + elif st[0] == '?' and st[1] == '?': + untracked.append(st) + else: + if st[1] == 'M': + changed.append(st) + if st[0] == 'U': + conflicts.append(st) + elif st[0] != ' ': + staged.append(st) + +if not changed and not staged and not conflicts and not untracked: + clean = 1 else: - remote_name = Popen(['git','config','branch.%s.remote' % branch], stdout=PIPE).communicate()[0].strip() - if remote_name: - merge_name = Popen(['git','config','branch.%s.merge' % branch], stdout=PIPE).communicate()[0].strip() - else: - remote_name = "origin" - merge_name = "refs/heads/%s" % branch - - if remote_name == '.': # local - remote_ref = merge_name - else: - remote_ref = 'refs/remotes/%s/%s' % (remote_name, merge_name[11:]) - revgit = Popen(['git', 'rev-list', '--left-right', '%s...HEAD' % remote_ref],stdout=PIPE, stderr=PIPE) - revlist = revgit.communicate()[0] - if revgit.poll(): # fallback to local - revlist = Popen(['git', 'rev-list', '--left-right', '%s...HEAD' % merge_name],stdout=PIPE, stderr=PIPE).communicate()[0] - behead = revlist.splitlines() - ahead = len([x for x in behead if x[0]=='>']) - behind = len(behead) - ahead - if behind: - remote += '%s%s' % (symbols['behind'], behind) - if ahead: - remote += '%s%s' % (symbols['ahead of'], ahead) + clean = 0 if remote == "": - remote = '.' + remote = '.' out = '\n'.join([ - str(branch), - str(remote), - staged, - conflicts, - changed, - untracked, - stashed, - clean]) + branch, + remote.decode('utf-8'), + str(len(staged)), + str(len(conflicts)), + str(len(changed)), + str(len(untracked)), + str(get_stash()), + str(clean) +]) Print(out) diff --git a/gitstatus.sh b/gitstatus.sh index c9b72c2..59f3673 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -6,8 +6,7 @@ # Alan K. Stebbens [http://github.com/aks] # helper functions -count_lines() { echo "$1" | egrep -c "^$2" ; } -all_lines() { echo "$1" | grep -v "^$" | wc -l ; } +count_lines() { echo "$1" | egrep -c $3 "^$2" ; } if [ -z "${__GIT_PROMPT_DIR}" ]; then SOURCE="${BASH_SOURCE[0]}" @@ -19,39 +18,38 @@ if [ -z "${__GIT_PROMPT_DIR}" ]; then __GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )" fi -gitsym=`git symbolic-ref HEAD` +gitstatus=`git status --porcelain --branch` -# if "fatal: Not a git repo .., then exit -case "$gitsym" in fatal*) exit 0 ;; esac +# if the status is fatal, exit now +[[ "$?" -ne 0 ]] && exit 0 -# the current branch is the tail end of the symbolic reference -branch="${gitsym##refs/heads/}" # get the basename after "refs/heads/" +num_staged=`count_lines "$gitstatus" "(\?\?|##| )" "-v"` +num_changed=`count_lines "$gitstatus" ".M"` +num_conflicts=`count_lines "$gitstatus" "U"` +num_untracked=`count_lines "$gitstatus" "\?\?"` -gitstatus=`git diff --name-status 2>&1` - -# if the diff is fatal, exit now -case "$gitstatus" in fatal*) exit 0 ;; esac - - -staged_files=`git diff --staged --name-status` - -num_changed=$(( `all_lines "$gitstatus"` - `count_lines "$gitstatus" U` )) -num_conflicts=`count_lines "$staged_files" U` -num_staged=$(( `all_lines "$staged_files"` - num_conflicts )) -num_untracked=`git ls-files --others --exclude-standard $(git rev-parse --show-cdup) | wc -l` if [[ "$__GIT_PROMPT_IGNORE_STASH" = "1" ]]; then num_stashed=0 -else - num_stashed=`git stash list | wc -l` +else + stash_file="`git rev-parse --git-dir`/logs/refs/stash" + if [[ -e "${stash_file}" ]]; then + num_stashed=`wc -l "${stash_file}" | cut -d' ' -f 1` + else + num_stashed=0 + fi fi clean=0 -if (( num_changed == 0 && num_staged == 0 && num_U == 0 && num_untracked == 0 && num_stashed == 0 )) ; then +if (( num_changed == 0 && num_staged == 0 && num_untracked == 0 && num_stashed == 0 )) ; then clean=1 fi remote= +branch_line=`echo $gitstatus | grep "^##"` +IFS="." read -ra line <<< "${branch_line/\#\# }" +branch="${line[0]}" + if [[ -z "$branch" ]]; then tag=`git describe --exact-match` if [[ -n "$tag" ]]; then @@ -59,52 +57,27 @@ if [[ -z "$branch" ]]; then else branch="_PREHASH_`git rev-parse --short HEAD`" fi +elif [[ "$branch" == *"Initial commit on"* ]]; then + IFS=" " read -ra branch_line <<< "$branch" + branch=${branch_line[-1]} +elif [[ "$branch" == *"no branch"* ]]; then + branch="_PREHASH_`git rev-parse --short HEAD`" else - remote_name=`git config branch.${branch}.remote` - - if [[ -n "$remote_name" ]]; then - merge_name=`git config branch.${branch}.merge` - else - remote_name='origin' - merge_name="refs/heads/${branch}" - fi - - if [[ "$remote_name" == '.' ]]; then - remote_ref="$merge_name" - else - remote_ref="refs/remotes/$remote_name/${merge_name##refs/heads/}" - fi - - # detect if the local branch have a remote tracking branch - cmd_output=$(git rev-parse --abbrev-ref ${branch}@{upstream} 2>&1 >/dev/null) - - if [ `count_lines "$cmd_output" "fatal: no upstream"` == 1 ] ; then - has_remote_tracking=0 - else - has_remote_tracking=1 + IFS="[]" read -ra remote_line <<< "${line[3]}" + if [[ "${remote_line[1]}" == *ahead* ]]; then + num_ahead=`echo "${remote_line[1]}" | cut -c 7-` + remote="${remote}_AHEAD_${num_ahead}" fi - - # get the revision list, and count the leading "<" and ">" - revgit=`git rev-list --left-right ${remote_ref}...HEAD` - num_revs=`all_lines "$revgit"` - num_ahead=`count_lines "$revgit" "^>"` - num_behind=$(( num_revs - num_ahead )) - if (( num_behind > 0 )) ; then + if [[ "${remote_line[1]}" == *behind* ]]; then + num_behind=`echo "${remote_line[1]}" | cut -c 9-` remote="${remote}_BEHIND_${num_behind}" fi - if (( num_ahead > 0 )) ; then - remote="${remote}_AHEAD_${num_ahead}" - fi fi if [[ -z "$remote" ]] ; then remote='.' fi -if [[ "$has_remote_tracking" == "0" ]] ; then - remote='_NO_REMOTE_TRACKING_' -fi - for w in "$branch" "$remote" $num_staged $num_conflicts $num_changed $num_untracked $num_stashed $clean ; do echo "$w" done From 8e9faff94949907b40e2eaf8738b5b8da0e6cb48 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Sun, 20 Sep 2015 15:55:36 -0500 Subject: [PATCH 02/26] Fix issue parsing where there is no remote branch --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index 59f3673..dbc0bc9 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -46,7 +46,7 @@ fi remote= -branch_line=`echo $gitstatus | grep "^##"` +branch_line=`echo "$gitstatus" | grep "^##"` IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" From 7f63c3b0c708ca0b30acfbb5d39b571269a6ffd7 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Mon, 21 Sep 2015 00:47:13 -0500 Subject: [PATCH 03/26] Fix a problem calculating clean in the python script --- gitstatus.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gitstatus.py b/gitstatus.py index 423619a..3b12c3b 100755 --- a/gitstatus.py +++ b/gitstatus.py @@ -119,7 +119,8 @@ for st in status: elif st[0] != ' ': staged.append(st) -if not changed and not staged and not conflicts and not untracked: +stashed=get_stash() +if not changed and not staged and not conflicts and not untracked and not stashed: clean = 1 else: clean = 0 @@ -134,7 +135,7 @@ out = '\n'.join([ str(len(conflicts)), str(len(changed)), str(len(untracked)), - str(get_stash()), + str(stashed), str(clean) ]) Print(out) From 0231552c4e66dd802008927104c32275d7daaa99 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Mon, 21 Sep 2015 10:18:15 -0500 Subject: [PATCH 04/26] use bash substring rather than cut --- gitstatus.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index dbc0bc9..234926d 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -65,11 +65,11 @@ elif [[ "$branch" == *"no branch"* ]]; then else IFS="[]" read -ra remote_line <<< "${line[3]}" if [[ "${remote_line[1]}" == *ahead* ]]; then - num_ahead=`echo "${remote_line[1]}" | cut -c 7-` + num_ahead=${remote_line[1]:6} remote="${remote}_AHEAD_${num_ahead}" fi if [[ "${remote_line[1]}" == *behind* ]]; then - num_behind=`echo "${remote_line[1]}" | cut -c 9-` + num_behind=${remote_line[1]:9} remote="${remote}_BEHIND_${num_behind}" fi fi From 00558b8de8ad43c7522651d517ac9baadd417ad0 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Mon, 21 Sep 2015 10:19:26 -0500 Subject: [PATCH 05/26] fix substring indexing --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index 234926d..0d58678 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -69,7 +69,7 @@ else remote="${remote}_AHEAD_${num_ahead}" fi if [[ "${remote_line[1]}" == *behind* ]]; then - num_behind=${remote_line[1]:9} + num_behind=${remote_line[1]:8} remote="${remote}_BEHIND_${num_behind}" fi fi From 0dbac24bba7515a59636abab91d97187c597459c Mon Sep 17 00:00:00 2001 From: Kentaro Wada Date: Wed, 23 Sep 2015 17:19:47 +0900 Subject: [PATCH 06/26] Set LC_ALL=C at git status to make sure in English Fix https://github.com/magicmonty/bash-git-prompt/pull/170#issuecomment-142516122 --- gitstatus.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitstatus.py b/gitstatus.py index 423619a..48d91f5 100755 --- a/gitstatus.py +++ b/gitstatus.py @@ -74,7 +74,8 @@ def get_stash(): # `git status --porcelain --branch` can collect all information # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind -po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE) +po = Popen(['git', 'status', '--porcelain', '--branch'], env={'LC_ALL': 'C'}, + stdout=PIPE, stderr=PIPE) stdout, sterr = po.communicate() if po.returncode != 0: sys.exit(0) # Not a git repository From 7418da801dddd67a17d89fae587191aedf893b98 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 09:22:56 -0500 Subject: [PATCH 07/26] Set LC_ALL=C to force branch output to English --- gitstatus.py | 3 ++- gitstatus.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gitstatus.py b/gitstatus.py index 3b12c3b..54ada71 100755 --- a/gitstatus.py +++ b/gitstatus.py @@ -74,7 +74,8 @@ def get_stash(): # `git status --porcelain --branch` can collect all information # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind -po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE) +po = Popen(['git', 'status', '--porcelain', '--branch'], env={'LC_ALL': 'C'}, + stdout=PIPE, stderr=PIPE) stdout, sterr = po.communicate() if po.returncode != 0: sys.exit(0) # Not a git repository diff --git a/gitstatus.sh b/gitstatus.sh index 0d58678..cea824a 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -18,7 +18,7 @@ if [ -z "${__GIT_PROMPT_DIR}" ]; then __GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )" fi -gitstatus=`git status --porcelain --branch` +gitstatus=`LC_ALL=C git status --porcelain --branch` # if the status is fatal, exit now [[ "$?" -ne 0 ]] && exit 0 From 3a9239d227fa3476550c8fdb00160d5ae2e68f76 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 14:32:02 -0500 Subject: [PATCH 08/26] Fix issue where _NO_REMOTE_TRACKING_ doesn't show up when there is no remote branch --- gitstatus.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gitstatus.sh b/gitstatus.sh index cea824a..df90245 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -50,6 +50,10 @@ branch_line=`echo "$gitstatus" | grep "^##"` IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" +if [[ "${#line[@]}" -eq 1 ]]; then + remote="_NO_REMOTE_TRACKING_" +fi + if [[ -z "$branch" ]]; then tag=`git describe --exact-match` if [[ -n "$tag" ]]; then From e4c6b0ab9e9895968bd3fc08928eb22b7c850f9f Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 15:09:40 -0500 Subject: [PATCH 09/26] Remove calls to grep/egrep --- gitstatus.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index df90245..bb98436 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -5,9 +5,6 @@ # # Alan K. Stebbens [http://github.com/aks] -# helper functions -count_lines() { echo "$1" | egrep -c $3 "^$2" ; } - if [ -z "${__GIT_PROMPT_DIR}" ]; then SOURCE="${BASH_SOURCE[0]}" while [ -h "${SOURCE}" ]; do @@ -23,17 +20,27 @@ gitstatus=`LC_ALL=C git status --porcelain --branch` # if the status is fatal, exit now [[ "$?" -ne 0 ]] && exit 0 -num_staged=`count_lines "$gitstatus" "(\?\?|##| )" "-v"` -num_changed=`count_lines "$gitstatus" ".M"` -num_conflicts=`count_lines "$gitstatus" "U"` -num_untracked=`count_lines "$gitstatus" "\?\?"` +num_staged=0 +num_changed=0 +num_conflicts=0 +num_untracked=0 +while IFS='' read -r line || [[ -n "$line" ]]; do + status=${line:0:2} + case "$status" in + \#\#) branch_line="$line" ;; + *M) ((num_changed++)) ;; + U*) ((num_conflicts++)) ;; + \?\?) ((num_untracked++)) ;; + *) ((num_staged++)) ;; + esac +done <<< "$gitstatus" if [[ "$__GIT_PROMPT_IGNORE_STASH" = "1" ]]; then num_stashed=0 else stash_file="`git rev-parse --git-dir`/logs/refs/stash" if [[ -e "${stash_file}" ]]; then - num_stashed=`wc -l "${stash_file}" | cut -d' ' -f 1` + num_stashed=`cat "${stash_file} | wc -l` else num_stashed=0 fi @@ -46,7 +53,6 @@ fi remote= -branch_line=`echo "$gitstatus" | grep "^##"` IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" From 1e2ff372826abd8d51d9bb58c3fa6aff5b0dfb40 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 18:12:37 -0500 Subject: [PATCH 10/26] Switch case matches from * to ? --- gitstatus.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index bb98436..03e1bc1 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -28,8 +28,8 @@ while IFS='' read -r line || [[ -n "$line" ]]; do status=${line:0:2} case "$status" in \#\#) branch_line="$line" ;; - *M) ((num_changed++)) ;; - U*) ((num_conflicts++)) ;; + ?M) ((num_changed++)) ;; + U?) ((num_conflicts++)) ;; \?\?) ((num_untracked++)) ;; *) ((num_staged++)) ;; esac From ff7aa3aa7a547c1555aaca435091ce257f465a8c Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 18:22:35 -0500 Subject: [PATCH 11/26] Fix handling of stash --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index 03e1bc1..57876f7 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -40,7 +40,7 @@ if [[ "$__GIT_PROMPT_IGNORE_STASH" = "1" ]]; then else stash_file="`git rev-parse --git-dir`/logs/refs/stash" if [[ -e "${stash_file}" ]]; then - num_stashed=`cat "${stash_file} | wc -l` + num_stashed=`wc -l "${stash_file}" | cut -d' ' -f1` else num_stashed=0 fi From 545cdce3990f56b7734c4cc0accd6ff3fb4bb12a Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 18:29:44 -0500 Subject: [PATCH 12/26] Use printf instead of echo to display --- gitstatus.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index 57876f7..e1e395d 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -88,8 +88,13 @@ if [[ -z "$remote" ]] ; then remote='.' fi -for w in "$branch" "$remote" $num_staged $num_conflicts $num_changed $num_untracked $num_stashed $clean ; do - echo "$w" -done +printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" \ + "$branch" \ + "$remote" \ + $num_staged \ + $num_conflicts \ + $num_changed \ + $num_untracked \ + $num_stashed $clean exit From 01f5402c7713ee784f038d1705d26563f6b958f9 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 20:05:13 -0500 Subject: [PATCH 13/26] Fix behind parsing --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index df90245..a834f91 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -73,7 +73,7 @@ else remote="${remote}_AHEAD_${num_ahead}" fi if [[ "${remote_line[1]}" == *behind* ]]; then - num_behind=${remote_line[1]:8} + num_behind=${remote_line[1]:7} remote="${remote}_BEHIND_${num_behind}" fi fi From 606388df395f6ac166c23e1871cbadffc474b4e3 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Wed, 23 Sep 2015 20:05:13 -0500 Subject: [PATCH 14/26] Fix behind parsing --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index e1e395d..57a8afd 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -79,7 +79,7 @@ else remote="${remote}_AHEAD_${num_ahead}" fi if [[ "${remote_line[1]}" == *behind* ]]; then - num_behind=${remote_line[1]:8} + num_behind=${remote_line[1]:7} remote="${remote}_BEHIND_${num_behind}" fi fi From 220d5c22b126f27eb688cd2c1d68e4c07175d37b Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Thu, 24 Sep 2015 09:08:27 -0500 Subject: [PATCH 15/26] Fix parsing when both ahead and behind --- gitstatus.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index 57a8afd..932804a 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -73,15 +73,17 @@ elif [[ "$branch" == *"Initial commit on"* ]]; then elif [[ "$branch" == *"no branch"* ]]; then branch="_PREHASH_`git rev-parse --short HEAD`" else - IFS="[]" read -ra remote_line <<< "${line[3]}" - if [[ "${remote_line[1]}" == *ahead* ]]; then - num_ahead=${remote_line[1]:6} - remote="${remote}_AHEAD_${num_ahead}" - fi - if [[ "${remote_line[1]}" == *behind* ]]; then - num_behind=${remote_line[1]:7} - remote="${remote}_BEHIND_${num_behind}" - fi + IFS="[,]" read -ra remote_line <<< "${line[3]}" + for rline in "${remote_line[@]}"; do + if [[ "$rline" == *ahead* ]]; then + num_ahead=${rline:6} + remote="${remote}_AHEAD_${num_ahead}" + fi + if [[ "$rline" == *behind* ]]; then + num_behind=${rline:7} + remote="${remote}_BEHIND_${num_behind# }" + fi + done fi if [[ -z "$remote" ]] ; then From 750425d8417478f098b04b8544ddb26d7d70d633 Mon Sep 17 00:00:00 2001 From: oGre Date: Thu, 24 Sep 2015 08:33:06 +0200 Subject: [PATCH 16/26] Changed all backticks to --- gitstatus.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index 9cff1c4..b228b5a 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -15,7 +15,7 @@ if [ -z "${__GIT_PROMPT_DIR}" ]; then __GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )" fi -gitstatus=`LC_ALL=C git status --porcelain --branch` +gitstatus=$( LC_ALL=C git status --porcelain --branch ) # if the status is fatal, exit now [[ "$?" -ne 0 ]] && exit 0 @@ -38,9 +38,9 @@ done <<< "$gitstatus" if [[ "$__GIT_PROMPT_IGNORE_STASH" = "1" ]]; then num_stashed=0 else - stash_file="`git rev-parse --git-dir`/logs/refs/stash" + stash_file="$( git rev-parse --git-dir )/logs/refs/stash" if [[ -e "${stash_file}" ]]; then - num_stashed=`wc -l "${stash_file}" | cut -d' ' -f1` + num_stashed=$( wc -l "${stash_file}" | cut -d' ' -f1 ) else num_stashed=0 fi @@ -62,17 +62,17 @@ if [[ "${#line[@]}" -eq 1 ]]; then fi if [[ -z "$branch" ]]; then - tag=`git describe --exact-match` + tag=$( git describe --exact-match ) if [[ -n "$tag" ]]; then branch="$tag" else - branch="_PREHASH_`git rev-parse --short HEAD`" + branch="_PREHASH_$( git rev-parse --short HEAD )" fi elif [[ "$branch" == *"Initial commit on"* ]]; then IFS=" " read -ra branch_line <<< "$branch" branch=${branch_line[-1]} elif [[ "$branch" == *"no branch"* ]]; then - branch="_PREHASH_`git rev-parse --short HEAD`" + branch="_PREHASH_$( git rev-parse --short HEAD )" else IFS="[,]" read -ra remote_line <<< "${line[3]}" for rline in "${remote_line[@]}"; do From 0e48e020b8be82fbda22d1cf681b087a0f031944 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Thu, 24 Sep 2015 09:54:02 -0500 Subject: [PATCH 17/26] Remove unnecessary grep line --- gitstatus.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index 9cff1c4..100b335 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -53,7 +53,6 @@ fi remote= -branch_line=`echo "$gitstatus" | grep "^##"` IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" From 87c66ea8d1d65b91519c5f032544321e064bcfd4 Mon Sep 17 00:00:00 2001 From: oGre Date: Thu, 24 Sep 2015 17:28:20 +0200 Subject: [PATCH 18/26] Missed one --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index b228b5a..a83e91b 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -53,7 +53,7 @@ fi remote= -branch_line=`echo "$gitstatus" | grep "^##"` +branch_line=$( echo "$gitstatus" | grep "^##" ) IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" From db6f2195538982482feba56ae411d78ed391d252 Mon Sep 17 00:00:00 2001 From: Dan Nguyen Date: Thu, 24 Sep 2015 10:40:18 -0500 Subject: [PATCH 19/26] Reorder AHEAD and BEHIND --- gitstatus.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index 100b335..04bce5a 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -77,13 +77,14 @@ else for rline in "${remote_line[@]}"; do if [[ "$rline" == *ahead* ]]; then num_ahead=${rline:6} - remote="${remote}_AHEAD_${num_ahead}" + ahead="_AHEAD_${num_ahead}" fi if [[ "$rline" == *behind* ]]; then num_behind=${rline:7} - remote="${remote}_BEHIND_${num_behind# }" + behind="_BEHIND_${num_behind# }" fi done + remote="${behind}${ahead}" fi if [[ -z "$remote" ]] ; then From 9955edb5c373938b947379182a916adaaf40a7ab Mon Sep 17 00:00:00 2001 From: oGre Date: Fri, 25 Sep 2015 07:22:52 +0200 Subject: [PATCH 20/26] Check for local branch needs to be moved so that check for behind/after doesn't override the result --- gitstatus.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index 2f15540..a7b9c65 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -56,10 +56,6 @@ remote= IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" -if [[ "${#line[@]}" -eq 1 ]]; then - remote="_NO_REMOTE_TRACKING_" -fi - if [[ -z "$branch" ]]; then tag=$( git describe --exact-match ) if [[ -n "$tag" ]]; then @@ -73,18 +69,22 @@ elif [[ "$branch" == *"Initial commit on"* ]]; then elif [[ "$branch" == *"no branch"* ]]; then branch="_PREHASH_$( git rev-parse --short HEAD )" else - IFS="[,]" read -ra remote_line <<< "${line[3]}" - for rline in "${remote_line[@]}"; do - if [[ "$rline" == *ahead* ]]; then - num_ahead=${rline:6} - ahead="_AHEAD_${num_ahead}" - fi - if [[ "$rline" == *behind* ]]; then - num_behind=${rline:7} - behind="_BEHIND_${num_behind# }" - fi - done - remote="${behind}${ahead}" + if [[ "${#line[@]}" -eq 1 ]]; then + remote="_NO_REMOTE_TRACKING_" + else + IFS="[,]" read -ra remote_line <<< "${line[3]}" + for rline in "${remote_line[@]}"; do + if [[ "$rline" == *ahead* ]]; then + num_ahead=${rline:6} + ahead="_AHEAD_${num_ahead}" + fi + if [[ "$rline" == *behind* ]]; then + num_behind=${rline:7} + behind="_BEHIND_${num_behind# }" + fi + done + remote="${behind}${ahead}" + fi fi if [[ -z "$remote" ]] ; then From b989b7f324cf7c2d04eca941916395b4a05252b7 Mon Sep 17 00:00:00 2001 From: oGre Date: Fri, 25 Sep 2015 12:30:29 +0200 Subject: [PATCH 21/26] Able to parse tag names when on tag --- gitstatus.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index a7b9c65..fc48cf7 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -56,18 +56,16 @@ remote= IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" -if [[ -z "$branch" ]]; then +if [[ "$branch" == *"Initial commit on"* ]]; then + IFS=" " read -ra branch_line <<< "$branch" + branch=${branch_line[-1]} +elif [[ "$branch" == *"no branch"* ]]; then tag=$( git describe --exact-match ) if [[ -n "$tag" ]]; then branch="$tag" else branch="_PREHASH_$( git rev-parse --short HEAD )" fi -elif [[ "$branch" == *"Initial commit on"* ]]; then - IFS=" " read -ra branch_line <<< "$branch" - branch=${branch_line[-1]} -elif [[ "$branch" == *"no branch"* ]]; then - branch="_PREHASH_$( git rev-parse --short HEAD )" else if [[ "${#line[@]}" -eq 1 ]]; then remote="_NO_REMOTE_TRACKING_" From c5cac48f4d85c012a76861450067019db518c4f1 Mon Sep 17 00:00:00 2001 From: oGre Date: Fri, 25 Sep 2015 12:59:48 +0200 Subject: [PATCH 22/26] Initial commit on is always a local state - set no remote tracking --- gitstatus.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/gitstatus.sh b/gitstatus.sh index fc48cf7..7782e62 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -59,6 +59,7 @@ branch="${line[0]}" if [[ "$branch" == *"Initial commit on"* ]]; then IFS=" " read -ra branch_line <<< "$branch" branch=${branch_line[-1]} + remote="_NO_REMOTE_TRACKING_" elif [[ "$branch" == *"no branch"* ]]; then tag=$( git describe --exact-match ) if [[ -n "$tag" ]]; then From 3621b5a67c3ea87d47e8679c4a12117d09d23125 Mon Sep 17 00:00:00 2001 From: oGre Date: Fri, 25 Sep 2015 19:41:07 +0200 Subject: [PATCH 23/26] We set branch first, then remote --- gitstatus.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gitstatus.sh b/gitstatus.sh index 7782e62..e01e00d 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -51,10 +51,9 @@ if (( num_changed == 0 && num_staged == 0 && num_untracked == 0 && num_stashed = clean=1 fi -remote= - IFS="." read -ra line <<< "${branch_line/\#\# }" branch="${line[0]}" +remote= if [[ "$branch" == *"Initial commit on"* ]]; then IFS=" " read -ra branch_line <<< "$branch" From 5fe390d098974932939290df4eca194e97ece7b7 Mon Sep 17 00:00:00 2001 From: oGre Date: Fri, 25 Sep 2015 22:28:40 +0200 Subject: [PATCH 24/26] Fixed bug in stash parsing --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index e01e00d..3b87cf0 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -40,7 +40,7 @@ if [[ "$__GIT_PROMPT_IGNORE_STASH" = "1" ]]; then else stash_file="$( git rev-parse --git-dir )/logs/refs/stash" if [[ -e "${stash_file}" ]]; then - num_stashed=$( wc -l "${stash_file}" | cut -d' ' -f1 ) + num_stashed=$( wc -l < "${stash_file}" | tr -s ' ' | cut -d ' ' -f2 ) else num_stashed=0 fi From c279c77fd8437a813a838083de39506f9dfe2ec8 Mon Sep 17 00:00:00 2001 From: oGre Date: Sun, 27 Sep 2015 18:14:52 +0200 Subject: [PATCH 25/26] Resolved conflict --- gitstatus.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index 3b87cf0..c2a8e40 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -40,7 +40,8 @@ if [[ "$__GIT_PROMPT_IGNORE_STASH" = "1" ]]; then else stash_file="$( git rev-parse --git-dir )/logs/refs/stash" if [[ -e "${stash_file}" ]]; then - num_stashed=$( wc -l < "${stash_file}" | tr -s ' ' | cut -d ' ' -f2 ) + wc_output=$( wc -l < "${stash_file}" ) + num_stashed=${wc_output// /} else num_stashed=0 fi From 89acb1c4b0925cf40d1d016c2610552836f310db Mon Sep 17 00:00:00 2001 From: oGre Date: Sun, 27 Sep 2015 18:43:30 +0200 Subject: [PATCH 26/26] Changed to match tabs and spaces --- gitstatus.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitstatus.sh b/gitstatus.sh index c2a8e40..9b763e0 100755 --- a/gitstatus.sh +++ b/gitstatus.sh @@ -41,7 +41,7 @@ else stash_file="$( git rev-parse --git-dir )/logs/refs/stash" if [[ -e "${stash_file}" ]]; then wc_output=$( wc -l < "${stash_file}" ) - num_stashed=${wc_output// /} + num_stashed=${wc_output//[[:space:]]/} else num_stashed=0 fi