[PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

Subsystems: the rest

STALE3738d

31 messages, 10 authors, 2016-06-15 · open the first message on its own page

[PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Andrew Sayers <hidden>
Date: 2016-06-15 22:48:55

People working in small teams sometimes forget to push their changes, causing
general confusion.  A gentle reminder in the command prompt should help.

Users migrating from centralised version control systems are especially likely
to forget, so I've included git-svn support as a special case.  Only SVN is
supported because it's the only centralised version control system I have any
experience with.  The code is designed to make adding other version control
systems easy for anyone that's interested.

Signed-off-by: Andrew Sayers <redacted>
---
 contrib/completion/git-completion.bash |   33 ++++++++++++++++++++++++++++++-
 1 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d3fec32..4bb0fee 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -48,6 +48,12 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see if there're unpushed commits, then
+#       you can set GIT_PS1_SHOWUNPUSHED to a nonempty value. If
+#       there're unpushed commits, then a '!' will be shown next to
+#       the branch name.  Setting GIT_PS1_SHOWUNPUSHED=svn will look
+#       for unpushed git-svn commits.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -138,6 +144,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -167,12 +174,34 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUNPUSHED-}" ]; then
+			   local head
+			   local upstream
+			   if [ "${GIT_PS1_SHOWUNPUSHED-}" = "svn" ]; then # git-svn upstream checking
+			      local remote_branch=$( git config --get svn-remote.svn.url | sed 's/\//\\\//g' )
+			      upstream=$( git log | sed -ne "/^    git-svn-id: / { s/^    git-svn-id: $remote_branch\/\([^@]*\).*/\1/p ; q }" )
+			   else # git upstream checking
+			      upstream="@{upstream}"
+			   fi
+
+			   if git rev-parse --quiet "$upstream" HEAD 2>/dev/null | {
+			      read upstream
+			      read head
+			      [ -n "$head" -a -n "$upstream" -a "$head" != "$upstream" ]
+			   }; then
+			       p='!'
+			   else
+			       p=
+			   fi
+			fi
+
 		fi
 
 		if [ -n "${1-}" ]; then
-			printf "$1" "$c${b##refs/heads/}$w$i$s$u$r"
+			printf "$1" "$c${b##refs/heads/}$w$i$s$u$r$p"
 		else
-			printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r"
+			printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r$p"
 		fi
 	fi
 }

Re: [PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:55

Andrew Sayers wrote:
People working in small teams sometimes forget to push their changes, causing
general confusion.  A gentle reminder in the command prompt should help.
I think this is a good idea but...
+#       If you would like to see if there're unpushed commits, then
+#       you can set GIT_PS1_SHOWUNPUSHED to a nonempty value. If
+#       there're unpushed commits, then a '!' will be shown next to
+#       the branch name.  Setting GIT_PS1_SHOWUNPUSHED=svn will look
+#       for unpushed git-svn commits.
At least the svn/git setting should definitely be configurable through
git-config, so that it becomes per-repo configurable.  Also, you could
try to trigger the svn mode by default if a svn-remote.svn.url exists.
+			      upstream=$( git log | sed -ne "/^    git-svn-id: / { s/^    git-svn-id: $remote_branch\/\([^@]*\).*/\1/p ; q }" )
How about starting with

  git log -1 --first-parent --grep="^git-svn-id: $remote_branch"

which should be faster and is also closer to the truth.  It still
doesn't work if the repo was cloned with --no-metadata.  Doing it
right probably would require a new informational command in git-svn
that reports the branch name.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

Re: [PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:55

Andrew Sayers wrote:
People working in small teams sometimes forget to push their changes, causing
general confusion.  A gentle reminder in the command prompt should help.
[...]
+#       there're unpushed commits, then a '!' will be shown next to
BTW, here's another idea: how about using '>' and '<' to signal being
ahead and behind upstream, resp. (and both if they diverged)?

(I think the hard question here is whether it's helpful enough to
weigh against the confusion of having it show nothing, because the
user hasn't fetched after an update on the remote...)

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

Re: [PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Andrew Sayers <hidden>
Date: 2016-06-15 22:48:55

On 06/06/10 19:14, Thomas Rast wrote:
At least the svn/git setting should definitely be configurable through
git-config, so that it becomes per-repo configurable.  Also, you could
try to trigger the svn mode by default if a svn-remote.svn.url exists.
I'm not averse to adding a config setting, or to exploring the
"--no-metadata" case.  I am concerned about the strict time constraints
for code called in a command prompt though.  For instance, calling
git-svn could easily make your prompt take over half a second to respond
because of all the Perl you'd have to compile.  I'd also want a few
real-world use cases and a nod from Shawn before diverging any further
from the existing GIT_PS1_FOO= convention.

Having said all that, I'm quite happy to resubmit with
GIT_PS1_SHOWUNPUSHED=svn treated like GIT_PS1_SHOWUNPUSHED=1 when
$GIT_DIR/svn doesn't exist.
How about starting with

  git log -1 --first-parent --grep="^git-svn-id: $remote_branch"

which should be faster and is also closer to the truth.  It still
doesn't work if the repo was cloned with --no-metadata.  Doing it
right probably would require a new informational command in git-svn
that reports the branch name.
Good idea about "-1" and "--grep", but multi-parent commits aren't
compatible with SVN, so I don't see how "--first-parent" is useful here?
 In fact I'm tempted to look for merge commits and print a big warning
when one is found.

I don't see how to actually split out the branch name without calling
sed or using one of the disallowed ${} constructs.  So I compared the
following commands on my PC (2.1 GHz dual-core Athlon) using a
repository with 100 empty commits between HEAD and a git-svn-id:

time git log | \
	sed -ne "/^    git-svn-id: / { s/^    git-svn-id: "\
	"$remote_branch\/\([^@]*\).*/\1/p ; q }"

time git log -1 --grep="^git-svn-id: $remote_branch" | \
	sed -ne "s/^    git-svn-id: $remote_branch\/\([^@]*\).*/\1/p"

The former averaged about 0.017 seconds, whereas the latter averaged
about 0.015.  So when I resubmit this patch, I'll include your version
if merge commits are somehow useful to SVNers, or a merge warning otherwise.

Incidentally, a quick bit of etiquette - would you rather I submitted an
RFC patch or two with these changes, or wait until the discussion has
reached a more stable point?

	- Andrew

Re: [PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:48:55

Andrew Sayers [off-list ref] writes:
I don't see how to actually split out the branch name without calling
sed or using one of the disallowed ${} constructs.  So I compared the
following commands on my PC (2.1 GHz dual-core Athlon) using a
repository with 100 empty commits between HEAD and a git-svn-id:

time git log | \
	sed -ne "/^    git-svn-id: / { s/^    git-svn-id: "\
	"$remote_branch\/\([^@]*\).*/\1/p ; q }"

time git log -1 --grep="^git-svn-id: $remote_branch" | \
	sed -ne "s/^    git-svn-id: $remote_branch\/\([^@]*\).*/\1/p"
What disallowed ${} constructs?

First, ${var#pattern}, ${var##pattern}, ${var%pattern} and ${var%%pattern}
are POSIX, so you can use it in git shell scripts.

Second, this is _bash_ completion, so you can use also bash-specific
expansion, like ${var/pattern/string} or ${var//pattern/string}.

-- 
Jakub Narebski
Poland
ShadeHawk on #git

Re: [PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Andrew Sayers <hidden>
Date: 2016-06-15 22:48:55

On 06/06/10 22:07, Jakub Narebski wrote:
What disallowed ${} constructs?
My mistake, I misread that part of CodingGuidelines.  The following
bash-specific implementation takes about 0.013 seconds:

BRANCH=( $( git log --first-parent -1 \
		--grep="^git-svn-id: $remote_branch" ) )
BRANCH=${BRANCH[ ${#BRANCH[@]} - 2 ]}
BRANCH=${BRANCH%@*}
BRANCH=${BRANCH#*$remote_branch/}

Using an array here saves about 0.001 of a second.

	- Andrew

Re: [PATCH] bash completion: Support "unpushed commits" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:55

Andrew Sayers wrote:
I'm not averse to adding a config setting, or to exploring the
"--no-metadata" case.  I am concerned about the strict time constraints
for code called in a command prompt though.  For instance, calling
git-svn could easily make your prompt take over half a second to respond
because of all the Perl you'd have to compile.
True, I forgot about that.
I'd also want a few
real-world use cases and a nod from Shawn before diverging any further
from the existing GIT_PS1_FOO= convention.
Having said all that, I'm quite happy to resubmit with
GIT_PS1_SHOWUNPUSHED=svn treated like GIT_PS1_SHOWUNPUSHED=1 when
$GIT_DIR/svn doesn't exist.
There's the precedent of bash.showDirtyState that allows you to
disable the +* indicators _per repository_.  The latter idea also
sounds reasonable, though I personally would find the configuration
more useful.  I have several repos that push to both git (for real
work) and SVN (for buildbots) where I'd prefer the indicator to refer
to git.
quoted
How about starting with

  git log -1 --first-parent --grep="^git-svn-id: $remote_branch"
Good idea about "-1" and "--grep", but multi-parent commits aren't
compatible with SVN, so I don't see how "--first-parent" is useful here?
 In fact I'm tempted to look for merge commits and print a big warning
when one is found.
Please don't; you'd immediately lose me as a user :-)

First, --first-parent is actually how git-svn looks for the
git-svn-id, and any other search is liable to turn up wrong results.
See working_head_info in git-svn.perl.

Second, the behaviour of git-svn with merges is very useful and
well-defined.  (Yes, there are stern warnings in the manpage, but if
you know what you're doing just ignore them...)

'git svn dcommit' will first determine the correct upstream branch
according to the above logic, i.e., it *always* commits to the
first-parent ancestry.  Then it commits the diff along this line of
history (i.e., always diffing to the first parent) but it does rewrite
the commits so that merges are preserved.

In pictures, if you have

    o---B---o---o---o    trunk
         \
          *---*---*---*    topic

and run 'git checkout trunk; git merge topic; git svn dcommit' you get

    o---B---o---o---o---M'    trunk
         \             /
          *---*---*---*    topic

(writing M' since this is already the rewritten version of an original
merge M).  M' looks to SVN like a 'git merge --squash topic' because
git-svn doesn't (yet?) store the merge info.

So you get to keep the git merge info, which is very useful for later
merges of 'topic'.

Note: NEVER run 'git checkout topic; git merge trunk'.  git-svn will
think (because of the first-parent rule) that you want to commit on
top of B!  I don't know what happens next but I expect it won't be too
pretty.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

[RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Andrew Sayers <hidden>
Date: 2016-06-15 22:48:56

Add a notification in the command prompt specifying whether you're ahead of
(>), behind (<), diverged from (<>) or at (=) your upstream.  This is
especially helpful in small teams that (forget to) push to each other very
frequently.

Support git-svn upstream detection as a special case, as migraters from
centralised version control systems are especially likely to forget to push.

Support for other types of upstream than SVN should be easy to add if anyone is
so inclined.

Signed-off-by: Andrew Sayers <redacted>
---

This patch includes Thomas Rast's feedback - thanks Thomas for the education :)

This patch makes unashamed use of shell arrays and substring expansion that
would normally not be allowed.  As Jakub Narebski mentioned, this is probably ok
in a bash-specific script.

Unlike other prompt options, I've put the divergence characters on the left of the
branch name.  I'm really not sure about this, and I'd like to hear people's
opinions.

This patch produces output like this when I have unpushed commits:

[andrew@pc myrepo >master] # my master is ahead of upstream

Intuitively, I like having a ">" when I'm ahead, although it would be more
logical to have something like this:

[andrew@pc myrepo <master] # upstream less-than master

Putting the symbol on the right makes this problem go away, but looks ridiculous
if you use a prompt like PS1='\W:$(__git_ps1 "(%s)")> '

myrepo:master>> # master greater-than upstream
myrepo:master<> # master less-than upstream
myrepo:master<>> # master and upstream have diverged

I'd rather not rely on colour prompts to clear this up - using colour as the
only way to convey important information to the user rarely ends well.

Adding a "u" to the symbol could also clear this up:

[andrew@pc myrepo u<master] # upstream less-than master

Using "u<", "u=", "u>" and "<>" would mean that the prompt always used either
two or zero characters, which would keep prompts lined up over time.  But it
would also eat horizontal space for an issue you'd stop seeing after a few
minutes.

Finally, my apologies to anyone that tried to apply my previous patch - to make
a long story short, it turns out I need this feature more than I realised :)

 contrib/completion/git-completion.bash |   58 +++++++++++++++++++++++++++++++-
 1 files changed, 57 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..1dc80fd 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,14 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference bitween HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.
+#       Unpushed commits (>), unmerged commits (<), both (<>) and
+#       neither (=) will be shown on the left of the branch name.  You
+#       can enable git-svn mode by setting GIT_PS1_SHOWUPSTREAM=svn
+#       and set the value per-repository with the bash.showUpstream
+#       variable.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -132,6 +140,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +168,57 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+
+				# Note: 'p' is used as a temporary throughout this block,
+				# before finally being assigned its correct value
+
+				if p="$(git config --get bash.showUpstream)"
+				then
+					GIT_PS1_SHOWUPSTREAM="$p"
+				fi
+
+				local upstream
+
+				if [ "${GIT_PS1_SHOWUPSTREAM-}" = "svn" ]; then
+
+					# git-svn upstream checking
+					p="$( git config --get svn-remote.svn.url )"
+					upstream=( $( git log --first-parent -1 \
+						--grep="^git-svn-id: $p" ) )
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$p/}
+
+				else # git upstream checking
+				  upstream="@{upstream}"
+				fi
+
+				if p="$( git rev-list \
+						--left-right "$upstream"...HEAD 2>/dev/null )"
+				then
+					case "$p" in
+						\<*\>*|\>*\<* ) p="<>" ;;
+						*\<*          ) p="<"  ;;
+						*\>*          ) p=">"  ;;
+						""            ) p="="  ;;
+
+						# the following case shouldn't be possible
+						# if you see this, please report it as a bug
+						* ) p="?ERROR($p)?" ;;
+
+					esac
+				else
+					p=""
+				fi
+
+			fi
+
 		fi
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c$p${b##refs/heads/}${f:+ $f}$r"
 	fi
 }
 
-- 
1.7.0.4

RE: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Peter Kjellerstedt <hidden>
Date: 2016-06-15 22:48:56

quoted hunk
-----Original Message-----
From: git-owner@vger.kernel.org [mailto:git-owner@vger.kernel.org] On
Behalf Of Andrew Sayers
Sent: den 8 juni 2010 23:37
To: Thomas Rast
Cc: Shawn O. Pearce; Git Mailing List
Subject: [RFC/PATCHv2] bash completion: Support "divergence from
upstream" warnings in __git_ps1

Add a notification in the command prompt specifying whether you're ahead of
(>), behind (<), diverged from (<>) or at (=) your upstream.  This is
especially helpful in small teams that (forget to) push to each other very
frequently.

Support git-svn upstream detection as a special case, as migraters from
centralised version control systems are especially likely to forget to push.

Support for other types of upstream than SVN should be easy to add if anyone is
so inclined.

Signed-off-by: Andrew Sayers <redacted>
---

This patch includes Thomas Rast's feedback - thanks Thomas for the education :)

This patch makes unashamed use of shell arrays and substring expansion that
would normally not be allowed.  As Jakub Narebski mentioned, this is probably ok
in a bash-specific script.

Unlike other prompt options, I've put the divergence characters on the left of the
branch name.  I'm really not sure about this, and I'd like to hear people's
opinions.

This patch produces output like this when I have unpushed commits:

[andrew@pc myrepo >master] # my master is ahead of upstream

Intuitively, I like having a ">" when I'm ahead, although it would be more
logical to have something like this:

[andrew@pc myrepo <master] # upstream less-than master

Putting the symbol on the right makes this problem go away, but looks ridiculous
if you use a prompt like PS1='\W:$(__git_ps1 "(%s)")> '

myrepo:master>> # master greater-than upstream
myrepo:master<> # master less-than upstream
myrepo:master<>> # master and upstream have diverged

I'd rather not rely on colour prompts to clear this up - using colour as the
only way to convey important information to the user rarely ends well.

Adding a "u" to the symbol could also clear this up:

[andrew@pc myrepo u<master] # upstream less-than master

Using "u<", "u=", "u>" and "<>" would mean that the prompt always used either
two or zero characters, which would keep prompts lined up over time. But it
would also eat horizontal space for an issue you'd stop seeing after a few
minutes.

Finally, my apologies to anyone that tried to apply my previous patch - to make
a long story short, it turns out I need this feature more than I realised :)

 contrib/completion/git-completion.bash |   58 +++++++++++++++++++++++++++++++-
 1 files changed, 57 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..1dc80fd 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,14 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference bitween HEAD and its
Typo: bitween -> between
quoted hunk
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.
+#       Unpushed commits (>), unmerged commits (<), both (<>) and
+#       neither (=) will be shown on the left of the branch name.  You
+#       can enable git-svn mode by setting GIT_PS1_SHOWUPSTREAM=svn
+#       and set the value per-repository with the bash.showUpstream
+#       variable.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -132,6 +140,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p

 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +168,57 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+
+				# Note: 'p' is used as a temporary throughout this block,
+				# before finally being assigned its correct value
+
+				if p="$(git config --get bash.showUpstream)"
+				then
+					GIT_PS1_SHOWUPSTREAM="$p"
+				fi
+
+				local upstream
+
+				if [ "${GIT_PS1_SHOWUPSTREAM-}" = "svn" ]; then
+
+					# git-svn upstream checking
+					p="$( git config --get svn-remote.svn.url )"
+					upstream=( $( git log --first-parent -1 \
+						--grep="^git-svn-id: $p" ) )
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$p/}
+
+				else # git upstream checking
+				  upstream="@{upstream}"
+				fi
+
+				if p="$( git rev-list \
+						--left-right "$upstream"...HEAD 2>/dev/null )"
+				then
+					case "$p" in
+						\<*\>*|\>*\<* ) p="<>" ;;
+						*\<*          ) p="<"  ;;
+						*\>*          ) p=">"  ;;
+						""            ) p="="  ;;
+
+						# the following case shouldn't be possible
+						# if you see this, please report it as a bug
+						* ) p="?ERROR($p)?" ;;
+
+					esac
+				else
+					p=""
+				fi
+
+			fi
+
 		fi

 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c$p${b##refs/heads/}${f:+ $f}$r"
 	fi
 }

--
1.7.0.4
//Peter

Re: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: John Tapsell <hidden>
Date: 2016-06-15 22:48:56

On 9 June 2010 06:36, Andrew Sayers [off-list ref] wrote:
Add a notification in the command prompt specifying whether you're ahead of
(>), behind (<), diverged from (<>) or at (=) your upstream.  This is
especially helpful in small teams that (forget to) push to each other very
frequently.
I hate to get all feature-bloat on you...

But could it state the number of commits as well please? :) :)

John

Re: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Michael J Gruber <hidden>
Date: 2016-06-15 22:48:56

[I haven't followed the previous discussion, just this RFC.]

Andrew Sayers venit, vidit, dixit 08.06.2010 23:36:
Add a notification in the command prompt specifying whether you're ahead of
(>), behind (<), diverged from (<>) or at (=) your upstream.  This is
especially helpful in small teams that (forget to) push to each other very
frequently.

Support git-svn upstream detection as a special case, as migraters from
centralised version control systems are especially likely to forget to push.

Support for other types of upstream than SVN should be easy to add if anyone is
so inclined.

Signed-off-by: Andrew Sayers <redacted>
---

This patch includes Thomas Rast's feedback - thanks Thomas for the education :)

This patch makes unashamed use of shell arrays and substring expansion that
would normally not be allowed.  As Jakub Narebski mentioned, this is probably ok
in a bash-specific script.

Unlike other prompt options, I've put the divergence characters on the left of the
branch name.  I'm really not sure about this, and I'd like to hear people's
opinions.
I'd say it would make sense to you use the same order as "branch -vv"
and "status -s", i.e. after the branch name.
This patch produces output like this when I have unpushed commits:

[andrew@pc myrepo >master] # my master is ahead of upstream

Intuitively, I like having a ">" when I'm ahead, although it would be more
logical to have something like this:
That is really illogical, please don't.
[andrew@pc myrepo <master] # upstream less-than master

Putting the symbol on the right makes this problem go away, but looks ridiculous
if you use a prompt like PS1='\W:$(__git_ps1 "(%s)")> '
Patient: If I move my arm like this then it hurts.
Doctor: Then don't do that ;)
myrepo:master>> # master greater-than upstream
myrepo:master<> # master less-than upstream
myrepo:master<>> # master and upstream have diverged

I'd rather not rely on colour prompts to clear this up - using colour as the
only way to convey important information to the user rarely ends well.

Adding a "u" to the symbol could also clear this up:

[andrew@pc myrepo u<master] # upstream less-than master

Using "u<", "u=", "u>" and "<>" would mean that the prompt always used either
two or zero characters, which would keep prompts lined up over time.  But it
would also eat horizontal space for an issue you'd stop seeing after a few
minutes.
I think a simple space would help already, i.e.
myrepo:master<> >

An alternative would be to use something like
myrepo:master+5-3

The numbers should make this distinguishable from the "--cached +". Of
course it eats up more space and is slightly confusing unless it is read
master = upstream + 5 -3.
OTOH it is very analogous to status -s and branch -vv.
Finally, my apologies to anyone that tried to apply my previous patch - to make
a long story short, it turns out I need this feature more than I realised :)
;)
quoted hunk
 contrib/completion/git-completion.bash |   58 +++++++++++++++++++++++++++++++-
 1 files changed, 57 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..1dc80fd 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,14 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference bitween HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.
+#       Unpushed commits (>), unmerged commits (<), both (<>) and
+#       neither (=) will be shown on the left of the branch name.  You
+#       can enable git-svn mode by setting GIT_PS1_SHOWUPSTREAM=svn
+#       and set the value per-repository with the bash.showUpstream
+#       variable.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -132,6 +140,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +168,57 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+
+				# Note: 'p' is used as a temporary throughout this block,
+				# before finally being assigned its correct value
+
+				if p="$(git config --get bash.showUpstream)"
+				then
+					GIT_PS1_SHOWUPSTREAM="$p"
+				fi
+
+				local upstream
+
+				if [ "${GIT_PS1_SHOWUPSTREAM-}" = "svn" ]; then
+
+					# git-svn upstream checking
+					p="$( git config --get svn-remote.svn.url )"
+					upstream=( $( git log --first-parent -1 \
+						--grep="^git-svn-id: $p" ) )
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$p/}
+
+				else # git upstream checking
+				  upstream="@{upstream}"
+				fi
+
+				if p="$( git rev-list \
+						--left-right "$upstream"...HEAD 2>/dev/null )"
Here you have all the info to do a "grep \<|wc -l" etc. instead of the
below if you go for the +5-3.
+				then
+					case "$p" in
+						\<*\>*|\>*\<* ) p="<>" ;;
+						*\<*          ) p="<"  ;;
+						*\>*          ) p=">"  ;;
+						""            ) p="="  ;;
+
+						# the following case shouldn't be possible
+						# if you see this, please report it as a bug
+						* ) p="?ERROR($p)?" ;;
+
+					esac
+				else
+					p=""
+				fi
+
+			fi
+
 		fi
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c$p${b##refs/heads/}${f:+ $f}$r"
 	fi
 }
 
Cheers,
Michael

Re: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Michael J Gruber <hidden>
Date: 2016-06-15 22:48:56

Michael J Gruber venit, vidit, dixit 09.06.2010 11:17:
...
An alternative would be to use something like
myrepo:master+5-3

The numbers should make this distinguishable from the "--cached +". Of
course it eats up more space and is slightly confusing unless it is read
master = upstream + 5 -3.
OTOH it is very analogous to status -s and branch -vv.
...
quoted
+				if p="$( git rev-list \
+						--left-right "$upstream"...HEAD 2>/dev/null )"
Here you have all the info to do a "grep \<|wc -l" etc. instead of the
below if you go for the +5-3.
quoted
+				then
+					case "$p" in
+						\<*\>*|\>*\<* ) p="<>" ;;
+						*\<*          ) p="<"  ;;
+						*\>*          ) p=">"  ;;
I mean something like this

					case "$p" in
						\<*\>*|\>*\<* ) p="+"$(echo "$p"|grep ">"|wc -l)"-"$(echo
"$p"|grep "<"|wc -l)  ;;
						*\<*          ) p="-"$(echo "$p"|grep "<"|wc -l)  ;;
						*\>*          ) p="+"$(echo "$p"|grep ">"|wc -l)  ;;

with

		printf "${1:- (%s)}" "$c${b##refs/heads/}$p${f:+ $f}$r"

resulting in a prompt like

[mjg@localhost git (mjg/sane-symlink-diff+4-153 *+%)]

on my branch "mjg/sane-symlink-diff".

Cheers,
Michael

Re: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Steven Michalske <hidden>
Date: 2016-06-15 22:48:56

On Jun 9, 2010, at 1:45 AM, John Tapsell wrote:
On 9 June 2010 06:36, Andrew Sayers [off-list ref] wrote:
quoted
Add a notification in the command prompt specifying whether you're ahead of
(>), behind (<), diverged from (<>) or at (=) your upstream.  This is
especially helpful in small teams that (forget to) push to each other very
frequently.
I hate to get all feature-bloat on you...

But could it state the number of commits as well please? :) :)
I like the idea of ahead, at, behind, and diverged

but I would want to use unicode/utf8  as my terminal supports it, would use it.

⇅	UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW is diverged.
↑	UPWARDS ARROW master is ahead.
↓	DOWNWARDS ARROW is master is behind.

Steve

Re: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Michael J Gruber <hidden>
Date: 2016-06-15 22:48:56

Michael J Gruber venit, vidit, dixit 09.06.2010 22:48:
					case "$p" in
						\<*\>*|\>*\<* ) p="+"$(echo "$p"|grep ">"|wc -l)"-"$(echo
"$p"|grep "<"|wc -l)  ;;
						*\<*          ) p="-"$(echo "$p"|grep "<"|wc -l)  ;;
						*\>*          ) p="+"$(echo "$p"|grep ">"|wc -l)  ;;
...make this

grep -Fc ">"

etc. rather than

grep ">"|wc -l

etc. of course. Sorry for the bash-spam :)

Michael

[PATCH 0/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:56

Andrew Sayers wrote:
+                                       case "$p" in
+                                               \<*\>*|\>*\<* ) p="<>" ;;
+                                               *\<*          ) p="<"  ;;
+                                               *\>*          ) p=">"  ;;
+                                               ""            ) p="="  ;;
+
+                                               # the following case shouldn't be possible
+                                               # if you see this, please report it as a bug
+                                               * ) p="?ERROR($p)?" ;;
+
+                                       esac
I didn't really like this bit, since rev-list has to format the output
only so you can match it.  I realized that I too have written code in
the past to detect which way this goes (in post-receive hooks), and/or
the number of commits as per the request

John Tapsell wrote:
I hate to get all feature-bloat on you...

But could it state the number of commits as well please? :) :)
So here's an additional patch to provide rev-list logic that supports
this feature.  I have then tweaked your original patch to make use of
it a u+7-5 style.

I'm not too picky about the exact style that it turns out to have in
the end; I have used my own customized version ever since we started
printing a space before the (master *+) dirtiness indicator.  However,
I think we should try to be as unambiguous and short as possible.
Hence I picked the 'u' prefix to avoid ambiguity with the dirtiness
indicator.


Andrew Sayers (1):
  bash completion: Support "divergence from upstream" warnings in
    __git_ps1

Thomas Rast (1):
  rev-list: introduce --count option

 Documentation/rev-list-options.txt     |    9 +++++
 builtin/rev-list.c                     |   16 +++++++++
 contrib/completion/git-completion.bash |   57 +++++++++++++++++++++++++++++++-
 revision.c                             |    2 +
 revision.h                             |    5 +++
 t/t6007-rev-list-cherry-pick-file.sh   |   29 ++++++++++++++++
 6 files changed, 117 insertions(+), 1 deletions(-)

[PATCH 2/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:56

From: Andrew Sayers <redacted>

Add a notification in the command prompt specifying whether you're
ahead of or behind your upstream.  This is especially helpful in small
teams that (forget to) push to each other very frequently.

Support git-svn upstream detection as a special case, as migraters from
centralised version control systems are especially likely to forget to push.

Support for other types of upstream than SVN should be easy to add if anyone is
so inclined.

Signed-off-by: Thomas Rast <redacted>
---
 contrib/completion/git-completion.bash |   57 +++++++++++++++++++++++++++++++-
 1 files changed, 56 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index de5e6c1..49253a1 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,14 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference bitween HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.  The
+#       difference will be shown as, e.g., "u+7-5" meaning that you
+#       are 7 commits ahead of and 5 commits behind the upstream.  You
+#       can enable git-svn mode by setting GIT_PS1_SHOWUPSTREAM=svn
+#       and set the value per-repository with the bash.showUpstream
+#       variable.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -132,6 +140,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +168,56 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+
+				# Note: 'p' is used as a temporary throughout this block,
+				# before finally being assigned its correct value
+
+				if p="$(git config --get bash.showUpstream)"
+				then
+					GIT_PS1_SHOWUPSTREAM="$p"
+				fi
+
+				local upstream
+
+				if [ "${GIT_PS1_SHOWUPSTREAM-}" = "svn" ]; then
+
+					# git-svn upstream checking
+					p="$( git config --get svn-remote.svn.url )"
+					upstream=( $( git log --first-parent -1 \
+						--grep="^git-svn-id: $p" ) )
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$p/}
+
+				else # git upstream checking
+					upstream="@{upstream}"
+				fi
+
+				p=$(git rev-list --count --left-right "$upstream"...HEAD 2>/dev/null)
+				debug_p="$p"
+				case "$p" in
+				"0	0"|"") # empty means no --count support or no upstream
+					p=
+					;;
+				"0	"*)
+					p="+${p#0	}"
+					;;
+				*"	0")
+					p="-${p%	0}"
+					;;
+				*)
+					p="+${p#*	}-${p%	*}"
+					;;
+				esac
+
+			fi
+
 		fi
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r${p:+ u$p}"
 	fi
 }
 
-- 
1.7.1.553.ge4d5c.dirty

[PATCH 1/2] rev-list: introduce --count option

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:56

Add a --count option that, instead of actually listing the commits,
merely counts them.

This is mostly geared towards script use, and to this end it acts
specially when used with --left-right: it outputs the left and right
counts separately.  Previously, scripts would have to run a shell loop
or small inline script over to achieve the same.  (Without
--left-right, a simple |wc -l does the job.)

Signed-off-by: Thomas Rast <redacted>
---
 Documentation/rev-list-options.txt   |    9 +++++++++
 builtin/rev-list.c                   |   16 ++++++++++++++++
 revision.c                           |    2 ++
 revision.h                           |    5 +++++
 t/t6007-rev-list-cherry-pick-file.sh |   29 +++++++++++++++++++++++++++++
 5 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index b9fb7a8..066ade9 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -98,6 +98,15 @@ you would get an output like this:
 This implies the '--topo-order' option by default, but the
 '--date-order' option may also be specified.
 
+ifdef::git-rev-list[]
+--count::
+	Print a number stating how many commits would have been
+	listed, and suppress all other output.  When used together
+	with '--left-right', instead print the counts for left and
+	right commits, separated by a tab.
+endif::git-rev-list[]
+
+
 ifndef::git-rev-list[]
 Diff Formatting
 ~~~~~~~~~~~~~~~
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 51ceb19..efe9360 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -50,6 +50,15 @@ static void show_commit(struct commit *commit, void *data)
 
 	graph_show_commit(revs->graph);
 
+	if (revs->count) {
+		if (commit->object.flags & SYMMETRIC_LEFT)
+			revs->count_left++;
+		else
+			revs->count_right++;
+		finish_commit(commit, data);
+		return;
+	}
+
 	if (info->show_timestamp)
 		printf("%lu ", commit->date);
 	if (info->header_prefix)
@@ -400,5 +409,12 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			     quiet ? finish_object : show_object,
 			     &info);
 
+	if (revs.count) {
+		if (revs.left_right)
+			printf("%d\t%d\n", revs.count_left, revs.count_right);
+		else
+			printf("%d\n", revs.count_left + revs.count_right);
+	}
+
 	return 0;
 }
diff --git a/revision.c b/revision.c
index b209d49..94fca7f 100644
--- a/revision.c
+++ b/revision.c
@@ -1146,6 +1146,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->boundary = 1;
 	} else if (!strcmp(arg, "--left-right")) {
 		revs->left_right = 1;
+	} else if (!strcmp(arg, "--count")) {
+		revs->count = 1;
 	} else if (!strcmp(arg, "--cherry-pick")) {
 		revs->cherry_pick = 1;
 		revs->limited = 1;
diff --git a/revision.h b/revision.h
index 568f1c9..bafa728 100644
--- a/revision.h
+++ b/revision.h
@@ -57,6 +57,7 @@ struct rev_info {
 			limited:1,
 			unpacked:1,
 			boundary:2,
+			count:1,
 			left_right:1,
 			rewrite_parents:1,
 			print_parents:1,
@@ -131,6 +132,10 @@ struct rev_info {
 
 	/* notes-specific options: which refs to show */
 	struct display_notes_opt notes_opt;
+
+	/* commit counts */
+	int count_left;
+	int count_right;
 };
 
 #define REV_TREE_SAME		0
diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh
index 4b8611c..b565638 100755
--- a/t/t6007-rev-list-cherry-pick-file.sh
+++ b/t/t6007-rev-list-cherry-pick-file.sh
@@ -32,6 +32,23 @@ test_expect_success setup '
 	git tag B
 '
 
+cat >expect <<EOF
+<tags/B
+>tags/C
+EOF
+
+test_expect_success '--left-right' '
+	git rev-list --left-right B...C > actual &&
+	git name-rev --stdin --name-only --refs="*tags/*" \
+		< actual > actual.named &&
+	test_cmp actual.named expect
+'
+
+test_expect_success '--count' '
+	git rev-list --count B...C > actual &&
+	test "$(cat actual)" = 2
+'
+
 test_expect_success '--cherry-pick foo comes up empty' '
 	test -z "$(git rev-list --left-right --cherry-pick B...C -- foo)"
 '
@@ -54,4 +71,16 @@ test_expect_success '--cherry-pick with independent, but identical branches' '
 		HEAD...master -- foo)"
 '
 
+cat >expect <<EOF
+1	2
+EOF
+
+# Insert an extra commit to break the symmetry
+test_expect_success '--count --left-right' '
+	git checkout branch &&
+	test_commit D &&
+	git rev-list --count --left-right B...D > actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.7.1.553.ge4d5c.dirty

Re: [RFC/PATCHv2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:56

Andrew Sayers wrote:
+				if [ "${GIT_PS1_SHOWUPSTREAM-}" = "svn" ]; then
+
+					# git-svn upstream checking
+					p="$( git config --get svn-remote.svn.url )"
+					upstream=( $( git log --first-parent -1 \
+						--grep="^git-svn-id: $p" ) )
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$p/}
This appears to be tailored to --stdlayout, and sadly doesn't work in
the (probably fairly common) case of single-branch checkouts where
git-svn only puts a "remotes/git-svn" branch.

I can't come up with any easy-but-robust method of checking that
though.  Perhaps it suffices to check that

  git config 'svn-remote.svn.(branches|tags)'

comes up empty, and in this case simply use git-svn as the remote.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

Re: [PATCH 0/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Michael J Gruber <hidden>
Date: 2016-06-15 22:48:57

Thomas Rast venit, vidit, dixit 10.06.2010 13:47:
Andrew Sayers wrote:
quoted
+                                       case "$p" in
+                                               \<*\>*|\>*\<* ) p="<>" ;;
+                                               *\<*          ) p="<"  ;;
+                                               *\>*          ) p=">"  ;;
+                                               ""            ) p="="  ;;
+
+                                               # the following case shouldn't be possible
+                                               # if you see this, please report it as a bug
+                                               * ) p="?ERROR($p)?" ;;
+
+                                       esac
I didn't really like this bit, since rev-list has to format the output
only so you can match it.  I realized that I too have written code in
the past to detect which way this goes (in post-receive hooks), and/or
the number of commits as per the request

John Tapsell wrote:
quoted
I hate to get all feature-bloat on you...

But could it state the number of commits as well please? :) :)
So here's an additional patch to provide rev-list logic that supports
this feature.  I have then tweaked your original patch to make use of
it a u+7-5 style.

I'm not too picky about the exact style that it turns out to have in
the end; I have used my own customized version ever since we started
printing a space before the (master *+) dirtiness indicator.  However,
I think we should try to be as unambiguous and short as possible.
Hence I picked the 'u' prefix to avoid ambiguity with the dirtiness
indicator.


Andrew Sayers (1):
  bash completion: Support "divergence from upstream" warnings in
    __git_ps1

Thomas Rast (1):
  rev-list: introduce --count option

 Documentation/rev-list-options.txt     |    9 +++++
 builtin/rev-list.c                     |   16 +++++++++
 contrib/completion/git-completion.bash |   57 +++++++++++++++++++++++++++++++-
 revision.c                             |    2 +
 revision.h                             |    5 +++
 t/t6007-rev-list-cherry-pick-file.sh   |   29 ++++++++++++++++
 6 files changed, 117 insertions(+), 1 deletions(-)
Checked and tested. After setting DIFF, even the tests pass!
But we can probably do without the debug_p line ;)

Liked-by: Michael J Gruber [off-list ref]

Re: [PATCH 2/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: SZEDER Gábor <hidden>
Date: 2016-06-15 22:48:57

Hi,


On Thu, Jun 10, 2010 at 01:47:24PM +0200, Thomas Rast wrote:
From: Andrew Sayers <redacted>
quoted hunk
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index de5e6c1..49253a1 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,14 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference bitween HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.  The
+#       difference will be shown as, e.g., "u+7-5" meaning that you
+#       are 7 commits ahead of and 5 commits behind the upstream.  You
+#       can enable git-svn mode by setting GIT_PS1_SHOWUPSTREAM=svn
+#       and set the value per-repository with the bash.showUpstream
+#       variable.
I find the last sentence of this description ambiguous.  What value
should bash.showUpstream be set to?  Do I really need to set both
GIT_PS1_SHOWUPSTREAM and bash.showUpstream?  What if
GIT_PS1_SHOWUPSTREAM=foo and bash.showUpstream=svn?

Furthermore, I think it would be good to provide means to disable this
feature for some repositories while keeping it enabled for others.  In
the current version I could either disable or enable it globally.
Perhaps we could disable it when bash.showUpstream is set to an empty
value.
quoted hunk
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -132,6 +140,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +168,56 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+
+				# Note: 'p' is used as a temporary throughout this block,
+				# before finally being assigned its correct value
+
Back in the old days when I was just learning programming, I got my
ass kicked when I dared to reuse the same variable for different
purposes.  C'mon, just how much shorter it is to create one more
variable than this two lines long comment?! ;)  It could even be
squashed together with the "local upstream" line.
+				if p="$(git config --get bash.showUpstream)"
+				then
+					GIT_PS1_SHOWUPSTREAM="$p"
+				fi
+
+				local upstream
+
+				if [ "${GIT_PS1_SHOWUPSTREAM-}" = "svn" ]; then
No need to use default value here, because GIT_PS1_SHOWUPSTREAM has
already been set above.
+
+					# git-svn upstream checking
+					p="$( git config --get svn-remote.svn.url )"
+					upstream=( $( git log --first-parent -1 \
+						--grep="^git-svn-id: $p" ) )
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$p/}
+
Unnecessary empty lines before and after this block of code.
+				else # git upstream checking
+					upstream="@{upstream}"
+				fi
+
+				p=$(git rev-list --count --left-right "$upstream"...HEAD 2>/dev/null)
+				debug_p="$p"
The leftover debugging mentioned by Michael.
+				case "$p" in
+				"0	0"|"") # empty means no --count support or no upstream
+					p=
+					;;
+				"0	"*)
+					p="+${p#0	}"
+					;;
+				*"	0")
+					p="-${p%	0}"
+					;;
+				*)
+					p="+${p#*	}-${p%	*}"
+					;;
+				esac
+
+			fi
+
 		fi
Unnecessary empty lines before both fi.
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r${p:+ u$p}"
 	fi
 }
 
-- 
1.7.1.553.ge4d5c.dirty

[PATCH v2 2/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:57

From: Andrew Sayers <redacted>

Add a notification in the command prompt specifying whether you're
ahead of or behind your upstream.  This is especially helpful in small
teams that (forget to) push to each other very frequently.

Support git-svn upstream detection as a special case, as migrators
from centralised version control systems are especially likely to
forget to push.

Also provide ways for the user to specify a custom upstream, or code
that figures out the upstream.

Support for other types of upstream than SVN should be easy to add if
anyone is so inclined.

Signed-off-by: Thomas Rast <redacted>
---
 contrib/completion/git-completion.bash |   89 +++++++++++++++++++++++++++++++-
 1 files changed, 88 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..a6cb435 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,17 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference between HEAD and its upstream,
+#       set GIT_PS1_SHOWUPSTREAM to one of the following:
+#           git          use @{upstream}
+#           svn          attempt to DWIM svn upstream for normal and --stdlayout
+#           ref <ref>    unconditionally use <ref>
+#           eval <code>  evaluate <code> which should print the commit to use
+#       Any other value DWIMs either svn or git, preferring svn if configured.
+#
+#       The difference will be shown as, e.g., "u+7-5" meaning that you are 7
+#       commits ahead of and 5 commits behind the upstream.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -78,6 +89,77 @@ __gitdir ()
 	fi
 }
 
+__git_ps1_divergence_from_upstream ()
+{
+	local cfg
+	if cfg="$(git config --get bash.showUpstream)"
+	then
+		GIT_PS1_SHOWUPSTREAM="$cfg"
+	fi
+	if [ -n "${GIT_PS1_SHOWUPSTREAM}" ]; then
+		local upstream count
+		case "${GIT_PS1_SHOWUPSTREAM}" in
+		svn|git|"ref "*|"eval "*)
+			;;
+		*)
+			# try to dwim the type
+			if git config --get svn-remote.svn.url >/dev/null; then
+				GIT_PS1_SHOWUPSTREAM=svn
+			else
+				GIT_PS1_SHOWUPSTREAM=git
+			fi
+			;;
+		esac
+		case "${GIT_PS1_SHOWUPSTREAM}" in
+		git)
+			upstream="@{upstream}"
+			;;
+		svn)
+			local url
+			# git-svn upstream checking: if it has a
+			# remotes/git-svn, that is probably the upstream.
+			# Otherwise try to figure out the branch for
+			# --stdlayout repos.
+			if ! upstream="$(git rev-parse remotes/git-svn 2>/dev/null)"; then
+				url="$(git config --get svn-remote.svn.url)"
+				upstream=( $(git log --first-parent -1 \
+						 --grep="^git-svn-id: $url") )
+				if [ -n "$upstream" ]; then
+					upstream=${upstream[ ${#upstream[@]} - 2 ]}
+					upstream=${upstream%@*}
+					upstream=${upstream#*$url/}
+				fi
+			fi
+			;;
+		"eval "*)
+			# custom shell command that determines upstream
+			upstream="$(eval "${GIT_PS1_SHOWUPSTREAM#eval }")"
+			;;
+		"ref "*)
+			upstream="${GIT_PS1_SHOWUPSTREAM#ref }"
+			;;
+		esac
+
+		count=$(git rev-list --count --left-right \
+				"$upstream"...HEAD 2>/dev/null)
+		case "$count" in
+		"0	0"|"")
+			# empty = no upstream or no --count
+			;;
+		"0	"*)
+			echo "+${count#0	}"
+			;;
+		*"	0")
+			echo "-${count%	0}"
+			;;
+		*)
+			echo "+${count#*	}-${count%	*}"
+			;;
+		esac
+	fi
+}
+
+
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
 # returns text to add to bash PS1 prompt (includes branch name)
 __git_ps1 ()
@@ -132,6 +214,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +242,14 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+				p="$(__git_ps1_divergence_from_upstream)"
+			fi
 		fi
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r${p:+ u$p}"
 	fi
 }
 
-- 
1.7.1.561.g94582

[PATCH v2 1/2] rev-list: introduce --count option

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:57

Add a --count option that, instead of actually listing the commits,
merely counts them.

This is mostly geared towards script use, and to this end it acts
specially when used with --left-right: it outputs the left and right
counts separately.  Previously, scripts would have to run a shell loop
or small inline script over to achieve the same.  (Without
--left-right, a simple |wc -l does the job.)

Signed-off-by: Thomas Rast <redacted>
---
 Documentation/rev-list-options.txt   |    9 +++++++++
 builtin/rev-list.c                   |   16 ++++++++++++++++
 revision.c                           |    2 ++
 revision.h                           |    5 +++++
 t/t6007-rev-list-cherry-pick-file.sh |   29 +++++++++++++++++++++++++++++
 5 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index b9fb7a8..066ade9 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -98,6 +98,15 @@ you would get an output like this:
 This implies the '--topo-order' option by default, but the
 '--date-order' option may also be specified.
 
+ifdef::git-rev-list[]
+--count::
+	Print a number stating how many commits would have been
+	listed, and suppress all other output.  When used together
+	with '--left-right', instead print the counts for left and
+	right commits, separated by a tab.
+endif::git-rev-list[]
+
+
 ifndef::git-rev-list[]
 Diff Formatting
 ~~~~~~~~~~~~~~~
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 51ceb19..efe9360 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -50,6 +50,15 @@ static void show_commit(struct commit *commit, void *data)
 
 	graph_show_commit(revs->graph);
 
+	if (revs->count) {
+		if (commit->object.flags & SYMMETRIC_LEFT)
+			revs->count_left++;
+		else
+			revs->count_right++;
+		finish_commit(commit, data);
+		return;
+	}
+
 	if (info->show_timestamp)
 		printf("%lu ", commit->date);
 	if (info->header_prefix)
@@ -400,5 +409,12 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			     quiet ? finish_object : show_object,
 			     &info);
 
+	if (revs.count) {
+		if (revs.left_right)
+			printf("%d\t%d\n", revs.count_left, revs.count_right);
+		else
+			printf("%d\n", revs.count_left + revs.count_right);
+	}
+
 	return 0;
 }
diff --git a/revision.c b/revision.c
index f4b8b38..21b133c 100644
--- a/revision.c
+++ b/revision.c
@@ -1146,6 +1146,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->boundary = 1;
 	} else if (!strcmp(arg, "--left-right")) {
 		revs->left_right = 1;
+	} else if (!strcmp(arg, "--count")) {
+		revs->count = 1;
 	} else if (!strcmp(arg, "--cherry-pick")) {
 		revs->cherry_pick = 1;
 		revs->limited = 1;
diff --git a/revision.h b/revision.h
index 568f1c9..bafa728 100644
--- a/revision.h
+++ b/revision.h
@@ -57,6 +57,7 @@ struct rev_info {
 			limited:1,
 			unpacked:1,
 			boundary:2,
+			count:1,
 			left_right:1,
 			rewrite_parents:1,
 			print_parents:1,
@@ -131,6 +132,10 @@ struct rev_info {
 
 	/* notes-specific options: which refs to show */
 	struct display_notes_opt notes_opt;
+
+	/* commit counts */
+	int count_left;
+	int count_right;
 };
 
 #define REV_TREE_SAME		0
diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh
index 4b8611c..b565638 100755
--- a/t/t6007-rev-list-cherry-pick-file.sh
+++ b/t/t6007-rev-list-cherry-pick-file.sh
@@ -32,6 +32,23 @@ test_expect_success setup '
 	git tag B
 '
 
+cat >expect <<EOF
+<tags/B
+>tags/C
+EOF
+
+test_expect_success '--left-right' '
+	git rev-list --left-right B...C > actual &&
+	git name-rev --stdin --name-only --refs="*tags/*" \
+		< actual > actual.named &&
+	test_cmp actual.named expect
+'
+
+test_expect_success '--count' '
+	git rev-list --count B...C > actual &&
+	test "$(cat actual)" = 2
+'
+
 test_expect_success '--cherry-pick foo comes up empty' '
 	test -z "$(git rev-list --left-right --cherry-pick B...C -- foo)"
 '
@@ -54,4 +71,16 @@ test_expect_success '--cherry-pick with independent, but identical branches' '
 		HEAD...master -- foo)"
 '
 
+cat >expect <<EOF
+1	2
+EOF
+
+# Insert an extra commit to break the symmetry
+test_expect_success '--count --left-right' '
+	git checkout branch &&
+	test_commit D &&
+	git rev-list --count --left-right B...D > actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.7.1.561.g94582

[PATCH v2 0/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:57

[Argh.  Or maybe it's an encoding problem?]

SZEDER Gabor wrote:
Furthermore, I think it would be good to provide means to disable this
feature for some repositories while keeping it enabled for others.  In
the current version I could either disable or enable it globally.
Perhaps we could disable it when bash.showUpstream is set to an empty
value.
Well, I wanted to leave this to Andrew but since I'm already messing
around with it, here's my take on it.  I might be getting a bit
feature creepy, but it should be prepared for all possible uses now.

The semantics now are that (as with e.g. GIT_PS1_SHOWDIRTYSTATE) you
have to set the environment variable to get anything, but after that,
the config *always* overrides (so you can disable again).

Furthermore, the SVN code tries remotes/git-svn first (for
single-branch clones), and there are new features to set a certain ref
or provide a small snippet of hook code.


Andrew Sayers (1):
  bash completion: Support "divergence from upstream" warnings in
    __git_ps1

Thomas Rast (1):
  rev-list: introduce --count option

 Documentation/rev-list-options.txt     |    9 +++
 builtin/rev-list.c                     |   16 ++++++
 contrib/completion/git-completion.bash |   89 +++++++++++++++++++++++++++++++-
 revision.c                             |    2 +
 revision.h                             |    5 ++
 t/t6007-rev-list-cherry-pick-file.sh   |   29 ++++++++++
 6 files changed, 149 insertions(+), 1 deletions(-)

vger doesn't like UTF-8 from send-email

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:57

Thomas Rast wrote:
[Argh.  Or maybe it's an encoding problem?]
First, sorry everyone on the Cc list for the triple post.  I first
blamed it on the fact that I was Cc'ing Gabor, but apparently the
problem was in the content.

The files I handed to git-send-email were UTF-8, and I used my usual
git alias to --cc Gabor on the first pass which also results in an
UTF-8 encoded name.

I got this back from our university mail server:

  git@vger.kernel.org
  vger.kernel.org #550 5.7.1 Content-Policy reject msg: Wrong MIME labeling on 8-bit character texts. BF:<H 0>; S1753608Ab0FLKCQ ##

AFAICT the original message did not declare an encoding:

  Subject: [PATCH v2 0/2] bash completion: Support "divergence from upstream" warnings in __git_ps1
  Date: Sat, 12 Jun 2010 12:02:14 +0200
  Message-ID: [off-list ref]
  X-Mailer: git-send-email 1.7.1.561.g94582
  In-Reply-To: <20100612000002.GA30196@neumann>
  References: <20100612000002.GA30196@neumann>
  MIME-Version: 1.0
  Content-Type: text/plain
  Return-Path: trast@student.ethz.ch

It's hard to be 100% sure though because in the infinite wisdom of MS
Exchange, the bounce came back with everything wrapped in a layer of
HTML(!) and declared latin-1.

Is this a new vger policy, or am I hitting a send-email bug?

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

[PATCH] send-email: ask about and declare 8bit mails

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:57

git-send-email passes on an 8bit mail as-is even if it does not
declare a content-type.  Because the user can edit email between
format-patch and send-email, such invalid mails are unfortunately not
very hard to come by.

Make git-send-email stop and ask about the encoding to use if it
encounters any such mail.  Also provide a configuration setting to
permanently configure an encoding.

Signed-off-by: Thomas Rast <redacted>
---

This takes care of what I ran into earlier today.  However, there's
another problem: format-patch doesn't even mark the patch 8bit if its
patch contents (not log message) are non-ASCII.  I'm really not sure
what to do there.

On the practical hand, there's the problem that the entire
log_tree_commit() call chain is geared towards printing on a file, at
which time it's too late.  So we would either have to go in and fix
all of that to support formatting to a strbuf, or rewrite the patch if
it turns out to be non-ASCII.

On the philosophical hand, we don't really care about file encodings
so far, but this requires declaring one.

Either way, I think if vger doesn't accept format-patch;send-email,
something is really wrong :-)


 Documentation/git-send-email.txt |    9 ++++
 git-send-email.perl              |   59 +++++++++++++++++++++++++++++
 t/t9001-send-email.sh            |   77 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 12622fc..c283084 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -101,6 +101,15 @@ See the CONFIGURATION section for 'sendemail.multiedit'.
 +
 The --to option must be repeated for each user you want on the to list.
 
+--8bit-encoding=<encoding>::
+	When encountering a non-ASCII message or subject that does not
+	declare its encoding, add headers/quoting to indicate it is
+	encoded in <encoding>.  Default is the value of the
+	'sendemail.assume8bitEncoding'; if that is unspecified, this
+	will be prompted for if any non-ASCII files are encountered.
++
+Note that no attempts whatsoever are made to validate the encoding.
+
 
 Sending
 ~~~~~~~
diff --git a/git-send-email.perl b/git-send-email.perl
index 111c981..6b2ac79 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -54,6 +54,7 @@ git send-email [options] <file | directory | rev-list options >
     --in-reply-to           <str>  * Email "In-Reply-To:"
     --annotate                     * Review each patch that will be sent in an editor.
     --compose                      * Open an editor for introduction.
+    --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared
 
   Sending:
     --envelope-sender       <str>  * Email envelope sender.
@@ -191,6 +192,7 @@ my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
 my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts, $smtp_domain);
 my ($validate, $confirm);
 my (@suppress_cc);
+my ($auto_8bit_encoding);
 
 my ($debug_net_smtp) = 0;		# Net::SMTP, see send_message()
 
@@ -222,6 +224,7 @@ my %config_settings = (
     "multiedit" => \$multiedit,
     "confirm"   => \$confirm,
     "from" => \$sender,
+    "assume8bitencoding" => \$auto_8bit_encoding,
 );
 
 # Help users prepare for 1.7.0
@@ -297,6 +300,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
 		    "thread!" => \$thread,
 		    "validate!" => \$validate,
 		    "format-patch!" => \$format_patch,
+		    "8bit-encoding=s" => \$auto_8bit_encoding,
 	 );
 
 unless ($rc) {
@@ -669,6 +673,34 @@ sub ask {
 	return undef;
 }
 
+my %broken_encoding;
+
+sub file_declares_8bit_cte($) {
+	my $fn = shift;
+	open (my $fh, '<', $fn);
+	while (my $line = <$fh>) {
+		return 1 if ($line =~ /^Content-Transfer-Encoding: .*8bit.*$/);
+	}
+	close $fh;
+	return 0;
+}
+
+foreach my $f (@files) {
+	next unless (body_or_subject_has_nonascii($f)
+		     && !file_declares_8bit_cte($f));
+	$broken_encoding{$f} = 1;
+}
+
+if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
+	print "The following files are 8bit, but do not declare " .
+		"a Content-Transfer-Encoding.\n";
+	foreach my $f (sort keys %broken_encoding) {
+		print "    $f\n";
+	}
+	$auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ",
+				  default => "UTF-8");
+}
+
 my $prompting = 0;
 if (!defined $sender) {
 	$sender = $repoauthor || $repocommitter || '';
@@ -1221,6 +1253,18 @@ foreach my $t (@files) {
 			or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
 	}
 
+	if ($broken_encoding{$t} && !$has_content_type) {
+		$has_content_type = 1;
+		push @xh, "MIME-Version: 1.0",
+			"Content-Type: text/plain; charset=$auto_8bit_encoding",
+			"Content-Transfer-Encoding: 8bit";
+		$body_encoding = $auto_8bit_encoding;
+	}
+
+	if ($broken_encoding{$t} && !is_rfc2047_quoted($subject)) {
+		$subject = quote_rfc2047($subject, $auto_8bit_encoding);
+	}
+
 	if (defined $author and $author ne $sender) {
 		$message = "From: $author\n\n$message";
 		if (defined $author_encoding) {
@@ -1233,6 +1277,7 @@ foreach my $t (@files) {
 				}
 			}
 			else {
+				$has_content_type = 1;
 				push @xh,
 				  'MIME-Version: 1.0',
 				  "Content-Type: text/plain; charset=$author_encoding",
@@ -1310,3 +1355,17 @@ sub file_has_nonascii {
 	}
 	return 0;
 }
+
+sub body_or_subject_has_nonascii {
+	my $fn = shift;
+	open(my $fh, '<', $fn)
+		or die "unable to open $fn: $!\n";
+	while (my $line = <$fh>) {
+		last if $line =~ /^$/;
+		return 1 if $line =~ /^Subject.*[^[:ascii:]]/;
+	}
+	while (my $line = <$fh>) {
+		return 1 if $line =~ /[^[:ascii:]]/;
+	}
+	return 0;
+}
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 640b3d2..0b8a591 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -918,4 +918,81 @@ test_expect_success '--no-bcc overrides sendemail.bcc' '
 	! grep "RCPT TO:<other@ex.com>" stdout
 '
 
+cat >email-using-8bit <<EOF
+From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
+Message-Id: <bogus-message-id@example.com>
+From: author@example.com
+Date: Sat, 12 Jun 2010 15:53:58 +0200
+Subject: subject goes here
+
+Dieser deutsche Text enthält einen Umlaut!
+EOF
+
+cat >content-type-decl <<EOF
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+EOF
+
+test_expect_success 'asks about and fixes 8bit encodings' '
+	clean_fake_sendmail &&
+	echo |
+	git send-email --from=author@example.com --to=nobody@example.com \
+			--smtp-server="$(pwd)/fake.sendmail" \
+			email-using-8bit >stdout &&
+	grep "do not declare a Content-Transfer-Encoding" stdout &&
+	grep email-using-8bit stdout &&
+	grep "Which 8bit encoding" stdout &&
+	grep "Content\\|MIME" msgtxt1 >actual &&
+	test_cmp actual content-type-decl
+'
+
+test_expect_success 'sendemail.8bitEncoding works' '
+	clean_fake_sendmail &&
+	git config sendemail.assume8bitEncoding UTF-8 &&
+	echo bogus |
+	git send-email --from=author@example.com --to=nobody@example.com \
+			--smtp-server="$(pwd)/fake.sendmail" \
+			email-using-8bit >stdout &&
+	grep "Content\\|MIME" msgtxt1 >actual &&
+	test_cmp actual content-type-decl
+'
+
+test_expect_success '--8bit-encoding overrides sendemail.8bitEncoding' '
+	clean_fake_sendmail &&
+	git config sendemail.assume8bitEncoding "bogus too" &&
+	echo bogus |
+	git send-email --from=author@example.com --to=nobody@example.com \
+			--smtp-server="$(pwd)/fake.sendmail" \
+			--8bit-encoding=UTF-8 \
+			email-using-8bit >stdout &&
+	grep "Content\\|MIME" msgtxt1 >actual &&
+	test_cmp actual content-type-decl
+'
+
+cat >email-using-8bit <<EOF
+From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
+Message-Id: <bogus-message-id@example.com>
+From: author@example.com
+Date: Sat, 12 Jun 2010 15:53:58 +0200
+Subject: Dieser Betreff enthält auch einen Umlaut!
+
+Nothing to see here.
+EOF
+
+cat >expected <<EOF
+Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
+EOF
+
+test_expect_success '--8bit-encoding also treats subject' '
+	clean_fake_sendmail &&
+	echo bogus |
+	git send-email --from=author@example.com --to=nobody@example.com \
+			--smtp-server="$(pwd)/fake.sendmail" \
+			--8bit-encoding=UTF-8 \
+			email-using-8bit >stdout &&
+	grep "Subject" msgtxt1 >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
1.7.1.557.gd161

[PATCH] bash completion: Support "divergence from upstream" messages in __git_ps1

From: Andrew Sayers <hidden>
Date: 2016-06-15 22:48:57

Add a notification in the command prompt specifying whether (and optionally how
far) your branch has diverged from its upstream.  This is especially helpful in
small teams that very frequently (forget to) push to each other.

Support git-svn upstream detection as a special case, as migrators from
centralised version control systems are especially likely to forget to push.

Also provide ways for the user to specify a custom upstream, or code that
figures out the upstream.

Support for other types of upstream than SVN should be easy to add if anyone is
so inclined.
---

This is based largely on Thomas' patch, but with some significant
differences.  Thanks once again Thomas.

I've made the quieter </> behaviour the default.  A major use case for
me will be over-the-shoulder checking for the rest of my team - I can
probably add a couple of characters to their prompts without raising
any eyebrows, but " u+1-2" is enough UI to provoke people's curiosity.
If they're not interested in this feature, it will be harder for me to
justify 6+ interesting characters than 2 boring ones.  I haven't gone
with Steven's ↑/↓ idea because I don't want to field complaints
about "my terminal is Unicode-aware but those characters are
unreadable in my default font".  I'd rather people edit the source for
that sort of thing.

I've added a message in the "equal to upstream" case, to differentiate
it from the "no upstream" case.  Again, this is an over-the-shoulder
issue - when I see an "=" (or " u=") in someone's prompt, I don't have
to patronise them about whether they've e.g. misconfigured their
branch.

I've added a legacy mode to make the script work without "git rev-list
--count".  I really like the "git rev-list --count" option, but
getting my team to run a patched version of git would be quite a bit
more trouble than it's worth.  If people strongly object to this
feature then I can hide it better or remove it from the public patch.

The documentation for the "legacy" option currently reads "don't use
the '--count' option available in recent versions of git-rev-list".
If/when "--count" makes it into master, this could be changed to
"compatibility mode for git versions less than <version when --count
went in>".

I've made several efficiency improvements, only one of which is
particularly interesting: instead of doing an `echo`, the code now
sets `p=` directly.  Admittedly this is messier, but $p is dynamically
scoped and testing suggests that setting it knocks 10% or so off
run-time.

The code should now handle multiple SVN repositories, by getting all
svn-remote.*.url config options with a --get-regexp.

I like the "ref" option, but I'm not really sure when "eval" would be
useful.  I've changed it here to "cmd" so people are encouraged to put
their work in a script.

I've tried to take Szeder's comments on board, but I'm not really sure
what the problem with unnecessary empty lines is.  If this is a
convention I'm not aware of, could you explain in a bit more detail?

	- Andrew

 contrib/completion/git-completion.bash |  144 +++++++++++++++++++++++++++++++-
 1 files changed, 143 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..7e40f65 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,23 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference between HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.  A "<"
+#       indicates you are behind, ">" indicates you are ahead, and
+#       "<>" indicates you have diverged.  You can further control the
+#       output by setting GIT_PS1_SHOWUPSTREAM to a space-separated
+#       list of values:
+#           git           compare HEAD to @{upstream}
+#           svn           compare HEAD to your SVN upstream
+#           ref=<ref>     compare HEAD to <ref>
+#           cmd=<command> compare HEAD to the output of <command>
+#           verbose       show number of commits ahead/behind (+/-) upstream
+#           legacy        don't use the '--count' option available in recent
+#                         versions of git-rev-list
+#       If none of 'git', 'svn', 'ref' or 'cmd' are specified, your SVN
+#       upstream will be used if configured, or your git upstream otherwise.
+#
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -78,6 +95,126 @@ __gitdir ()
 	fi
 }
 
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+	local cfg=( $( git config --get-regexp '^bash\.showUpstream$|^svn-remote\..*\.url$' 2>/dev/null ) )
+	local svn_remote=() svn_url_pattern count n
+	local upstream=git legacy verbose
+
+	# get some config options from git-config
+	for (( n=0; "$n" != "${#cfg[@]}"; ++n )); do
+		case "${cfg[$n]}" in
+			bash.showUpstream)
+				GIT_PS1_SHOWUPSTREAM="${cfg[$((n+1))]}"
+				if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+					p=""
+					return
+				fi
+				;;
+			svn-remote.*.url)
+				svn_remote[ $(( ${#svn_remote[@]} + 1 )) ]="${cfg[$((n+1))]}"
+				svn_url_pattern+="\\|${cfg[$((n+1))]}"
+				upstream=svn # default upstream is SVN if available
+				;;
+		esac
+	done
+
+	# parse configuration values
+	for option in ${GIT_PS1_SHOWUPSTREAM}; do
+		case "$option" in
+			git|svn|"ref="*|"cmd="*) upstream="$option" ;;
+			verbose) verbose=1 ;;
+			legacy)  legacy=1  ;;
+		esac
+	done
+
+	# Find our upstream
+	case "$upstream" in
+		git)    upstream="@{upstream}" ;;
+		ref\=*) upstream="${option:4}" ;;
+		cmd\=*) upstream=$( "${option:4}" ) ;;
+		svn)
+			# get the upstream from the "git-svn-id: ..." in a commit message
+			# (git-svn uses essentially the same procedure internally)
+			upstream=( $(git log --first-parent -1 \
+					--grep="^git-svn-id: \(${svn_url_pattern:2}\)") )
+			if [[ -n "$upstream" ]]; then
+				upstream=${upstream[ ${#upstream[@]} - 2 ]}
+				upstream=${upstream%@*}
+				for (( n=1; "$n" <= "${#svn_remote[@]}"; ++n )); do
+					upstream=${upstream#${svn_remote[$n]}}
+				done
+
+				if [[ -z "$upstream" ]]; then
+					# default branch name for checkouts with no layout:
+					upstream=${GIT_SVN_ID:-git-svn}
+				else
+					upstream=${upstream#/}
+				fi
+
+			fi
+			;;
+	esac
+
+	# Find how many commits we are ahead/behind our upstream
+	if [[ -z "$legacy" ]]; then
+		count="$(git rev-list --count --left-right \
+				"$upstream"...HEAD 2>/dev/null)"
+	else
+		# produce equivalent output to --count for older versions of git
+		local commits
+		if commits="$( git rev-list --left-right "$upstream"...HEAD 2>/dev/null )"
+		then
+			local commit behind=0 ahead=0
+			for commit in $commits
+			do
+				case "$commit" in
+					"<"*) let ++behind
+						;;
+					*)    let ++ahead
+						;;
+				esac
+			done
+			count="$behind	$ahead"
+		else
+			count=""
+		fi
+	fi
+
+	# calculate the result
+	if [[ -z "$verbose" ]]; then
+		case "$count" in
+			"") # no upstream
+				p="" ;;
+			"0	0") # equal to upstream
+				p="=" ;;
+			"0	"*) # ahead of upstream
+				p=">" ;;
+			*"	0") # behind upstream
+				p="<" ;;
+			*)	    # diverged from upstream
+				p="<>" ;;
+		esac
+	else
+		case "$count" in
+			"") # no upstream
+				p="" ;;
+			"0	0") # equal to upstream
+				p=" u=" ;;
+			"0	"*) # ahead of upstream
+				p=" u+${count#0	}" ;;
+			*"	0") # behind upstream
+				p=" u-${count%	0}" ;;
+			*)	    # diverged from upstream
+				p=" u+${count#*	}-${count%	*}" ;;
+		esac
+	fi
+
+}
+
+
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
 # returns text to add to bash PS1 prompt (includes branch name)
 __git_ps1 ()
@@ -132,6 +269,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +297,14 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+				__git_ps1_show_upstream
+			fi
 		fi
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
 	fi
 }
 
-- 
1.7.0.4

Re: vger doesn't like UTF-8 from send-email

From: Michael Witten <hidden>
Date: 2016-06-15 22:48:57

On Sat, Jun 12, 2010 at 05:11, Thomas Rast [off-list ref] wrote:
AFAICT the original message did not declare an encoding:

Subject: [PATCH v2 0/2] bash completion: Support "divergence from upstream" warnings in __git_ps1
Date: Sat, 12 Jun 2010 12:02:14 +0200
Message-ID: [off-list ref]
X-Mailer: git-send-email 1.7.1.561.g94582
In-Reply-To: <20100612000002.GA30196@neumann>
References: <20100612000002.GA30196@neumann>
MIME-Version: 1.0
Content-Type: text/plain
Return-Path: trast@student.ethz.ch
...
Is this a new vger policy, or am I hitting a send-email bug?
Let's assume the headers themselves are already properly encoded.

According to:

    http://www.faqs.org/rfcs/rfc2045.html

we have:

    The proper Content-Transfer-Encoding
    label must always be used.

and:

    An encoding type of 7BIT requires that
    the body is already in a 7bit mail-ready
    representation.  This is the default value
    -- that is, "Content-Transfer-Encoding: 7BIT"
    is assumed if the Content-Transfer-Encoding
    header field is not present.

Moreover, according to:

    http://www.faqs.org/rfcs/rfc2046.html

we have:

    4.1.2    Charset Parameter
    ...
    The default character set, which must be
    assumed in the absence of a charset parameter,
    is US-ASCII.

So, your email is indeed incorrect in 2 ways if the body contains
UTF-8 encoded data.
From what I've skimmed, the mail user agent (MUA)---such as
send-email---could send your unmodified message body by producing
these headers:

    MIME-Version: 1.0
    Content-type: text/plain; charset=utf-8
    Content-transfer-encoding: 8bit

but only 7bit transfer encodings are guaranteed to make it intact to
the destination; consequently, it would probably be a good idea for
the MUA to transform your message into some 7bit encoding, preferably
a human-readable one such as the 'quoted-printable' encoding; after
such a transformation, the headers could be:

    MIME-Version: 1.0
    Content-type: text/plain; charset=utf-8
    Content-transfer-encoding: quoted-printable

Sincerely,
Michael Witten

Re: [PATCH] bash completion: Support "divergence from upstream" messages in __git_ps1

From: Thomas Rast <hidden>
Date: 2016-06-15 22:48:57

Andrew Sayers wrote:
I've added a message in the "equal to upstream" case, to differentiate
it from the "no upstream" case.  Again, this is an over-the-shoulder
issue - when I see an "=" (or " u=") in someone's prompt, I don't have
to patronise them about whether they've e.g. misconfigured their
branch.
I omitted it because I thought it would be too cluttery, but then my
branches seem to rarely agree with their upstream.
+       local cfg=( $( git config --get-regexp '^bash\.showUpstream$|^svn-remote\..*\.url$' 2>/dev/null ) )
Doesn't this break if the config value contains spaces?  I don't know
enough about bash arrays but in my simple tests, the array elements
are split between words.

And with the new design, you practically *expect* the config key to
contain spaces.

Along the same lines, I think
+                               GIT_PS1_SHOWUPSTREAM="${cfg[$((n+1))]}"
+                               if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
can never trigger because bash will never see the empty config string.

Slightly more robust would be to use

  git config --get-regexp '^bash\.showUpstream$|^svn-remote\..*\.url$' \
    2>/dev/null |
  while read key value, do
    # stuff
  done

That still breaks in the case of values containing newlines, though.
I like the "ref" option, but I'm not really sure when "eval" would be
useful.  I've changed it here to "cmd" so people are encouraged to put
their work in a script.
[...]
+#           cmd=<command> compare HEAD to the output of <command>
[...]
+		cmd\=*) upstream=$( "${option:4}" ) ;;
"Encourage" is a mild understatement; AFAICS the code doesn't work
with more than single-word command any more.

The original intent was that the user could put a (very small) shell
script directly in the configuration if the normal DWIMming doesn't
fit his neds, perhaps most likely in the case of git-svn (do other
remote helpers have the same problem?).

Having to wrap it in a script defeats that point, as it becomes almost
as easy to edit the completion script.  So I think if it can't eval,
you might as well remove it.

BTW, please spell $(command) substitution without the spaces.  Your
current style does not match what is already in the file.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

Re: vger doesn't like UTF-8 from send-email

From: Erik Faye-Lund <hidden>
Date: 2016-06-15 22:48:57

On Sun, Jun 13, 2010 at 6:15 AM, Michael Witten [off-list ref] wrote:
On Sat, Jun 12, 2010 at 05:11, Thomas Rast [off-list ref] wrote:
quoted
AFAICT the original message did not declare an encoding:

Subject: [PATCH v2 0/2] bash completion: Support "divergence from upstream" warnings in __git_ps1
Date: Sat, 12 Jun 2010 12:02:14 +0200
Message-ID: [off-list ref]
X-Mailer: git-send-email 1.7.1.561.g94582
In-Reply-To: <20100612000002.GA30196@neumann>
References: <20100612000002.GA30196@neumann>
MIME-Version: 1.0
Content-Type: text/plain
Return-Path: trast@student.ethz.ch
...
Is this a new vger policy, or am I hitting a send-email bug?
Let's assume the headers themselves are already properly encoded.

According to:

   http://www.faqs.org/rfcs/rfc2045.html

we have:

   The proper Content-Transfer-Encoding
   label must always be used.

and:

   An encoding type of 7BIT requires that
   the body is already in a 7bit mail-ready
   representation.  This is the default value
   -- that is, "Content-Transfer-Encoding: 7BIT"
   is assumed if the Content-Transfer-Encoding
   header field is not present.

Moreover, according to:

   http://www.faqs.org/rfcs/rfc2046.html

we have:

   4.1.2    Charset Parameter
   ...
   The default character set, which must be
   assumed in the absence of a charset parameter,
   is US-ASCII.

So, your email is indeed incorrect in 2 ways if the body contains
UTF-8 encoded data.

From what I've skimmed, the mail user agent (MUA)---such as
send-email---could send your unmodified message body by producing
these headers:

   MIME-Version: 1.0
   Content-type: text/plain; charset=utf-8
   Content-transfer-encoding: 8bit

but only 7bit transfer encodings are guaranteed to make it intact to
the destination; consequently, it would probably be a good idea for
the MUA to transform your message into some 7bit encoding, preferably
a human-readable one such as the 'quoted-printable' encoding; after
such a transformation, the headers could be:

   MIME-Version: 1.0
   Content-type: text/plain; charset=utf-8
   Content-transfer-encoding: quoted-printable
QP-encoding is sometimes destructive, and as such not recommended for
patches - in fact, Documentation/SubmittingPatches forbid it. For the
cover-letter the destruction might not be an issue (IIRC it's some
line-feeds that might be added because QP can a line longer than the
maximum line-length), but special casing the encoding for
cover-letters doesn't strike me as The Right Thing To Do(tm).

I think the only real alternative to 8-bit encoding is Base64, and it
sacrifices human-readability. Dunno how bad that is, though.

-- 
Erik "kusma" Faye-Lund

Re: [PATCH v2 2/2] bash completion: Support "divergence from upstream" warnings in __git_ps1

From: SZEDER Gábor <hidden>
Date: 2016-06-15 22:48:57

Hi,

On Sat, Jun 12, 2010 at 11:59:11AM +0200, Thomas Rast wrote:
quoted hunk
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..a6cb435 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,17 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference between HEAD and its upstream,
+#       set GIT_PS1_SHOWUPSTREAM to one of the following:
+#           git          use @{upstream}
+#           svn          attempt to DWIM svn upstream for normal and --stdlayout
+#           ref <ref>    unconditionally use <ref>
+#           eval <code>  evaluate <code> which should print the commit to use
+#       Any other value DWIMs either svn or git, preferring svn if configured.
Something like this should go in there somewhere:

  The bash.showUpstream config variable can be used to override the 
  value of GIT_PS1_SHOWUPSTREAM on a per-repository basis.
+#
+#       The difference will be shown as, e.g., "u+7-5" meaning that you are 7
+#       commits ahead of and 5 commits behind the upstream.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches

[PATCHv4] bash completion: Support "divergence from upstream" messages in __git_ps1

From: Andrew Sayers <hidden>
Date: 2016-06-15 22:48:58

Add a notification in the command prompt specifying whether (and optionally how
far) your branch has diverged from its upstream.  This is especially helpful in
small teams that very frequently (forget to) push to each other.

Support git-svn upstream detection as a special case, as migrators from
centralised version control systems are especially likely to forget to push.

Support for other types of upstream than SVN should be easy to add if anyone is
so inclined.
---

This version removes ref= and cmd=/eval entirely, adds documentation
and reaches once again into the forbidden bash bag to fix Thomas'
issues.

I've used process substitution <(git config) instead of a simple pipe
because it's the only way I know to maintain the value of a local
variable.  To demonstrate, this prints a blank line:

foo() {
	local FOO
	echo foo | while read ; do FOO=$REPLY ; done
	echo $FOO
}
foo

Whereas this prints 'foo':

foo() {
	local FOO
	while read ; do FOO=$REPLY ; done < <( echo foo )
	echo $FOO
}
foo

While working on this patch, I found the following bug in 1.7.0.4:

$ git config --get-regexp '^(bash\.showUpstream)$'
bash.showupstream legacy verbose
$ git config --get-regexp '^(bash\.showUpstream|x)$'
bash.showupstream legacy verbose
$ git config --get-regexp '^(bash\.showupstream|\.)$'
bash.showupstream legacy verbose
$ git config --get-regexp '^(bash\.showUpstream|\.)$'

The last line should print the same value as all the others.  This
seems to be some weird issue with handling uppercase characters, but
I've not yet had time to create a minimal test case or check it on
master - I'll try to make some time tomorrow if it isn't a known
issue.

 contrib/completion/git-completion.bash |  142 +++++++++++++++++++++++++++++++-
 1 files changed, 141 insertions(+), 1 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 57245a8..dabcdaa 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,23 @@
 #       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
 #       untracked files, then a '%' will be shown next to the branch name.
 #
+#       If you would like to see the difference between HEAD and its
+#       upstream, set GIT_PS1_SHOWUPSTREAM to a nonempty value.  A "<"
+#       indicates you are behind, ">" indicates you are ahead, and
+#       "<>" indicates you have diverged.  You can further control
+#       behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated
+#       list of values:
+#           git           compare HEAD to @{upstream}
+#           svn           compare HEAD to your SVN upstream
+#           verbose       show number of commits ahead/behind (+/-) upstream
+#           legacy        don't use the '--count' option available in recent
+#                         versions of git-rev-list
+#       By default, __git_ps1 will compare HEAD to your SVN upstream
+#       if it can find one, or @{upstream} otherwise.  You can
+#       override the value of GIT_PS1_SHOWUPSTREAM on a per-repository
+#       basis by setting the bash.showUpstream config variable.
+#
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -78,6 +95,124 @@ __gitdir ()
 	fi
 }
 
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+	local key value
+	local svn_remote=() svn_url_pattern count n
+	local upstream=git legacy verbose
+
+	# get some config options from git-config
+	while read key value; do
+		case "$key" in
+			bash.showupstream)
+				GIT_PS1_SHOWUPSTREAM="$value"
+				if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+					p=""
+					return
+				fi
+				;;
+			svn-remote.*.url)
+				svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
+				svn_url_pattern+="\\|$value"
+				upstream=svn # default upstream is SVN if available
+				;;
+		esac
+	done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')
+
+	# parse configuration values
+	for option in ${GIT_PS1_SHOWUPSTREAM}; do
+		case "$option" in
+			git|svn) upstream="$option" ;;
+			verbose) verbose=1 ;;
+			legacy)  legacy=1  ;;
+		esac
+	done
+
+	# Find our upstream
+	case "$upstream" in
+		git)    upstream="@{upstream}" ;;
+		svn)
+			# get the upstream from the "git-svn-id: ..." in a commit message
+			# (git-svn uses essentially the same procedure internally)
+			upstream=($(git log --first-parent -1 \
+					--grep="^git-svn-id: \(${svn_url_pattern:2}\)"))
+			if [[ -n "$upstream" ]]; then
+				upstream=${upstream[ ${#upstream[@]} - 2 ]}
+				upstream=${upstream%@*}
+				for ((n=1; "$n" <= "${#svn_remote[@]}"; ++n)); do
+					upstream=${upstream#${svn_remote[$n]}}
+				done
+
+				if [[ -z "$upstream" ]]; then
+					# default branch name for checkouts with no layout:
+					upstream=${GIT_SVN_ID:-git-svn}
+				else
+					upstream=${upstream#/}
+				fi
+
+			fi
+			;;
+	esac
+
+	# Find how many commits we are ahead/behind our upstream
+	if [[ -z "$legacy" ]]; then
+		count="$(git rev-list --count --left-right \
+				"$upstream"...HEAD 2>/dev/null)"
+	else
+		# produce equivalent output to --count for older versions of git
+		local commits
+		if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
+		then
+			local commit behind=0 ahead=0
+			for commit in $commits
+			do
+				case "$commit" in
+					"<"*) let ++behind
+						;;
+					*)    let ++ahead
+						;;
+				esac
+			done
+			count="$behind	$ahead"
+		else
+			count=""
+		fi
+	fi
+
+	# calculate the result
+	if [[ -z "$verbose" ]]; then
+		case "$count" in
+			"") # no upstream
+				p="" ;;
+			"0	0") # equal to upstream
+				p="=" ;;
+			"0	"*) # ahead of upstream
+				p=">" ;;
+			*"	0") # behind upstream
+				p="<" ;;
+			*)	    # diverged from upstream
+				p="<>" ;;
+		esac
+	else
+		case "$count" in
+			"") # no upstream
+				p="" ;;
+			"0	0") # equal to upstream
+				p=" u=" ;;
+			"0	"*) # ahead of upstream
+				p=" u+${count#0	}" ;;
+			*"	0") # behind upstream
+				p=" u-${count%	0}" ;;
+			*)	    # diverged from upstream
+				p=" u+${count#*	}-${count%	*}" ;;
+		esac
+	fi
+
+}
+
+
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
 # returns text to add to bash PS1 prompt (includes branch name)
 __git_ps1 ()
@@ -132,6 +267,7 @@ __git_ps1 ()
 		local s
 		local u
 		local c
+		local p
 
 		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
 			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,10 +295,14 @@ __git_ps1 ()
 			      u="%"
 			   fi
 			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+				__git_ps1_show_upstream
+			fi
 		fi
 
 		local f="$w$i$s$u"
-		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+		printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
 	fi
 }
 
-- 
1.7.0.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help