git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v7 5/7] clone: introduce struct clone_opts in builtin/clone.c

From
Toon Claes <toon@iotcl.com>
Date
Feb 6, 2025, 06:33 UTC
Message-ID
<20250206-toon-clone-refs-v7-5-4622b7392202@iotcl.com>
In-Reply-To
<20250206-toon-clone-refs-v7-0-4622b7392202@iotcl.com>

There is a lot of state stored in global variables in builtin/clone.c. In the long run we'd like to remove many of those.

Introduce `struct clone_opts` in this file. This struct will be used to contain all details needed to perform the clone. The struct object can be thrown around to all the functions that need these details.

The first field we're adding is `wants_head`. In some scenarios (specifically when both `--single-branch` and `--branch` are given) we are not interested in `HEAD` on the remote. The field `wants_head` in `struct clone_opts` will hold this information. We could have put `option_branch` and `option_single_branch` into that struct instead, but in a following commit we'll be using `wants_head` as well.

Signed-off-by: Toon Claes <toon@iotcl.com>
---
 builtin/clone.c | 44 +++++++++++++++++++++++++++++---------------
 remote.c        |  2 +-
 remote.h        |  5 +++++
 3 files changed, 35 insertions(+), 16 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index ef4af1f3e6bf0a33c13ed874587b35aba14fe43c..1d421c8f758e37a7219d2da680c7ef8699016171 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -57,6 +57,13 @@
  *
  */
 
+struct clone_opts {
+	int wants_head;
+};
+#define CLONE_OPTS_INIT { \
+	.wants_head = 1 /* default enabled */ \
+}
+
 static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
 static int option_local = -1, option_no_hardlinks, option_shared;
 static int option_tags = 1; /* default enabled */
@@ -429,23 +436,24 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
 	return ref;
 }
 
-static struct ref *wanted_peer_refs(const struct ref *refs,
-		struct refspec *refspec)
+static struct ref *wanted_peer_refs(struct clone_opts *opts,
+				    const struct ref *refs,
+				    struct refspec *refspec)
 {
-	struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
-	struct ref *local_refs = head;
-	struct ref **tail = local_refs ? &local_refs->next : &local_refs;
+	struct ref *local_refs = NULL;
+	struct ref **tail = &local_refs;
 	struct ref *to_free = NULL;
 
-	if (option_single_branch) {
-		if (!option_branch)
+	if (opts->wants_head) {
+		struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
+		if (head)
+			tail_link_ref(head, &tail);
+		if (option_single_branch)
 			refs = to_free = guess_remote_head(head, refs, 0);
-		else {
-			free_one_ref(head);
-			local_refs = head = NULL;
-			tail = &local_refs;
-			refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
-		}
+	} else if (option_single_branch) {
+		local_refs = NULL;
+		tail = &local_refs;
+		refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
 	}
 
 	for (size_t i = 0; i < refspec->nr; i++)
@@ -893,6 +901,8 @@ int cmd_clone(int argc,
 	struct string_list server_options = STRING_LIST_INIT_NODUP;
 	const char *bundle_uri = NULL;
 
+	struct clone_opts opts = CLONE_OPTS_INIT;
+
 	struct transport_ls_refs_options transport_ls_refs_options =
 		TRANSPORT_LS_REFS_OPTIONS_INIT;
 
@@ -1343,9 +1353,13 @@ int cmd_clone(int argc,
 	if (option_not.nr)
 		transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
 				     (const char *)&option_not);
-	if (option_single_branch)
+	if (option_single_branch) {
 		transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
 
+		if (option_branch)
+			opts.wants_head = 0;
+	}
+
 	if (option_upload_pack)
 		transport_set_option(transport, TRANS_OPT_UPLOADPACK,
 				     option_upload_pack);
@@ -1454,7 +1468,7 @@ int cmd_clone(int argc,
 	}
 
 	if (refs)
-		mapped_refs = wanted_peer_refs(refs, &remote->fetch);
+		mapped_refs = wanted_peer_refs(&opts, refs, &remote->fetch);
 
 	if (mapped_refs) {
 		/*
diff --git a/remote.c b/remote.c
index 1779f0e7bbb8b88965f2fedf407e50ed20ea7a13..69d8c43ea694f1b9a7699e5d5a49bfc169058b8e 100644
--- a/remote.c
+++ b/remote.c
@@ -1260,7 +1260,7 @@ int count_refspec_match(const char *pattern,
 	}
 }
 
-static void tail_link_ref(struct ref *ref, struct ref ***tail)
+void tail_link_ref(struct ref *ref, struct ref ***tail)
 {
 	**tail = ref;
 	while (ref->next)
diff --git a/remote.h b/remote.h
index a19353f68999f5440db7bf5f91dd4be8bcc1d8a5..ce3e7c8512981d0ac5db2da508c4fbe64cede961 100644
--- a/remote.h
+++ b/remote.h
@@ -221,6 +221,11 @@ struct ref *alloc_ref(const char *name);
 struct ref *copy_ref(const struct ref *ref);
 struct ref *copy_ref_list(const struct ref *ref);
 int count_refspec_match(const char *, struct ref *refs, struct ref **matched_ref);
+/*
+ * Put a ref in the tail and prepare tail for adding another one.
+ * *tail is the pointer to the tail of the list of refs.
+ */
+void tail_link_ref(struct ref *ref, struct ref ***tail);
 
 int check_ref_type(const struct ref *ref, int flags);
 
-- 
2.48.1.447.gc0086e9015
Previous: Toon ClaesNext: Toon Claes
Message 53 of 57 in “builtin/clone: teach git-clone(1) the --revision= option”
  1. builtin/clone: teach git-clone(1) the --revision= optionToon Claes, Nov 29, 2024
  2. Patrick SteinhardtDec 2, 2024
  3. Jeff KingDec 2, 2024
  4. Michal SuchánekDec 3, 2024
  5. Toon ClaesDec 19, 2024
  6. builtin/clone: teach git-clone(1) the --revision= optionToon Claes, Dec 19, 2024
  7. Junio C HamanoDec 19, 2024
  8. 0/6 Enable doing a shallow clone of a specific git revisionToon Claes, Jan 31, 2025
  9. 1/6 clone: cut down on global variables in clone.cToon Claes, Jan 31, 2025
  10. 2/6 clone: make it possible to specify --tagsToon Claes, Jan 31, 2025
  11. Jean-Noël AVILAFeb 1, 2025
  12. 3/6 clone: refactor wanted_peer_refs()Toon Claes, Jan 31, 2025
  13. Patrick SteinhardtFeb 3, 2025
  14. 4/6 clone: add tags refspec earlier to fetch refspecToon Claes, Jan 31, 2025
  15. Patrick SteinhardtFeb 3, 2025
  16. 5/6 clone: introduce struct clone_opts in builtin/clone.cToon Claes, Jan 31, 2025
  17. Patrick SteinhardtFeb 3, 2025
  18. 6/6 builtin/clone: teach git-clone(1) the --revision= optionToon Claes, Jan 31, 2025
  19. Junio C HamanoJan 31, 2025
  20. Jean-Noël AVILAFeb 1, 2025
  21. Patrick SteinhardtFeb 3, 2025
  22. 0/7 Enable doing a shallow clone of a specific git revisionToon Claes, Feb 4, 2025
  23. 1/7 clone: cut down on global variables in clone.cToon Claes, Feb 4, 2025
  24. 2/7 clone: make it possible to specify --tagsToon Claes, Feb 4, 2025
  25. Patrick SteinhardtFeb 5, 2025
  26. Toon ClaesFeb 5, 2025
  27. Jean-Noël AVILAFeb 5, 2025
  28. 3/7 clone: refactor wanted_peer_refs()Toon Claes, Feb 4, 2025
  29. 4/7 clone: add tags refspec earlier to fetch refspecToon Claes, Feb 4, 2025
  30. Patrick SteinhardtFeb 5, 2025
  31. 5/7 clone: introduce struct clone_opts in builtin/clone.cToon Claes, Feb 4, 2025
  32. 6/7 parse-options: introduce die_for_incompatible_opt2()Toon Claes, Feb 4, 2025
  33. Patrick SteinhardtFeb 5, 2025
  34. 7/7 builtin/clone: teach git-clone(1) the --revision= optionToon Claes, Feb 4, 2025
  35. Patrick SteinhardtFeb 5, 2025
  36. Toon ClaesFeb 5, 2025
  37. Patrick SteinhardtFeb 5, 2025
  38. Junio C HamanoFeb 5, 2025
  39. 0/7 Enable doing a shallow clone of a specific git revisionToon Claes, Feb 5, 2025
  40. 1/7 clone: cut down on global variables in clone.cToon Claes, Feb 5, 2025
  41. 2/7 clone: make it possible to specify --tagsToon Claes, Feb 5, 2025
  42. 3/7 clone: refactor wanted_peer_refs()Toon Claes, Feb 5, 2025
  43. 4/7 clone: add tags refspec earlier to fetch refspecToon Claes, Feb 5, 2025
  44. 5/7 clone: introduce struct clone_opts in builtin/clone.cToon Claes, Feb 5, 2025
  45. 6/7 parse-options: introduce die_for_incompatible_opt2()Toon Claes, Feb 5, 2025
  46. 7/7 builtin/clone: teach git-clone(1) the --revision= optionToon Claes, Feb 5, 2025
  47. Junio C HamanoFeb 5, 2025
  48. 0/7 Enable doing a shallow clone of a specific git revisionToon Claes, Feb 6, 2025
  49. 1/7 clone: cut down on global variables in clone.cToon Claes, Feb 6, 2025
  50. 2/7 clone: make it possible to specify --tagsToon Claes, Feb 6, 2025
  51. 3/7 clone: refactor wanted_peer_refs()Toon Claes, Feb 6, 2025
  52. 4/7 clone: add tags refspec earlier to fetch refspecToon Claes, Feb 6, 2025
  53. 5/7 clone: introduce struct clone_opts in builtin/clone.cToon Claes, Feb 6, 2025
  54. 6/7 parse-options: introduce die_for_incompatible_opt2()Toon Claes, Feb 6, 2025
  55. 7/7 builtin/clone: teach git-clone(1) the --revision= optionToon Claes, Feb 6, 2025
  56. Patrick SteinhardtFeb 6, 2025
  57. Junio C HamanoFeb 6, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.