clone: refactor wanted_peer_refs()

The function wanted_peer_refs() is used to map the refs returned by the server to refs we will save in our clone. Over time this function grown to be very complex. Refactor it. Previously, there was a separate code path for when `option_single_branch` was set. It resulted in duplicated code and deeper nested conditions. After this refactor the code path for when `option_single_branch` is truthy modifies `refs` and then falls through to the common code path. This approach relies on the `refspec` being set correctly and thus only mapping refs that are relevant. 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 879780f9a15177ed703f56bf347e0a410c22e9d1
1 file changed +15 -24
builtin/clone.c
+15 -24
@@ -434,46 +434,37 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
434 {
435 struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
436 struct ref *local_refs = head;
437 - struct ref **tail = head ? &head->next : &local_refs;
437 + struct ref **tail = local_refs ? &local_refs->next : &local_refs;
438 struct refspec_item tag_refspec;
439 + struct ref *to_free = NULL;
440
441 refspec_item_init(&tag_refspec, TAG_REFSPEC, 0);
442
443 if (option_single_branch) {
443 - struct ref *remote_head = NULL;
444 -
444 if (!option_branch)
446 - remote_head = guess_remote_head(head, refs, 0);
445 + refs = to_free = guess_remote_head(head, refs, 0);
446 else {
447 free_one_ref(head);
448 local_refs = head = NULL;
449 tail = &local_refs;
451 - remote_head = copy_ref(find_remote_branch(refs, option_branch));
452 - }
453 -
454 - if (!remote_head && option_branch)
455 - warning(_("Could not find remote branch %s to clone."),
456 - option_branch);
457 - else {
458 - int i;
459 - for (i = 0; i < refspec->nr; i++)
460 - get_fetch_map(remote_head, &refspec->items[i],
461 - &tail, 0);
462 -
463 - /* if --branch=tag, pull the requested tag explicitly */
464 - get_fetch_map(remote_head, &tag_refspec, &tail, 0);
450 + refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
451 }
466 - free_refs(remote_head);
467 - } else {
468 - int i;
469 - for (i = 0; i < refspec->nr; i++)
470 - get_fetch_map(refs, &refspec->items[i], &tail, 0);
452 }
453
473 - if (!option_mirror && !option_single_branch && option_tags)
454 + for (size_t i = 0; i < refspec->nr; i++)
455 + get_fetch_map(refs, &refspec->items[i], &tail, 0);
456 +
457 + /*
458 + * Grab all refs that match the TAG_REFSPEC. Any tags we don't care
459 + * about won't be present in `refs` anyway.
460 + * Except with option --mirror, where we grab all refs already.
461 + */
462 + if (!option_mirror)
463 get_fetch_map(refs, &tag_refspec, &tail, 0);
464
465 + free_one_ref(to_free);
466 refspec_item_clear(&tag_refspec);
467 +
468 return local_refs;
469 }
470