Merge branch 'cc/tests-without-assuming-ref-files-backend'
[gitweb.git] / builtin / clone.c
index 284651797e5402c9f7ef85003d7d1c4ea944e2d7..99e73dae8595d37f704d0fe7f7fd84a190edfcf6 100644 (file)
@@ -14,6 +14,7 @@
 #include "parse-options.h"
 #include "fetch-pack.h"
 #include "refs.h"
+#include "refspec.h"
 #include "tree.h"
 #include "tree-walk.h"
 #include "unpack-trees.h"
@@ -26,6 +27,8 @@
 #include "run-command.h"
 #include "connected.h"
 #include "packfile.h"
+#include "list-objects-filter-options.h"
+#include "object-store.h"
 
 /*
  * Overall FIXMEs:
@@ -60,6 +63,7 @@ static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
 static int option_dissociate;
 static int max_jobs = -1;
 static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
+static struct list_objects_filter_options filter_options;
 
 static int recurse_submodules_cb(const struct option *opt,
                                 const char *arg, int unset)
@@ -135,6 +139,7 @@ static struct option builtin_clone_options[] = {
                        TRANSPORT_FAMILY_IPV4),
        OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
                        TRANSPORT_FAMILY_IPV6),
+       OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
        OPT_END()
 };
 
@@ -542,7 +547,7 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
 }
 
 static struct ref *wanted_peer_refs(const struct ref *refs,
-               struct refspec *refspec)
+               struct refspec_item *refspec)
 {
        struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
        struct ref *local_refs = head;
@@ -819,7 +824,7 @@ static void write_refspec_config(const char *src_ref_prefix,
                        } else if (remote_head_points_at) {
                                const char *head = remote_head_points_at->name;
                                if (!skip_prefix(head, "refs/heads/", &head))
-                                       die("BUG: remote HEAD points at non-head?");
+                                       BUG("remote HEAD points at non-head?");
 
                                strbuf_addf(&value, "+%s:%s%s", remote_head_points_at->name,
                                                branch_top->buf, head);
@@ -890,8 +895,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        int err = 0, complete_refs_before_fetch = 1;
        int submodule_progress;
 
-       struct refspec *refspec;
-       const char *fetch_pattern;
+       struct refspec_item refspec;
+
+       fetch_if_missing = 0;
 
        packet_trace_identity("clone");
        argc = parse_options(argc, argv, prefix, builtin_clone_options,
@@ -1071,8 +1077,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        if (option_required_reference.nr || option_optional_reference.nr)
                setup_reference();
 
-       fetch_pattern = value.buf;
-       refspec = parse_fetch_refspec(1, &fetch_pattern);
+       refspec_item_init(&refspec, value.buf, REFSPEC_FETCH);
 
        strbuf_reset(&value);
 
@@ -1090,6 +1095,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                        warning(_("--shallow-since is ignored in local clones; use file:// instead."));
                if (option_not.nr)
                        warning(_("--shallow-exclude is ignored in local clones; use file:// instead."));
+               if (filter_options.choice)
+                       warning(_("--filter is ignored in local clones; use file:// instead."));
                if (!access(mkpath("%s/shallow", path), F_OK)) {
                        if (option_local > 0)
                                warning(_("source repository is shallow, ignoring --local"));
@@ -1118,13 +1125,19 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                transport_set_option(transport, TRANS_OPT_UPLOADPACK,
                                     option_upload_pack);
 
-       if (transport->smart_options && !deepen)
+       if (filter_options.choice) {
+               transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
+                                    filter_options.filter_spec);
+               transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
+       }
+
+       if (transport->smart_options && !deepen && !filter_options.choice)
                transport->smart_options->check_self_contained_and_connected = 1;
 
-       refs = transport_get_remote_refs(transport);
+       refs = transport_get_remote_refs(transport, NULL);
 
        if (refs) {
-               mapped_refs = wanted_peer_refs(refs, refspec);
+               mapped_refs = wanted_peer_refs(refs, &refspec);
                /*
                 * transport_get_remote_refs() may return refs with null sha-1
                 * in mapped_refs (see struct transport->get_refs_list
@@ -1178,13 +1191,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        write_refspec_config(src_ref_prefix, our_head_points_at,
                        remote_head_points_at, &branch_top);
 
+       if (filter_options.choice)
+               partial_clone_register("origin", &filter_options);
+
        if (is_local)
                clone_local(path, git_dir);
        else if (refs && complete_refs_before_fetch)
                transport_fetch_refs(transport, mapped_refs);
 
        update_remote_refs(refs, mapped_refs, remote_head_points_at,
-                          branch_top.buf, reflog_msg.buf, transport, !is_local);
+                          branch_top.buf, reflog_msg.buf, transport,
+                          !is_local && !filter_options.choice);
 
        update_head(our_head_points_at, remote_head, reflog_msg.buf);
 
@@ -1200,11 +1217,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        transport_disconnect(transport);
 
        if (option_dissociate) {
-               close_all_packs();
+               close_all_packs(the_repository->objects);
                dissociate_from_references();
        }
 
        junk_mode = JUNK_LEAVE_REPO;
+       fetch_if_missing = 1;
        err = checkout(submodule_progress);
 
        strbuf_release(&reflog_msg);
@@ -1213,6 +1231,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        strbuf_release(&value);
        junk_mode = JUNK_LEAVE_ALL;
 
-       free(refspec);
+       refspec_item_clear(&refspec);
        return err;
 }