All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, Jonathan Tan <jonathantanmy@google.com>
Subject: Re: [PATCH 3/3] clone: propagate empty remote HEAD even with other branches
Date: Thu, 7 Jul 2022 13:40:51 -0400	[thread overview]
Message-ID: <Yscaoz8qmPYiiLO5@coredump.intra.peff.net> (raw)
In-Reply-To: <xmqq5yk9hpd9.fsf@gitster.g>

On Wed, Jul 06, 2022 at 03:01:54PM -0700, Junio C Hamano wrote:

> > I am kind of surprised that the code still behaves differently
> > between empty and non-empty cases.  Given the earlier decision above
> > to consistently use the remote's HEAD, I would have expected that
> > setting HEAD to point at an non-existent ref would be done at one
> > place, instead of being done for empty and non-empty clone
> > separately.  We'll find out why while reading the patch, I think.
> 
> OK, that is because we have if/else on the number of refs mapped via
> the refspec by wanted_peer_refs(), and setup_unborn_head is done
> independently in each of these if/else arms.

Right. I was hoping to avoid disturbing the logic too much, because I
didn't want to introduce new bugs. But I took a stab at it and it
doesn't seem too bad:

diff --git a/builtin/clone.c b/builtin/clone.c
index aa0729f62d..7b270d436a 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1290,32 +1290,28 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		remote_head = find_ref_by_name(refs, "HEAD");
 		remote_head_points_at =
 			guess_remote_head(remote_head, mapped_refs, 0);
-
-		if (option_branch) {
-			our_head_points_at =
-				find_remote_branch(mapped_refs, option_branch);
-
-			if (!our_head_points_at)
-				die(_("Remote branch %s not found in upstream %s"),
-				    option_branch, remote_name);
-		} else {
-			our_head_points_at = remote_head_points_at;
-			if (!our_head_points_at)
-				setup_unborn_head(transport_ls_refs_options.unborn_head_target,
-						  reflog_msg.buf);
-		}
+	} else {
+		remote_head_points_at = NULL;
+		remote_head = NULL;
 	}
-	else {
-		if (option_branch)
+
+	if (option_branch) {
+		/* this is a noop if mapped_refs is NULL, but should be OK */
+		our_head_points_at = find_remote_branch(mapped_refs, option_branch);
+		if (!our_head_points_at)
 			die(_("Remote branch %s not found in upstream %s"),
-					option_branch, remote_name);
+			    option_branch, remote_name);
+	} else if (remote_head_points_at) {
+		our_head_points_at = remote_head_points_at;
+	} else {
+		if (!mapped_refs) {
+			warning(_("You appear to have cloned an empty repository."));
+			/* could do this even in mapped_refs case, but we'd
+			 * want to issue a warning ourselves then */
+			option_no_checkout = 1;
+		}
 
-		warning(_("You appear to have cloned an empty repository."));
 		our_head_points_at = NULL;
-		remote_head_points_at = NULL;
-		remote_head = NULL;
-		option_no_checkout = 1;
-
 		setup_unborn_head(transport_ls_refs_options.unborn_head_target,
 				  reflog_msg.buf);
 	}

In fact, I think it may make things more clear. We avoid the duplicate
die() condition for option_branch, and we now have only one call to
setup_unborn_head(). So we could drop patch 2 and just keep it inline
here.

> The following rewrite with the same behaviour may be a bit easier to
> follow.
> [...]
> -		} else {
> +		} else if (remote_head_points_at) {
>  			our_head_points_at = remote_head_points_at;
> -			if (!our_head_points_at)
> -				setup_unborn_head(transport_ls_refs_options.unborn_head_target,
> -						  reflog_msg.buf);
> +		} else {
> +			our_head_points_at = NULL;
> +			setup_unborn_head(transport_ls_refs_options.unborn_head_target,
> +					  reflog_msg.buf);
>  		}

Heh, I actually wrote it that way initially, but then realized it
collapsed to the more terse version. I don't mind doing it either way,
but maybe it's worth the rewrite I showed above.

If so, do you prefer to go straight there in patch 3 (and drop patch 2,
keeping the unborn setup inline), or do you prefer to see it on top?
Normally I'd suggest the former, but I worry that doing it all in one
patch means it's reorganizing the code _and_ changing the behavior all
at once, which is harder to reason about. And I don't see an easy way to
reorganize the code without changing the behavior.

-Peff

  reply	other threads:[~2022-07-07 17:41 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-06  7:57 [PATCH 0/3] cloning unborn HEAD when other branches are present Jeff King
2022-07-06  8:00 ` [PATCH 1/3] clone: drop extra newline from warning message Jeff King
2022-07-06  8:00 ` [PATCH 2/3] clone: factor out unborn head setup into its own function Jeff King
2022-07-06  8:03 ` [PATCH 3/3] clone: propagate empty remote HEAD even with other branches Jeff King
2022-07-06 18:19   ` Junio C Hamano
2022-07-06 22:01     ` Junio C Hamano
2022-07-07 17:40       ` Jeff King [this message]
2022-07-07 18:50         ` Junio C Hamano
2022-07-07 23:54           ` [PATCH v2 0/3] cloning unborn HEAD when other branches are present Jeff King
2022-07-07 23:54             ` [PATCH v2 1/3] clone: drop extra newline from warning message Jeff King
2022-07-07 23:57             ` [PATCH v2 2/3] clone: propagate empty remote HEAD even with other branches Jeff King
2022-07-08 15:41               ` Junio C Hamano
2022-07-08 16:08                 ` Jeff King
2022-07-07 23:59             ` [PATCH v2 3/3] clone: use remote branch if it matches default HEAD Jeff King
2022-07-08 16:28               ` Junio C Hamano
2022-07-08 19:30                 ` Jeff King
2022-07-08 20:33                   ` Junio C Hamano
2022-07-11  9:21                     ` [PATCH v2 4/3] clone: move unborn head creation to update_head() Jeff King
2022-07-11 20:36                       ` Junio C Hamano
2022-07-07 17:23     ` [PATCH 3/3] clone: propagate empty remote HEAD even with other branches Jeff King
2022-07-06 18:17 ` [PATCH 0/3] cloning unborn HEAD when other branches are present Jonathan Tan

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=Yscaoz8qmPYiiLO5@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.