git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: Damien Robert <damien.olivier.robert@gmail.com>
Cc: git@vger.kernel.org,
	Damien Robert <damien.olivier.robert+git@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Karthik Nayak <karthik.188@gmail.com>,
	Jeff Hostetler <jeffhost@microsoft.com>,
	"brian m. carlson" <sandals@crustytoothpaste.net>
Subject: Re: [PATCH 1/1] Fix %(push:track) in ref-filter
Date: Mon, 15 Apr 2019 18:01:08 -0400	[thread overview]
Message-ID: <20190415220108.GD28128@sigill.intra.peff.net> (raw)
In-Reply-To: <20190415210416.7525-2-damien.olivier.robert+git@gmail.com>

On Mon, Apr 15, 2019 at 11:04:16PM +0200, Damien Robert wrote:

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

Good catch. I think this has been broken since %(push) was added in
29bc88505f (for-each-ref: accept "%(push)" format, 2015-05-21). I don't
actually use the track option, so I never noticed.

> Fix that by introducing a new function `stat_push_info` in remote.c
> (exported in remote.h), which does the same thing but for the push
> branch. Factorise the ahead/behind computation of `stat_tracking_info` into
> `stat_compare_info` so that it can be reused for `stat_push_info`.

Makes sense.

> 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 branch were ahead by 1.
> Change the test so that the upstream branch is ahead by 2 while the push
> branch is ahead by 1, this allow us to test that %(push:track) refer to
> the correct branch.

Nice. I wish all patches were this careful about thinking through
details like this.

> diff --git a/ref-filter.c b/ref-filter.c
> index 3aca105307..82e277222b 100644
> --- a/ref-filter.c
> +++ b/ref-filter.c
> @@ -1391,8 +1391,11 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
>  	if (atom->u.remote_ref.option == RR_REF)
>  		*s = show_ref(&atom->u.remote_ref.refname, refname);
>  	else if (atom->u.remote_ref.option == RR_TRACK) {
> -		if (stat_tracking_info(branch, &num_ours, &num_theirs,
> -				       NULL, AHEAD_BEHIND_FULL) < 0) {
> +		if ((atom->u.remote_ref.push ?
> +		     stat_push_info(branch, &num_ours, &num_theirs,
> +				    NULL, AHEAD_BEHIND_FULL) :
> +		     stat_tracking_info(branch, &num_ours, &num_theirs,
> +					NULL, AHEAD_BEHIND_FULL)) < 0) {
>  			*s = xstrdup(msgs.gone);
>  		} else if (!num_ours && !num_theirs)

I'm a big fan of the "?" operator, but this ternary-within-an-if might
be pushing even my boundaries of taste. :) I wonder if it would be more
readable as:

  int ret;
  if (atom->u.remote_ref.push)
	stat_push_info(...);
  else
	stat_tracking_info(...);
  if (ret < 0)
	... gone ...
  else if (!num_ours && !num_theirs)
	... etc ...

I'd even be OK with a ternary for assigning "ret". :)

All that said, we would need to do the exact same conditional for
":trackshort", wouldn't we? The tests don't pick it up because the
symbol is still ">" for both branches (deja vu!). So it might be worth
not just having push be 2 ahead, but have it actually be behind instead
(or in addition to).

So since we have to do it twice, maybe that makes it worth factoring
out something like:

  int stat_remote_ref(struct used_atom *atom, struct branch *branch,
                      int *num_ours, int *num_theirs)
  {
        if (atom->u.remote_ref.push)
                return stat_push_info(branch, &num_ours, &num_theirs,
                                      NULL, AHEAD_BEHIND_FULL);
        else
                return stat_tracking_info(branch, &num_ours, &num_theirs,
                                          NULL, AHEAD_BEHIND_FULL);
  }

Or perhaps it argues for just giving access to the more generic stat_*
function, and letting callers pass in a flag for push vs upstream (and
either leaving stat_tracking_info() as a wrapper, or just updating its
few callers).

> -int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
> -		       const char **upstream_name, enum ahead_behind_flags abf)
> +
> +int stat_compare_info(const char **branch_name, const char **base,
> +		      int *num_ours, int *num_theirs,
> +		      enum ahead_behind_flags abf)

In the original, we need a pointer-to-pointer for upstream_name, because
we return the string as an out-parameter. But here we're just taking two
strings as input. We can drop the extra layer of indirection, like the
patch below.

Also, since this is an internal helper function for the file, we should
mark it as static.

diff --git a/remote.c b/remote.c
index b2b37d1e8d..e6ca62dc19 100644
--- a/remote.c
+++ b/remote.c
@@ -1895,23 +1895,23 @@ int resolve_remote_symref(struct ref *ref, struct ref *list)
  * commits are different.
  */
 
-int stat_compare_info(const char **branch_name, const char **base,
-		      int *num_ours, int *num_theirs,
-		      enum ahead_behind_flags abf)
+static int stat_compare_info(const char *branch_name, const char *base,
+			     int *num_ours, int *num_theirs,
+			     enum ahead_behind_flags abf)
 {
 	struct object_id oid;
 	struct commit *ours, *theirs;
 	struct rev_info revs;
 	struct argv_array argv = ARGV_ARRAY_INIT;
 
 	/* Cannot stat if what we used to build on no longer exists */
-	if (read_ref(*base, &oid))
+	if (read_ref(base, &oid))
 		return -1;
 	theirs = lookup_commit_reference(the_repository, &oid);
 	if (!theirs)
 		return -1;
 
-	if (read_ref(*branch_name, &oid))
+	if (read_ref(branch_name, &oid))
 		return -1;
 	ours = lookup_commit_reference(the_repository, &oid);
 	if (!ours)
@@ -1987,7 +1987,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
 	if (!base)
 		return -1;
 
-	return stat_compare_info(&(branch->refname), &base, num_ours, num_theirs, abf);
+	return stat_compare_info(branch->refname, base, num_ours, num_theirs, abf);
 }
 
 /*
@@ -2006,7 +2006,7 @@ int stat_push_info(struct branch *branch, int *num_ours, int *num_theirs,
 	if (!base)
 		return -1;
 
-	return stat_compare_info(&(branch->refname), &base, num_ours, num_theirs, abf);
+	return stat_compare_info(branch->refname, base, num_ours, num_theirs, abf);
 }
 
 /*

Of course if you buy my argument above that we should just let
ref-filter call into the generic form of the function, then all of that
would change. :)

> [...]

Other than that, the patch looked quite reasonable. I didn't dig too far
into the ripple effects of the test changes, since I think we'll end up
changing them again to make sure ":trackshort" is distinct.

Thanks for working on this.

-Peff

  reply	other threads:[~2019-04-15 22:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-15 21:04 [PATCH 0/1] Fix a bug in ref-filter Damien Robert
2019-04-15 21:04 ` [PATCH 1/1] Fix %(push:track) " Damien Robert
2019-04-15 22:01   ` Jeff King [this message]
2019-04-16 12:39     ` Damien Robert
2019-04-16 14:13       ` Christian Couder
2019-04-16 21:48       ` Jeff King
2019-04-17  8:17         ` Damien Robert
2019-04-18  0:23           ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190415220108.GD28128@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=damien.olivier.robert+git@gmail.com \
    --cc=damien.olivier.robert@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jeffhost@microsoft.com \
    --cc=karthik.188@gmail.com \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).