git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / 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 v2 3/3] clone: use remote branch if it matches default HEAD
Date: Fri, 8 Jul 2022 15:30:51 -0400	[thread overview]
Message-ID: <YsiF6+RjEsmwviuS@coredump.intra.peff.net> (raw)
In-Reply-To: <xmqq8rp3wovj.fsf@gitster.g>

On Fri, Jul 08, 2022 at 09:28:00AM -0700, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > +		/*
> > +		 * We may have selected a local default branch name "foo",
> > +		 * and even though the remote's HEAD does not point there,
> > +		 * it may still have a "foo" branch. If so, set it up so
> > +		 * that we can follow the usual checkout code later.
> 
> Very sensible.
> 
> > +		 *
> > +		 * Note that for an empty repo we'll already have set
> > +		 * option_no_checkout above, which would work against us here.
> > +		 * But for an empty repo, find_remote_branch() can never find
> > +		 * a match.
> > +		 */
> > +		our_head_points_at = find_remote_branch(mapped_refs, branch);
> > +
> > +		if (!option_bare && !our_head_points_at)
> >  			install_branch_config(0, branch, remote_name, ref);
> 
> I may be completely confused, but shouldn't the condition read "if
> we are not bare, and we did find the 'branch' in their refs", i.e.
> without "!" in front of our_head_points_at?

No. That line is for setting up the branch config for an unborn head. If
we actually set up our_head_points_at, then the later "usual checkout
code" mentioned above will take care of it (actually it is
update_head(), I think).

Your next thought may be: why does the unborn head code do its own
branch config setup here, and not also rely on update_head()? I think
it's just that update_head() is expecting to see an actual ref object,
and we don't have one. It could probably be taught to handle this case,
like the patch below. I'm not sure if that is more readable or not. On
one hand, it is putting all of the HEAD symref creation and config in
one spot. On the other, it is adding to the pile of widely scoped
variables that have subtle precedence interactions later on in the
function.

diff --git a/builtin/clone.c b/builtin/clone.c
index 0912d268a1..a776563759 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -606,7 +606,7 @@ static void update_remote_refs(const struct ref *refs,
 }
 
 static void update_head(const struct ref *our, const struct ref *remote,
-			const char *msg)
+			const char *unborn, const char *msg)
 {
 	const char *head;
 	if (our && skip_prefix(our->name, "refs/heads/", &head)) {
@@ -632,6 +632,14 @@ static void update_head(const struct ref *our, const struct ref *remote,
 		 */
 		update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NO_DEREF,
 			   UPDATE_REFS_DIE_ON_ERR);
+	} else if (unborn && skip_prefix(unborn, "refs/heads/", &head)) {
+		/* yuck, cut and paste from the "our" block above, but we
+		 * need to make sure that we come after those other options in
+		 * the if/else chain */
+		if (create_symref("HEAD", unborn, NULL) < 0)
+			die(_("unable to update HEAD"));
+		if (!option_bare)
+			install_branch_config(0, head, remote_name, unborn);
 	}
 }
 
@@ -876,6 +884,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	const struct ref *refs, *remote_head;
 	struct ref *remote_head_points_at = NULL;
 	const struct ref *our_head_points_at;
+	char *unborn_head = NULL;
 	struct ref *mapped_refs = NULL;
 	const struct ref *ref;
 	struct strbuf key = STRBUF_INIT;
@@ -1282,8 +1291,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		our_head_points_at = NULL;
 	} else {
 		const char *branch;
-		const char *ref;
-		char *ref_free = NULL;
 
 		if (!mapped_refs) {
 			warning(_("You appear to have cloned an empty repository."));
@@ -1293,12 +1300,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		if (transport_ls_refs_options.unborn_head_target &&
 		    skip_prefix(transport_ls_refs_options.unborn_head_target,
 				"refs/heads/", &branch)) {
-			ref = transport_ls_refs_options.unborn_head_target;
-			create_symref("HEAD", ref, reflog_msg.buf);
+			unborn_head  = xstrdup(transport_ls_refs_options.unborn_head_target);
 		} else {
 			branch = git_default_branch_name(0);
-			ref_free = xstrfmt("refs/heads/%s", branch);
-			ref = ref_free;
+			unborn_head = xstrfmt("refs/heads/%s", branch);
 		}
 
 		/*
@@ -1313,10 +1318,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		 * a match.
 		 */
 		our_head_points_at = find_remote_branch(mapped_refs, branch);
-
-		if (!option_bare && !our_head_points_at)
-			install_branch_config(0, branch, remote_name, ref);
-		free(ref_free);
 	}
 
 	write_refspec_config(src_ref_prefix, our_head_points_at,
@@ -1336,7 +1337,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 			   branch_top.buf, reflog_msg.buf, transport,
 			   !is_local);
 
-	update_head(our_head_points_at, remote_head, reflog_msg.buf);
+	update_head(our_head_points_at, remote_head, unborn_head, reflog_msg.buf);
 
 	/*
 	 * We want to show progress for recursive submodule clones iff
@@ -1363,6 +1364,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	strbuf_release(&key);
 	free_refs(mapped_refs);
 	free_refs(remote_head_points_at);
+	free(unborn_head);
 	free(dir);
 	free(path);
 	UNLEAK(repo);

  reply	other threads:[~2022-07-08 19:32 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
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 [this message]
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

  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=YsiF6+RjEsmwviuS@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.
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).