git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] for-each-ref: Always check stat_tracking_info()'s return value.
@ 2015-01-02 21:01 Raphael Kubo da Costa
  2015-01-03 11:41 ` Jeff King
  0 siblings, 1 reply; 3+ messages in thread
From: Raphael Kubo da Costa @ 2015-01-02 21:01 UTC (permalink / raw)
  To: git; +Cc: Raphael Kubo da Costa

The code handling %(upstream:track) and %(upstream:trackshort) assumed
it always had a valid branch that had been sanitized earlier in
populate_value(), and thus did not check the return value of the call to
stat_tracking_info().

While there is indeed some sanitization code that basically corresponds
to stat_tracking_info() returning 0 (no base branch set), the function
can also return -1 when the base branch did exist but has since then
been deleted.

In this case, num_ours and num_theirs had undefined values and a call to
`git for-each-ref --format="%(upstream:track)"` could print spurious
values such as

  [behind -111794512]
  [ahead 38881640, behind 5103867]

even for repositories with one single commit.

We now properly verify stat_tracking_info()'s return value and do not
print anything if it returns -1. This behavior also matches the
documentation ("has no effect if the ref does not have tracking
information associated with it").

Signed-off-by: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
---
v3: Call `test_when_finished' as early as possible to clean up the
    "parent_gone" branch.

 builtin/for-each-ref.c  | 11 +++++++++--
 t/t6300-for-each-ref.sh | 15 +++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 603a90e..52e6323 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -717,7 +717,10 @@ static void populate_value(struct refinfo *ref)
 				 starts_with(name, "upstream")) {
 				char buf[40];
 
-				stat_tracking_info(branch, &num_ours, &num_theirs);
+				if (stat_tracking_info(branch, &num_ours,
+						       &num_theirs) != 1)
+					continue;
+
 				if (!num_ours && !num_theirs)
 					v->s = "";
 				else if (!num_ours) {
@@ -735,7 +738,11 @@ static void populate_value(struct refinfo *ref)
 			} else if (!strcmp(formatp, "trackshort") &&
 				   starts_with(name, "upstream")) {
 				assert(branch);
-				stat_tracking_info(branch, &num_ours, &num_theirs);
+
+				if (stat_tracking_info(branch, &num_ours,
+							&num_theirs) != 1)
+					continue;
+
 				if (!num_ours && !num_theirs)
 					v->s = "=";
 				else if (!num_ours)
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index bda354c..cba3454 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -335,6 +335,21 @@ test_expect_success 'Check that :track[short] cannot be used with other atoms' '
 '
 
 cat >expected <<EOF
+
+
+EOF
+
+test_expect_success 'Check that :track[short] works when upstream is gone' '
+	git branch --track to_delete master &&
+	git branch --track parent_gone to_delete &&
+	test_when_finished "git branch -D parent_gone" &&
+	git branch -D to_delete &&
+	git for-each-ref --format="%(upstream:track)" refs/heads/parent_gone >actual &&
+	git for-each-ref --format="%(upstream:trackshort)" refs/heads/parent_gone >>actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
 $(git rev-parse --short HEAD)
 EOF
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v3] for-each-ref: Always check stat_tracking_info()'s return value.
  2015-01-02 21:01 [PATCH v3] for-each-ref: Always check stat_tracking_info()'s return value Raphael Kubo da Costa
@ 2015-01-03 11:41 ` Jeff King
  2015-01-03 19:19   ` Raphael Kubo da Costa
  0 siblings, 1 reply; 3+ messages in thread
From: Jeff King @ 2015-01-03 11:41 UTC (permalink / raw)
  To: Raphael Kubo da Costa; +Cc: git

On Fri, Jan 02, 2015 at 11:01:53PM +0200, Raphael Kubo da Costa wrote:

> In this case, num_ours and num_theirs had undefined values and a call to
> `git for-each-ref --format="%(upstream:track)"` could print spurious
> values such as
> 
>   [behind -111794512]
>   [ahead 38881640, behind 5103867]
> 
> even for repositories with one single commit.
> 
> We now properly verify stat_tracking_info()'s return value and do not
> print anything if it returns -1. This behavior also matches the
> documentation ("has no effect if the ref does not have tracking
> information associated with it").

Thanks, this iteration looks good to me, and this is definitely a bug
worth fixing.

> +test_expect_success 'Check that :track[short] works when upstream is gone' '
> +	git branch --track to_delete master &&
> +	git branch --track parent_gone to_delete &&
> +	test_when_finished "git branch -D parent_gone" &&
> +	git branch -D to_delete &&
> +	git for-each-ref --format="%(upstream:track)" refs/heads/parent_gone >actual &&
> +	git for-each-ref --format="%(upstream:trackshort)" refs/heads/parent_gone >>actual &&
> +	test_cmp expected actual
> +'

I think you could minimize this quite a bit as:

diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index cba3454..f259c22 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -340,12 +340,11 @@ cat >expected <<EOF
 EOF
 
 test_expect_success 'Check that :track[short] works when upstream is gone' '
-	git branch --track to_delete master &&
-	git branch --track parent_gone to_delete &&
-	test_when_finished "git branch -D parent_gone" &&
-	git branch -D to_delete &&
-	git for-each-ref --format="%(upstream:track)" refs/heads/parent_gone >actual &&
-	git for-each-ref --format="%(upstream:trackshort)" refs/heads/parent_gone >>actual &&
+	test_when_finished "git config branch.master.merge refs/heads/master" &&
+	git config branch.master.merge refs/heads/does-not-exist &&
+	git for-each-ref \
+		--format="%(upstream:track)$LF%(upstream:trackshort)" \
+		refs/heads/master >actual &&
 	test_cmp expected actual
 '
 

which IMHO makes it a little more obvious what the setup is doing. But I
am OK with it either way.

-Peff

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v3] for-each-ref: Always check stat_tracking_info()'s return value.
  2015-01-03 11:41 ` Jeff King
@ 2015-01-03 19:19   ` Raphael Kubo da Costa
  0 siblings, 0 replies; 3+ messages in thread
From: Raphael Kubo da Costa @ 2015-01-03 19:19 UTC (permalink / raw)
  To: git

Jeff King <peff@peff.net> writes:

> I think you could minimize this quite a bit as:
>
> diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
> index cba3454..f259c22 100755
> --- a/t/t6300-for-each-ref.sh
> +++ b/t/t6300-for-each-ref.sh
> @@ -340,12 +340,11 @@ cat >expected <<EOF
>  EOF
>  
>  test_expect_success 'Check that :track[short] works when upstream is gone' '
> -	git branch --track to_delete master &&
> -	git branch --track parent_gone to_delete &&
> -	test_when_finished "git branch -D parent_gone" &&
> -	git branch -D to_delete &&
> -	git for-each-ref --format="%(upstream:track)" refs/heads/parent_gone >actual &&
> -	git for-each-ref --format="%(upstream:trackshort)" refs/heads/parent_gone >>actual &&
> +	test_when_finished "git config branch.master.merge refs/heads/master" &&
> +	git config branch.master.merge refs/heads/does-not-exist &&
> +	git for-each-ref \
> +		--format="%(upstream:track)$LF%(upstream:trackshort)" \
> +		refs/heads/master >actual &&
>  	test_cmp expected actual
>  '

Thanks Jeff (and Eric!) for the reviews so far. That does look much
better (the original test case was a reduction of a failure in a
Chromium test case).

One question about this suggestion: this test case actually depends on
the remote manipulations done in the setup test to work, as otherwise we
don't even test stat_tracking_info() because populate_value() would bail
out earlier on branch_get() returning NULL due to the branch's remote
not being set. Is it OK to continue assuming that?

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-01-03 19:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-02 21:01 [PATCH v3] for-each-ref: Always check stat_tracking_info()'s return value Raphael Kubo da Costa
2015-01-03 11:41 ` Jeff King
2015-01-03 19:19   ` Raphael Kubo da Costa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).