git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Jonathan Tan <jonathantanmy@google.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] transport: report refs only if transport does
Date: Tue, 31 Jul 2018 15:24:15 -0400	[thread overview]
Message-ID: <20180731192415.GC3372@sigill.intra.peff.net> (raw)
In-Reply-To: <20180730225601.107502-1-jonathantanmy@google.com>

On Mon, Jul 30, 2018 at 03:56:01PM -0700, Jonathan Tan wrote:

> Commit 989b8c4452 ("fetch-pack: put shallow info in output parameter",
> 2018-06-28) allows transports to report the refs that they have fetched
> in a new out-parameter "fetched_refs". If they do so,
> transport_fetch_refs() makes this information available to its caller.
> 
> Because transport_fetch_refs() filters the refs sent to the transport,
> it cannot just report the transport's result directly, but first needs
> to readd the excluded refs, pretending that they are fetched. However,
> this results in a wrong result if the transport did not report the refs
> that they have fetched in "fetched_refs" - the excluded refs would be
> added and reported, presenting an incomplete picture to the caller.

This part leaves me confused. If we are not fetching them, then why do
we need to pretend that they are fetched?

I think I am showing my lack of understanding about the reason for this
whole "return the fetched refs" scheme from 989b8c4452, and probably
reading the rest of that series would make it more clear. But from the
perspective of somebody digging into history and finding just this
commit, it probably needs to lay out a little more of the reasoning.

> Thanks for the reproduction recipe, Peff. Here's a fix. It can be
> reproduced with something using a remote helper's fetch command (and not
> using "connect" or "stateless-connect"), fetching at least one ref that
> requires a ref update and at least one that does not (as you can see
> from the included test).

Ah, that explains why I couldn't reproduce it with another repository; I
was using a direct git-upload-pack fetch, which wouldn't trigger the
remote helper code.

> diff --git a/transport.c b/transport.c
> index fdd813f684..2a2415d79c 100644
> --- a/transport.c
> +++ b/transport.c
> @@ -1230,17 +1230,18 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs,
>  	struct ref **heads = NULL;
>  	struct ref *nop_head = NULL, **nop_tail = &nop_head;
>  	struct ref *rm;
> +	struct ref *fetched_by_transport = NULL;
>  
>  	for (rm = refs; rm; rm = rm->next) {
>  		nr_refs++;
>  		if (rm->peer_ref &&
>  		    !is_null_oid(&rm->old_oid) &&
>  		    !oidcmp(&rm->peer_ref->old_oid, &rm->old_oid)) {
> -			/*
> -			 * These need to be reported as fetched, but we don't
> -			 * actually need to fetch them.
> -			 */
>  			if (fetched_refs) {
> +				/*
> +				 * These may need to be reported as fetched,
> +				 * but we don't actually need to fetch them.
> +				 */

So it's really this comment that leaves me the most puzzled.

> @@ -1264,10 +1265,25 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs,
>  			heads[nr_heads++] = rm;
>  	}
>  
> -	rc = transport->vtable->fetch(transport, nr_heads, heads, fetched_refs);
> -	if (fetched_refs && nop_head) {
> -		*nop_tail = *fetched_refs;
> -		*fetched_refs = nop_head;
> +	rc = transport->vtable->fetch(transport, nr_heads, heads,
> +				      fetched_refs ? &fetched_by_transport : NULL);
> +	if (fetched_refs) {
> +		if (fetched_by_transport) {
> +			/*
> +			 * The transport reported its fetched refs. Pretend
> +			 * that we also fetched the ones that we didn't need to
> +			 * fetch.
> +			 */
> +			*nop_tail = fetched_by_transport;
> +			*fetched_refs = nop_head;
> +		} else if (!fetched_by_transport) {
> +			/*
> +			 * The transport didn't report its fetched refs, so
> +			 * this function will not report them either. We have
> +			 * no use for nop_head.
> +			 */
> +			free_refs(nop_head);
> +		}

This part makes sense to me based on the description (and on the
assumption that reporting those nop refs is useful in the first place ;)
).

So I think your fix here is probably the right thing, but I'm just left
confused by the background a bit.

-Peff

  reply	other threads:[~2018-07-31 19:24 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-29 12:19 [BUG] fetching sometimes doesn't update refs Jeff King
2018-07-30 17:53 ` Brandon Williams
2018-07-30 22:56 ` [PATCH] transport: report refs only if transport does Jonathan Tan
2018-07-31 19:24   ` Jeff King [this message]
2018-07-31 21:38     ` Junio C Hamano
2018-07-31 23:29       ` Jonathan Tan
2018-07-31 23:23     ` Jonathan Tan
2018-08-01 17:18       ` Brandon Williams
2018-08-02 16:30       ` Jeff King
2018-08-01 20:13 ` [PATCH] fetch-pack: unify ref in and out param Jonathan Tan
2018-08-01 21:38   ` Brandon Williams
2018-08-01 22:23     ` Junio C Hamano
2018-08-02 16:40   ` Jeff King

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

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

  git send-email \
    --in-reply-to=20180731192415.GC3372@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=jonathantanmy@google.com \
    /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.
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).