clone: partial clone
[gitweb.git] / builtin / fetch.c
index c87e59f3b1def1f064e0dae54a14e310c06df1fa..14aab71c2ce0695aaad16ff4f59641d2e11265ef 100644 (file)
@@ -17,6 +17,8 @@
 #include "connected.h"
 #include "argv-array.h"
 #include "utf8.h"
+#include "packfile.h"
+#include "list-objects-filter-options.h"
 
 static const char * const builtin_fetch_usage[] = {
        N_("git fetch [<options>] [<repository> [<refspec>...]]"),
@@ -39,7 +41,7 @@ static int prune = -1; /* unspecified */
 static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative;
 static int progress = -1;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
-static int max_children = -1;
+static int max_children = 1;
 static enum transport_family family;
 static const char *depth;
 static const char *deepen_since;
@@ -54,6 +56,7 @@ static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
 static int shown_url = 0;
 static int refmap_alloc, refmap_nr;
 static const char **refmap_array;
+static struct list_objects_filter_options filter_options;
 
 static int git_fetch_config(const char *k, const char *v, void *cb)
 {
@@ -68,9 +71,30 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
                recurse_submodules = r;
        }
 
+       if (!strcmp(k, "submodule.fetchjobs")) {
+               max_children = parse_submodule_fetchjobs(k, v);
+               return 0;
+       } else if (!strcmp(k, "fetch.recursesubmodules")) {
+               recurse_submodules = parse_fetch_recurse_submodules_arg(k, v);
+               return 0;
+       }
+
        return git_default_config(k, v, cb);
 }
 
+static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "submodule.fetchjobs")) {
+               max_children = parse_submodule_fetchjobs(var, value);
+               return 0;
+       } else if (!strcmp(var, "fetch.recursesubmodules")) {
+               recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
+               return 0;
+       }
+
+       return 0;
+}
+
 static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
 {
        ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
@@ -138,6 +162,7 @@ static struct option builtin_fetch_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()
 };
 
@@ -1022,6 +1047,11 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
                set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes");
        if (update_shallow)
                set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
+       if (filter_options.choice) {
+               set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
+                          filter_options.filter_spec);
+               set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
+       }
        return transport;
 }
 
@@ -1300,17 +1330,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 {
        int i;
        struct string_list list = STRING_LIST_INIT_DUP;
-       struct remote *remote;
+       struct remote *remote = NULL;
        int result = 0;
        struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
 
        packet_trace_identity("fetch");
 
+       fetch_if_missing = 0;
+
        /* Record the command line for the reflog */
        strbuf_addstr(&default_rla, "fetch");
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
 
+       config_from_gitmodules(gitmodules_fetch_config, NULL);
        git_config(git_fetch_config, NULL);
 
        argc = parse_options(argc, argv, prefix,
@@ -1338,11 +1371,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        if (depth || deepen_since || deepen_not.nr)
                deepen = 1;
 
-       if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
-               set_config_fetch_recurse_submodules(recurse_submodules_default);
-               gitmodules_config();
-               git_config(submodule_config, NULL);
-       }
+       if (filter_options.choice && !repository_format_partial_clone)
+               die("--filter can only be used when extensions.partialClone is set");
 
        if (all) {
                if (argc == 1)
@@ -1350,17 +1380,14 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                else if (argc > 1)
                        die(_("fetch --all does not make sense with refspecs"));
                (void) for_each_remote(get_one_remote_for_fetch, &list);
-               result = fetch_multiple(&list);
        } else if (argc == 0) {
                /* No arguments -- use default remote */
                remote = remote_get(NULL);
-               result = fetch_one(remote, argc, argv);
        } else if (multiple) {
                /* All arguments are assumed to be remotes or groups */
                for (i = 0; i < argc; i++)
                        if (!add_remote_or_group(argv[i], &list))
                                die(_("No such remote or remote group: %s"), argv[i]);
-               result = fetch_multiple(&list);
        } else {
                /* Single remote or group */
                (void) add_remote_or_group(argv[0], &list);
@@ -1368,14 +1395,25 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                        /* More than one remote */
                        if (argc > 1)
                                die(_("Fetching a group and specifying refspecs does not make sense"));
-                       result = fetch_multiple(&list);
                } else {
                        /* Zero or one remotes */
                        remote = remote_get(argv[0]);
-                       result = fetch_one(remote, argc-1, argv+1);
+                       argc--;
+                       argv++;
                }
        }
 
+       if (remote) {
+               if (filter_options.choice &&
+                   strcmp(remote->name, repository_format_partial_clone))
+                       die(_("--filter can only be used with the remote configured in core.partialClone"));
+               result = fetch_one(remote, argc, argv);
+       } else {
+               if (filter_options.choice)
+                       die(_("--filter can only be used with the remote configured in core.partialClone"));
+               result = fetch_multiple(&list);
+       }
+
        if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
                struct argv_array options = ARGV_ARRAY_INIT;
 
@@ -1383,6 +1421,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                result = fetch_populated_submodules(&options,
                                                    submodule_prefix,
                                                    recurse_submodules,
+                                                   recurse_submodules_default,
                                                    verbosity < 0,
                                                    max_children);
                argv_array_clear(&options);