From 164576a817a4c6c44433c0194444d97225435b0c Mon Sep 17 00:00:00 2001
From: Michael Allen <michael@michaelallen.io>
Date: Tue, 21 Jul 2015 10:07:58 +0100
Subject: cleaned up the status line issues and provided tests for them

---
 git-base.sh    |  41 ++++++++++-------
 test-status.sh | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 162 insertions(+), 15 deletions(-)
 create mode 100755 test-status.sh

diff --git a/git-base.sh b/git-base.sh
index da9b35b..b45e42d 100755
--- a/git-base.sh
+++ b/git-base.sh
@@ -176,10 +176,16 @@ added="A%{$reset_color%}"
 modified="M%{$reset_color%}"
 deleted="D%{$reset_color%}"
 renamed="R%{$reset_color%}"
+copied="C%{$reset_color%}"
 us="U%{$reset_color%}"
 them="T%{$reset_color%}"
 both="B%{$reset_color%}"
 
+# Diacritic marks for overlaying an arrow over A D C etc
+#us="\xE2\x83\x97{$reset_color%}"
+#them="\xE2\x83\x96%{$reset_color%}"
+#both="\xE2\x83\xA1%{$reset_color%}"
+
 staged="%{$fg_bold[green]%}"
 unstaged="%{$fg_bold[red]%}"
 conflicted="%{$fg_bold[yellow]%}"
@@ -225,10 +231,11 @@ porcelain_status() {
 staged_status() {
   local gitStatus=${1:-"$(porcelain_status)"}
   local staged_string=""
-  local filesModified="$(echo "$gitStatus" | grep -p "M[A|M|C|D|U|R ] " | wc -l | grep -oEi '[1-9][0-9]*')"
-  local filesAdded="$(echo "$gitStatus" | grep -p "A[A|M|C|D|U|R ] " | wc -l | grep -oEi '[1-9][0-9]*')"
-  local filesDeleted="$(echo "$gitStatus" | grep -p "D[A|M|C|D|U|R ] " | wc -l | grep -oEi '[1-9][0-9]*')"
-  local filesRenamed="$(echo "$gitStatus" | grep -p "R[A|M|C|D|U|R ] " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesModified="$(echo "$gitStatus" | grep -p "M[ACDR ] " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesAdded="$(echo "$gitStatus" | grep -p "A[MCDR ] " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesDeleted="$(echo "$gitStatus" | grep -p "D[AMCR ] " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesRenamed="$(echo "$gitStatus" | grep -p "R[AMCD ] " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesCopied="$(echo "$gitStatus" | grep -p "C[AMDR ] " | wc -l | grep -oEi '[1-9][0-9]*')"
 
   if [ -n "$filesAdded" ]; then
     staged_string="$staged_string$filesAdded$staged$added"
@@ -242,24 +249,28 @@ staged_status() {
   if [ -n "$filesRenamed" ]; then
     staged_string="$staged_string$filesRenamed$staged$renamed"
   fi
+  if [ -n "$filesCopied" ]; then
+    staged_string="$staged_string$filesCopied$staged$copied"
+  fi
   echo "$staged_string"
 }
 
 conflicted_status() {
   local gitStatus=${1:-"$(porcelain_status)"}
   local conflicted_string=""
-  local filesConflictedUs="$(echo "$gitStatus" | grep -p "[A|M|C|D|R ]U " | wc -l | grep -oEi '[1-9][0-9]*')"
-  local filesConflictedThem="$(echo "$gitStatus" | grep -p "U[A|M|C|D|R ] " | wc -l | grep -oEi '[1-9][0-9]*')"
-  local filesConflictedBoth="$(echo "$gitStatus" | grep -p "UU " | wc -l | grep -oEi '[1-9][0-9]*')"
 
-  if [ -n "$filesConflictedUs" ]; then
-    conflicted_string="$conflicted_string$filesConflictedUs$conflicted$us"
+  local filesUs="$(echo "$gitStatus" | grep -p "[AD]U " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesThem="$(echo "$gitStatus" | grep -p "U[AD] " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesBoth="$(echo "$gitStatus" | grep -E "(UU|AA|DD) " | wc -l | grep -oEi '[1-9][0-9]*')"
+
+  if [ -n "$filesUs" ]; then
+    conflicted_string="$conflicted_string$filesUs$conflicted$us"
   fi
-  if [ -n "$filesConflictedBoth" ]; then
-    conflicted_string="$conflicted_string$filesConflictedBoth$conflicted$both"
+  if [ -n "$filesThem" ]; then
+    conflicted_string="$conflicted_string$filesThem$conflicted$them"
   fi
-  if [ -n "$filesConflictedThem" ]; then
-    conflicted_string="$conflicted_string$filesConflictedThem$conflicted$them"
+  if [ -n "$filesBoth" ]; then
+    conflicted_string="$conflicted_string$filesBoth$conflicted$both"
   fi
   echo "$conflicted_string"
 }
@@ -267,8 +278,8 @@ conflicted_status() {
 unstaged_status() {
   local gitStatus=${1:-"$(porcelain_status)"}
   local unstaged_string=""
-  local filesModified="$(echo "$gitStatus" | grep -p "[A|M|C|D|U|R ]M " | wc -l | grep -oEi '[1-9][0-9]*')"
-  local filesDeleted="$(echo "$gitStatus" | grep -p "[A|M|C|D|U|R ]D " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesModified="$(echo "$gitStatus" | grep -p "[AMCDR ]M " | wc -l | grep -oEi '[1-9][0-9]*')"
+  local filesDeleted="$(echo "$gitStatus" | grep -p "[AMCR ]D " | wc -l | grep -oEi '[1-9][0-9]*')"
 
   if [ -n "$filesDeleted" ]; then
     unstaged_string="$unstaged_string$filesDeleted$unstaged$deleted"
diff --git a/test-status.sh b/test-status.sh
new file mode 100755
index 0000000..025fc69
--- /dev/null
+++ b/test-status.sh
@@ -0,0 +1,136 @@
+scriptDir="$(cd "$(dirname "$0")"; pwd)"
+
+source "$scriptDir/git-base.sh"
+
+#  X          Y     Meaning
+#  -------------------------------------------------
+#            [MD]   not updated
+#  M        [ MD]   updated in index
+#  A        [ MD]   added to index
+#  D         [ M]   deleted from index
+#  R        [ MD]   renamed in index
+#  C        [ MD]   copied in index
+#  [MARC]           index and work tree matches
+#  [ MARC]     M    work tree changed since index
+#  [ MARC]     D    deleted in work tree
+#  -------------------------------------------------
+#  D           D    unmerged, both deleted
+#  A           U    unmerged, added by us
+#  U           D    unmerged, deleted by them
+#  U           A    unmerged, added by them
+#  D           U    unmerged, deleted by us
+#  A           A    unmerged, both added
+#  U           U    unmerged, both modified
+#  -------------------------------------------------
+#  ?           ?    untracked
+#  !           !    ignored
+#  -------------------------------------------------
+
+test_basic_unstaged_options() {
+  status="""
+ M modified-and-unstaged
+ D deleted-and-unstaged
+ A impossible-added-and-unstaged-(as-added-and-unstaged-is-untracked)
+ C impossible-copied-and-unstaged-(as-copied-and-unstaged-is-untracked)
+ R impossible-renamed-and-unstaged-(as-renamed-and-unstaged-is-untracked)
+ U impossible-updated-but-unmerged
+ ! impossible-ignored-without-!-in-position-1
+ ? impossible-untracked-without-?-in-position-1
+   empty-spaces-mean-nothing
+  """
+  assertEquals "line:${LINENO} staged status failed match" "" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match"\
+    "1${unstaged}${deleted}1${unstaged}${modified}" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+}
+
+test_basic_staged_options() {
+  status="""
+A  added-and-staged
+  """
+  assertEquals "line:${LINENO} staged status failed match"\
+    "1${staged}${added}" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+
+  status="""
+M  modified-and-staged
+  """
+  assertEquals "line:${LINENO} staged status failed match"\
+    "1${staged}${modified}" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+
+  status="""
+D  deleted-and-staged
+  """
+  assertEquals "line:${LINENO} staged status failed match"\
+    "1${staged}${deleted}" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+
+  status="""
+C  copied-and-staged
+  """
+  assertEquals "line:${LINENO} staged status failed match"\
+    "1${staged}${copied}" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+
+  status="""
+R  renamed-and-staged
+  """
+  assertEquals "line:${LINENO} staged status failed match"\
+    "1${staged}${renamed}" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+
+  status="""
+U  impossible-unmerged-without-a-character-in-position-2
+?  impossible-untracked-without-?-in-position-2
+!  impossible-ignored-without-!-in-position-2
+   empty-spaces-do-nothing
+  """
+  assertEquals "line:${LINENO} staged status failed match" "" "$(staged_status "$status")"
+  assertEquals "line:${LINENO} untracked status failed match" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO} unstaged status failed match" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO} conflicted status failed match" "" "$(conflicted_status "$status")"
+}
+
+test_conflicts() {
+  status="""
+UD unmerged-deleted-by-them
+UA unmerged-added-by-them
+  """
+  assertEquals "line:${LINENO}" "" "$(staged_status "$status")"
+  assertEquals "line:${LINENO}" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO}" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO}" "2${conflicted}${them}" "$(conflicted_status "$status")"
+
+  status="""
+AU unmerged-added-by-us
+DU unmerged-deleted-by-us
+  """
+  assertEquals "line:${LINENO}" "" "$(staged_status "$status")"
+  assertEquals "line:${LINENO}" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO}" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO}" "2${conflicted}${us}" "$(conflicted_status "$status")"
+
+  status="""
+AA unmerged-both-added
+DD unmerged-both-deleted
+UU unmerged-both-modified
+  """
+  assertEquals "line:${LINENO}" "" "$(staged_status "$status")"
+  assertEquals "line:${LINENO}" "" "$(untracked_status "$status")"
+  assertEquals "line:${LINENO}" "" "$(unstaged_status "$status")"
+  assertEquals "line:${LINENO}" "3${conflicted}${both}" "$(conflicted_status "$status")"
+}
+
+. ./shunit/shunit2
-- 
cgit v1.2.3