for-each-ref: always check stat_tracking_info()'s return value

The code handling %(upstream:track) and %(upstream:trackshort)
assumed that 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.

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").

Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Raphael Kubo da Costa 2015-01-05 11:58:55 +02:00 committed by Junio C Hamano
parent 9a8c2b67cd
commit b6160d950c
2 changed files with 22 additions and 2 deletions

View file

@ -728,7 +728,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) {
@ -746,7 +749,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)

View file

@ -334,6 +334,19 @@ test_expect_success 'Check that :track[short] cannot be used with other atoms' '
test_must_fail git for-each-ref --format="%(refname:trackshort)" 2>/dev/null
'
test_expect_success 'Check that :track[short] works when upstream is invalid' '
cat >expected <<-\EOF &&
EOF
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 >actual &&
test_cmp expected actual
'
cat >expected <<EOF
$(git rev-parse --short HEAD)
EOF