From 7a52a8c7d855d3ed779059af160248934ac2c6b0 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Thu, 6 Feb 2025 07:33:33 +0100 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- 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 ef4af1f3e6..1d421c8f75 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 0f6fba8562..cf82376482 100644 --- a/remote.c +++ b/remote.c @@ -1234,7 +1234,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 bda10dd5c8..c4acb832a1 100644 --- a/remote.h +++ b/remote.h @@ -219,6 +219,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);