Re: [PATCH 3/3] clone: propagate empty remote HEAD even with other branches

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux