aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/clone.c44
-rw-r--r--remote.c2
-rw-r--r--remote.h5
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);