ref-filter: use correct branch for %(push:track)

In ref-filter.c, when processing the atom %(push:track), the ahead/behind values are computed using `stat_tracking_info` which refers to the upstream branch. Fix that by introducing a new flag `for_push` in `stat_tracking_info` in remote.c, which does the same thing but for the push branch. Update the few callers of `stat_tracking_info` to handle this flag. This ensure that whenever we use this function in the future, we are careful to specify is this should apply to the upstream or the push branch. This bug was not detected in t/t6300-for-each-ref.sh because in the test for push:track, both the upstream and the push branches were behind by 1 from the local branch. Change the test so that the upstream branch is behind by 1 while the push branch is ahead by 1. This allows us to test that %(push:track) refers to the correct branch. This changes the expected value of some following tests (by introducing new references), so update them too. Signed-off-by: Damien Robert <damien.olivier.robert+git@gmail.com> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Damien Robert committed Apr 16, 2019 at 14:16 UTC c646d0934ec2056d816ad1ecc23f6620aba2c6da
5 files changed +66 -28
ref-filter.c
+4 -2
@@ -1388,7 +1388,8 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
1388 *s = show_ref(&atom->u.remote_ref.refname, refname);
1389 else if (atom->u.remote_ref.option == RR_TRACK) {
1390 if (stat_tracking_info(branch, &num_ours, &num_theirs,
1391 - NULL, AHEAD_BEHIND_FULL) < 0) {
1391 + NULL, atom->u.remote_ref.push,
1392 + AHEAD_BEHIND_FULL) < 0) {
1393 *s = xstrdup(msgs.gone);
1394 } else if (!num_ours && !num_theirs)
1395 *s = xstrdup("");
@@ -1406,7 +1407,8 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
1407 }
1408 } else if (atom->u.remote_ref.option == RR_TRACKSHORT) {
1409 if (stat_tracking_info(branch, &num_ours, &num_theirs,
1409 - NULL, AHEAD_BEHIND_FULL) < 0) {
1410 + NULL, atom->u.remote_ref.push,
1411 + AHEAD_BEHIND_FULL) < 0) {
1412 *s = xstrdup("");
1413 return;
1414 }
remote.c
+47 -21
@@ -1880,37 +1880,27 @@ int resolve_remote_symref(struct ref *ref, struct ref *list)
1880 }
1881
1882 /*
1883 - * Lookup the upstream branch for the given branch and if present, optionally
1884 - * compute the commit ahead/behind values for the pair.
1883 + * Compute the commit ahead/behind values for the pair branch_name, base.
1884 *
1885 * If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
1886 * counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
1887 * the (potentially expensive) a/b computation (*num_ours and *num_theirs are
1888 * set to zero).
1889 *
1891 - * The name of the upstream branch (or NULL if no upstream is defined) is
1892 - * returned via *upstream_name, if it is not itself NULL.
1893 - *
1894 - * Returns -1 if num_ours and num_theirs could not be filled in (e.g., no
1895 - * upstream defined, or ref does not exist). Returns 0 if the commits are
1896 - * identical. Returns 1 if commits are different.
1890 + * Returns -1 if num_ours and num_theirs could not be filled in (e.g., ref
1891 + * does not exist). Returns 0 if the commits are identical. Returns 1 if
1892 + * commits are different.
1893 */
1898 -int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
1899 - const char **upstream_name, enum ahead_behind_flags abf)
1894 +
1895 +static int stat_branch_pair(const char *branch_name, const char *base,
1896 + int *num_ours, int *num_theirs,
1897 + enum ahead_behind_flags abf)
1898 {
1899 struct object_id oid;
1900 struct commit *ours, *theirs;
1901 struct rev_info revs;
1904 - const char *base;
1902 struct argv_array argv = ARGV_ARRAY_INIT;
1903
1907 - /* Cannot stat unless we are marked to build on top of somebody else. */
1908 - base = branch_get_upstream(branch, NULL);
1909 - if (upstream_name)
1910 - *upstream_name = base;
1911 - if (!base)
1912 - return -1;
1913 -
1904 /* Cannot stat if what we used to build on no longer exists */
1905 if (read_ref(base, &oid))
1906 return -1;
@@ -1918,7 +1908,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
1908 if (!theirs)
1909 return -1;
1910
1921 - if (read_ref(branch->refname, &oid))
1911 + if (read_ref(branch_name, &oid))
1912 return -1;
1913 ours = lookup_commit_reference(the_repository, &oid);
1914 if (!ours)
@@ -1932,7 +1922,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
1922 if (abf == AHEAD_BEHIND_QUICK)
1923 return 1;
1924 if (abf != AHEAD_BEHIND_FULL)
1935 - BUG("stat_tracking_info: invalid abf '%d'", abf);
1925 + BUG("stat_branch_pair: invalid abf '%d'", abf);
1926
1927 /* Run "rev-list --left-right ours...theirs" internally... */
1928 argv_array_push(&argv, ""); /* ignored */
@@ -1966,6 +1956,42 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
1956 return 1;
1957 }
1958
1959 +/*
1960 + * Lookup the tracking branch for the given branch and if present, optionally
1961 + * compute the commit ahead/behind values for the pair.
1962 + *
1963 + * If for_push is true, the tracking branch refers to the push branch,
1964 + * otherwise it refers to the upstream branch.
1965 + *
1966 + * The name of the tracking branch (or NULL if it is not defined) is
1967 + * returned via *tracking_name, if it is not itself NULL.
1968 + *
1969 + * If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
1970 + * counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
1971 + * the (potentially expensive) a/b computation (*num_ours and *num_theirs are
1972 + * set to zero).
1973 + *
1974 + * Returns -1 if num_ours and num_theirs could not be filled in (e.g., no
1975 + * upstream defined, or ref does not exist). Returns 0 if the commits are
1976 + * identical. Returns 1 if commits are different.
1977 + */
1978 +int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
1979 + const char **tracking_name, int for_push,
1980 + enum ahead_behind_flags abf)
1981 +{
1982 + const char *base;
1983 +
1984 + /* Cannot stat unless we are marked to build on top of somebody else. */
1985 + base = for_push ? branch_get_push(branch, NULL) :
1986 + branch_get_upstream(branch, NULL);
1987 + if (tracking_name)
1988 + *tracking_name = base;
1989 + if (!base)
1990 + return -1;
1991 +
1992 + return stat_branch_pair(branch->refname, base, num_ours, num_theirs, abf);
1993 +}
1994 +
1995 /*
1996 * Return true when there is anything to report, otherwise false.
1997 */
@@ -1977,7 +2003,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
2003 char *base;
2004 int upstream_is_gone = 0;
2005
1980 - sti = stat_tracking_info(branch, &ours, &theirs, &full_base, abf);
2006 + sti = stat_tracking_info(branch, &ours, &theirs, &full_base, 0, abf);
2007 if (sti < 0) {
2008 if (!full_base)
2009 return 0;
remote.h
+2 -1
@@ -253,7 +253,8 @@ enum ahead_behind_flags {
253
254 /* Reporting of tracking info */
255 int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
256 - const char **upstream_name, enum ahead_behind_flags abf);
256 + const char **upstream_name, int for_push,
257 + enum ahead_behind_flags abf);
258 int format_tracking_info(struct branch *branch, struct strbuf *sb,
259 enum ahead_behind_flags abf);
260
t/t6300-for-each-ref.sh
+11 -2
@@ -392,8 +392,15 @@ test_atom head upstream:track '[ahead 1]'
392 test_atom head upstream:trackshort '>'
393 test_atom head upstream:track,nobracket 'ahead 1'
394 test_atom head upstream:nobracket,track 'ahead 1'
395 -test_atom head push:track '[ahead 1]'
396 -test_atom head push:trackshort '>'
395 +
396 +test_expect_success 'setup for push:track[short]' '
397 + test_commit third &&
398 + git update-ref refs/remotes/myfork/master master &&
399 + git reset master~1
400 +'
401 +
402 +test_atom head push:track '[behind 1]'
403 +test_atom head push:trackshort '<'
404
405 test_expect_success 'Check that :track[short] cannot be used with other atoms' '
406 test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
@@ -420,8 +427,10 @@ test_expect_success 'Check for invalid refname format' '
427 test_expect_success 'set up color tests' '
428 cat >expected.color <<-EOF &&
429 $(git rev-parse --short refs/heads/master) <GREEN>master<RESET>
430 + $(git rev-parse --short refs/remotes/myfork/master) <GREEN>myfork/master<RESET>
431 $(git rev-parse --short refs/remotes/origin/master) <GREEN>origin/master<RESET>
432 $(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET>
433 + $(git rev-parse --short refs/tags/third) <GREEN>third<RESET>
434 $(git rev-parse --short refs/tags/two) <GREEN>two<RESET>
435 EOF
436 sed "s/<[^>]*>//g" <expected.color >expected.bare &&
wt-status.c
+2 -2
@@ -1840,7 +1840,7 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
1840 color_fprintf(s->fp, branch_color_local, "%s", branch_name);
1841
1842 sti = stat_tracking_info(branch, &num_ours, &num_theirs, &base,
1843 - s->ahead_behind_flags);
1843 + 0, s->ahead_behind_flags);
1844 if (sti < 0) {
1845 if (!base)
1846 goto conclude;
@@ -1979,7 +1979,7 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
1979 branch = branch_get(branch_name);
1980 base = NULL;
1981 ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
1982 - &base, s->ahead_behind_flags);
1982 + &base, 0, s->ahead_behind_flags);
1983 if (base) {
1984 base = shorten_unambiguous_ref(base, 0);
1985 fprintf(s->fp, "# branch.upstream %s%c", base, eol);