Merge branch 'tr/rev-list-count'
* tr/rev-list-count: bash completion: Support "divergence from upstream" messages in __git_ps1 rev-list: introduce --count option Conflicts: contrib/completion/git-completion.bash
This commit is contained in:
		@ -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
 | 
			
		||||
~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,24 @@
 | 
			
		||||
#       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="auto".  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:
 | 
			
		||||
#           verbose       show number of commits ahead/behind (+/-) upstream
 | 
			
		||||
#           legacy        don't use the '--count' option available in recent
 | 
			
		||||
#                         versions of git-rev-list
 | 
			
		||||
#           git           always compare HEAD to @{upstream}
 | 
			
		||||
#           svn           always compare HEAD to your SVN upstream
 | 
			
		||||
#       By default, __git_ps1 will compare HEAD to your SVN upstream
 | 
			
		||||
#       if it can find one, or @{upstream} otherwise.  Once you have
 | 
			
		||||
#       set GIT_PS1_SHOWUPSTREAM, you can override it on a
 | 
			
		||||
#       per-repository basis by setting the bash.showUpstream config
 | 
			
		||||
#       variable.
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# To submit patches:
 | 
			
		||||
#
 | 
			
		||||
#    *) Read Documentation/SubmittingPatches
 | 
			
		||||
@ -78,6 +96,125 @@ __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+git # default upstream is SVN if available, else git
 | 
			
		||||
			;;
 | 
			
		||||
		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)
 | 
			
		||||
		local svn_upstream=($(git log --first-parent -1 \
 | 
			
		||||
					--grep="^git-svn-id: \(${svn_url_pattern:2}\)" 2>/dev/null))
 | 
			
		||||
		if [[ 0 -ne ${#svn_upstream[@]} ]]; then
 | 
			
		||||
			svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
 | 
			
		||||
			svn_upstream=${svn_upstream%@*}
 | 
			
		||||
			for ((n=1; "$n" <= "${#svn_remote[@]}"; ++n)); do
 | 
			
		||||
				svn_upstream=${svn_upstream#${svn_remote[$n]}}
 | 
			
		||||
			done
 | 
			
		||||
 | 
			
		||||
			if [[ -z "$svn_upstream" ]]; then
 | 
			
		||||
				# default branch name for checkouts with no layout:
 | 
			
		||||
				upstream=${GIT_SVN_ID:-git-svn}
 | 
			
		||||
			else
 | 
			
		||||
				upstream=${svn_upstream#/}
 | 
			
		||||
			fi
 | 
			
		||||
		elif [[ "svn+git" = "$upstream" ]]; then
 | 
			
		||||
			upstream="@{upstream}"
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1253,6 +1253,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;
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ struct rev_info {
 | 
			
		||||
			limited:1,
 | 
			
		||||
			unpacked:1,
 | 
			
		||||
			boundary:2,
 | 
			
		||||
			count:1,
 | 
			
		||||
			left_right:1,
 | 
			
		||||
			rewrite_parents:1,
 | 
			
		||||
			print_parents:1,
 | 
			
		||||
@ -132,6 +133,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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user