clone: introduce struct clone_opts in builtin/clone.c

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> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Toon Claes committed Feb 6, 2025 at 07:33 UTC 7a52a8c7d855d3ed779059af160248934ac2c6b0
3 files changed +35 -16
builtin/clone.c
+29 -15
@@ -57,6 +57,13 @@
57 *
58 */
59
60 +struct clone_opts {
61 + int wants_head;
62 +};
63 +#define CLONE_OPTS_INIT { \
64 + .wants_head = 1 /* default enabled */ \
65 +}
66 +
67 static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
68 static int option_local = -1, option_no_hardlinks, option_shared;
69 static int option_tags = 1; /* default enabled */
@@ -429,23 +436,24 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
436 return ref;
437 }
438
432 -static struct ref *wanted_peer_refs(const struct ref *refs,
433 - struct refspec *refspec)
439 +static struct ref *wanted_peer_refs(struct clone_opts *opts,
440 + const struct ref *refs,
441 + struct refspec *refspec)
442 {
435 - struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
436 - struct ref *local_refs = head;
437 - struct ref **tail = local_refs ? &local_refs->next : &local_refs;
443 + struct ref *local_refs = NULL;
444 + struct ref **tail = &local_refs;
445 struct ref *to_free = NULL;
446
440 - if (option_single_branch) {
441 - if (!option_branch)
447 + if (opts->wants_head) {
448 + struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
449 + if (head)
450 + tail_link_ref(head, &tail);
451 + if (option_single_branch)
452 refs = to_free = guess_remote_head(head, refs, 0);
443 - else {
444 - free_one_ref(head);
445 - local_refs = head = NULL;
446 - tail = &local_refs;
447 - refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
448 - }
453 + } else if (option_single_branch) {
454 + local_refs = NULL;
455 + tail = &local_refs;
456 + refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
457 }
458
459 for (size_t i = 0; i < refspec->nr; i++)
@@ -893,6 +901,8 @@ int cmd_clone(int argc,
901 struct string_list server_options = STRING_LIST_INIT_NODUP;
902 const char *bundle_uri = NULL;
903
904 + struct clone_opts opts = CLONE_OPTS_INIT;
905 +
906 struct transport_ls_refs_options transport_ls_refs_options =
907 TRANSPORT_LS_REFS_OPTIONS_INIT;
908
@@ -1343,9 +1353,13 @@ int cmd_clone(int argc,
1353 if (option_not.nr)
1354 transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
1355 (const char *)&option_not);
1346 - if (option_single_branch)
1356 + if (option_single_branch) {
1357 transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
1358
1359 + if (option_branch)
1360 + opts.wants_head = 0;
1361 + }
1362 +
1363 if (option_upload_pack)
1364 transport_set_option(transport, TRANS_OPT_UPLOADPACK,
1365 option_upload_pack);
@@ -1454,7 +1468,7 @@ int cmd_clone(int argc,
1468 }
1469
1470 if (refs)
1457 - mapped_refs = wanted_peer_refs(refs, &remote->fetch);
1471 + mapped_refs = wanted_peer_refs(&opts, refs, &remote->fetch);
1472
1473 if (mapped_refs) {
1474 /*
remote.c
+1 -1
@@ -1234,7 +1234,7 @@ int count_refspec_match(const char *pattern,
1234 }
1235 }
1236
1237 -static void tail_link_ref(struct ref *ref, struct ref ***tail)
1237 +void tail_link_ref(struct ref *ref, struct ref ***tail)
1238 {
1239 **tail = ref;
1240 while (ref->next)
remote.h
+5
@@ -219,6 +219,11 @@ struct ref *alloc_ref(const char *name);
219 struct ref *copy_ref(const struct ref *ref);
220 struct ref *copy_ref_list(const struct ref *ref);
221 int count_refspec_match(const char *, struct ref *refs, struct ref **matched_ref);
222 +/*
223 + * Put a ref in the tail and prepare tail for adding another one.
224 + * *tail is the pointer to the tail of the list of refs.
225 + */
226 +void tail_link_ref(struct ref *ref, struct ref ***tail);
227
228 int check_ref_type(const struct ref *ref, int flags);
229