Merge branch 'rs/use-strbuf-addbuf' into maint
[gitweb.git] / submodule.c
index 62c4356c50d4a41381336559f4e9af27e520ad0d..4532b11d66f8cdc0abdf003b3a16a632bd923890 100644 (file)
 #include "argv-array.h"
 #include "blob.h"
 #include "thread-utils.h"
+#include "quote.h"
 
 static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
+static int parallel_jobs = 1;
 static struct string_list changed_submodule_paths;
 static int initialized_fetch_ref_tips;
 static struct sha1_array ref_tips_before_fetch;
@@ -169,7 +171,12 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 
 int submodule_config(const char *var, const char *value, void *cb)
 {
-       if (starts_with(var, "submodule."))
+       if (!strcmp(var, "submodule.fetchjobs")) {
+               parallel_jobs = git_config_int(var, value);
+               if (parallel_jobs < 0)
+                       die(_("negative values not allowed for submodule.fetchJobs"));
+               return 0;
+       } else if (starts_with(var, "submodule."))
                return parse_submodule_config_option(var, value);
        else if (!strcmp(var, "fetch.recursesubmodules")) {
                config_fetch_recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
@@ -210,6 +217,48 @@ void gitmodules_config(void)
        }
 }
 
+int parse_submodule_update_strategy(const char *value,
+               struct submodule_update_strategy *dst)
+{
+       free((void*)dst->command);
+       dst->command = NULL;
+       if (!strcmp(value, "none"))
+               dst->type = SM_UPDATE_NONE;
+       else if (!strcmp(value, "checkout"))
+               dst->type = SM_UPDATE_CHECKOUT;
+       else if (!strcmp(value, "rebase"))
+               dst->type = SM_UPDATE_REBASE;
+       else if (!strcmp(value, "merge"))
+               dst->type = SM_UPDATE_MERGE;
+       else if (skip_prefix(value, "!", &value)) {
+               dst->type = SM_UPDATE_COMMAND;
+               dst->command = xstrdup(value);
+       } else
+               return -1;
+       return 0;
+}
+
+const char *submodule_strategy_to_string(const struct submodule_update_strategy *s)
+{
+       struct strbuf sb = STRBUF_INIT;
+       switch (s->type) {
+       case SM_UPDATE_CHECKOUT:
+               return "checkout";
+       case SM_UPDATE_MERGE:
+               return "merge";
+       case SM_UPDATE_REBASE:
+               return "rebase";
+       case SM_UPDATE_NONE:
+               return "none";
+       case SM_UPDATE_UNSPECIFIED:
+               return NULL;
+       case SM_UPDATE_COMMAND:
+               strbuf_addf(&sb, "!%s", s->command);
+               return strbuf_detach(&sb, NULL);
+       }
+       return NULL;
+}
+
 void handle_ignore_submodules_arg(struct diff_options *diffopt,
                                  const char *arg)
 {
@@ -366,7 +415,7 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20
 
                argv[1] = sha1_to_hex(sha1);
                cp.argv = argv;
-               cp.env = local_repo_env;
+               prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
                cp.no_stdin = 1;
                cp.out = -1;
@@ -453,7 +502,7 @@ static int push_submodule(const char *path)
                const char *argv[] = {"push", NULL};
 
                cp.argv = argv;
-               cp.env = local_repo_env;
+               prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
                cp.no_stdin = 1;
                cp.dir = path;
@@ -499,7 +548,7 @@ static int is_submodule_commit_present(const char *path, unsigned char sha1[20])
 
                argv[3] = sha1_to_hex(sha1);
                cp.argv = argv;
-               cp.env = local_repo_env;
+               prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
                cp.no_stdin = 1;
                cp.dir = path;
@@ -682,7 +731,7 @@ static int get_next_submodule(struct child_process *cp,
                if (is_directory(git_dir)) {
                        child_process_init(cp);
                        cp->dir = strbuf_detach(&submodule_path, NULL);
-                       cp->env = local_repo_env;
+                       prepare_submodule_repo_env(&cp->env_array);
                        cp->git_cmd = 1;
                        if (!spf->quiet)
                                strbuf_addf(err, "Fetching submodule %s%s\n",
@@ -750,6 +799,9 @@ int fetch_populated_submodules(const struct argv_array *options,
        argv_array_push(&spf.args, "--recurse-submodules-default");
        /* default value, "--submodule-prefix" and its value are added later */
 
+       if (max_parallel_jobs < 0)
+               max_parallel_jobs = parallel_jobs;
+
        calculate_changed_submodule_paths();
        run_processes_parallel(max_parallel_jobs,
                               get_next_submodule,
@@ -794,7 +846,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
                argv[2] = "-uno";
 
        cp.argv = argv;
-       cp.env = local_repo_env;
+       prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
        cp.no_stdin = 1;
        cp.out = -1;
@@ -855,7 +907,7 @@ int submodule_uses_gitfile(const char *path)
 
        /* Now test that all nested submodules use a gitfile too */
        cp.argv = argv;
-       cp.env = local_repo_env;
+       prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
        cp.no_stdin = 1;
        cp.no_stderr = 1;
@@ -888,7 +940,7 @@ int ok_to_remove_submodule(const char *path)
                return 0;
 
        cp.argv = argv;
-       cp.env = local_repo_env;
+       prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
        cp.no_stdin = 1;
        cp.out = -1;
@@ -1094,3 +1146,18 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)
        strbuf_release(&rel_path);
        free((void *)real_work_tree);
 }
+
+int parallel_submodules(void)
+{
+       return parallel_jobs;
+}
+
+void prepare_submodule_repo_env(struct argv_array *out)
+{
+       const char * const *var;
+
+       for (var = local_repo_env; *var; var++) {
+               if (strcmp(*var, CONFIG_DATA_ENVIRONMENT))
+                       argv_array_push(out, *var);
+       }
+}