Sync with Git 2.14.4
[gitweb.git] / builtin / submodule--helper.c
index 895555c93a3bb86ad5511a2ded2350614732d618..30e0bb876cffa1884267f616e0c31cb605f67019 100644 (file)
@@ -17,9 +17,8 @@
 static char *get_default_remote(void)
 {
        char *dest = NULL, *ret;
-       unsigned char sha1[20];
        struct strbuf sb = STRBUF_INIT;
-       const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+       const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 
        if (!refname)
                die(_("No such ref: %s"), "HEAD");
@@ -275,8 +274,6 @@ static void module_list_active(struct module_list *list)
        int i;
        struct module_list active_modules = MODULE_LIST_INIT;
 
-       gitmodules_config();
-
        for (i = 0; i < list->nr; i++) {
                const struct cache_entry *ce = list->entries[i];
 
@@ -337,9 +334,6 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
        struct strbuf sb = STRBUF_INIT;
        char *upd = NULL, *url = NULL, *displaypath;
 
-       /* Only loads from .gitmodules, no overlay with .git/config */
-       gitmodules_config();
-
        if (prefix && get_super_prefix())
                die("BUG: cannot have prefix and superprefix");
        else if (prefix)
@@ -350,7 +344,7 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
        } else
                displaypath = xstrdup(path);
 
-       sub = submodule_from_path(null_sha1, path);
+       sub = submodule_from_path(&null_oid, path);
 
        if (!sub)
                die(_("No url found for submodule path '%s' in .gitmodules"),
@@ -475,8 +469,7 @@ static int module_name(int argc, const char **argv, const char *prefix)
        if (argc != 2)
                usage(_("git submodule--helper name <path>"));
 
-       gitmodules_config();
-       sub = submodule_from_path(null_sha1, argv[1]);
+       sub = submodule_from_path(&null_oid, argv[1]);
 
        if (!sub)
                die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@ -510,6 +503,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
        if (gitdir && *gitdir)
                argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
 
+       argv_array_push(&cp.args, "--");
        argv_array_push(&cp.args, url);
        argv_array_push(&cp.args, path);
 
@@ -780,6 +774,10 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                                           struct strbuf *out)
 {
        const struct submodule *sub = NULL;
+       const char *url = NULL;
+       const char *update_string;
+       enum submodule_update_type update_type;
+       char *key;
        struct strbuf displaypath_sb = STRBUF_INIT;
        struct strbuf sb = STRBUF_INIT;
        const char *displaypath = NULL;
@@ -795,7 +793,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                goto cleanup;
        }
 
-       sub = submodule_from_path(null_sha1, ce->name);
+       sub = submodule_from_path(&null_oid, ce->name);
 
        if (suc->recursive_prefix)
                displaypath = relative_path(suc->recursive_prefix,
@@ -808,9 +806,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                goto cleanup;
        }
 
+       key = xstrfmt("submodule.%s.update", sub->name);
+       if (!repo_config_get_string_const(the_repository, key, &update_string)) {
+               update_type = parse_submodule_update_type(update_string);
+       } else {
+               update_type = sub->update_strategy.type;
+       }
+       free(key);
+
        if (suc->update.type == SM_UPDATE_NONE
            || (suc->update.type == SM_UPDATE_UNSPECIFIED
-               && sub->update_strategy.type == SM_UPDATE_NONE)) {
+               && update_type == SM_UPDATE_NONE)) {
                strbuf_addf(out, _("Skipping submodule '%s'"), displaypath);
                strbuf_addch(out, '\n');
                goto cleanup;
@@ -822,6 +828,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                goto cleanup;
        }
 
+       strbuf_reset(&sb);
+       strbuf_addf(&sb, "submodule.%s.url", sub->name);
+       if (repo_config_get_string_const(the_repository, sb.buf, &url))
+               url = sub->url;
+
        strbuf_reset(&sb);
        strbuf_addf(&sb, "%s/.git", ce->name);
        needs_cloning = !file_exists(sb.buf);
@@ -851,7 +862,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                argv_array_push(&child->args, "--depth=1");
        argv_array_pushl(&child->args, "--path", sub->path, NULL);
        argv_array_pushl(&child->args, "--name", sub->name, NULL);
-       argv_array_pushl(&child->args, "--url", sub->url, NULL);
+       argv_array_pushl(&child->args, "--url", url, NULL);
        if (suc->references.nr) {
                struct string_list_item *item;
                for_each_string_list_item(item, &suc->references)
@@ -960,10 +971,19 @@ static int update_clone_task_finished(int result,
        return 0;
 }
 
+static int gitmodules_update_clone_config(const char *var, const char *value,
+                                         void *cb)
+{
+       int *max_jobs = cb;
+       if (!strcmp(var, "submodule.fetchjobs"))
+               *max_jobs = parse_submodule_fetchjobs(var, value);
+       return 0;
+}
+
 static int update_clone(int argc, const char **argv, const char *prefix)
 {
        const char *update = NULL;
-       int max_jobs = -1;
+       int max_jobs = 1;
        struct string_list_item *item;
        struct pathspec pathspec;
        struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
@@ -1000,6 +1020,9 @@ static int update_clone(int argc, const char **argv, const char *prefix)
        };
        suc.prefix = prefix;
 
+       config_from_gitmodules(gitmodules_update_clone_config, &max_jobs);
+       git_config(gitmodules_update_clone_config, &max_jobs);
+
        argc = parse_options(argc, argv, prefix, module_update_clone_options,
                             git_submodule_helper_usage, 0);
 
@@ -1013,13 +1036,6 @@ static int update_clone(int argc, const char **argv, const char *prefix)
        if (pathspec.nr)
                suc.warn_if_uninitialized = 1;
 
-       /* Overlay the parsed .gitmodules file with .git/config */
-       gitmodules_config();
-       git_config(submodule_config, NULL);
-
-       if (max_jobs < 0)
-               max_jobs = parallel_submodules();
-
        run_processes_parallel(max_jobs,
                               update_clone_get_next_task,
                               update_clone_start_failure,
@@ -1057,19 +1073,23 @@ static int resolve_relative_path(int argc, const char **argv, const char *prefix
 static const char *remote_submodule_branch(const char *path)
 {
        const struct submodule *sub;
-       gitmodules_config();
-       git_config(submodule_config, NULL);
+       const char *branch = NULL;
+       char *key;
 
-       sub = submodule_from_path(null_sha1, path);
+       sub = submodule_from_path(&null_oid, path);
        if (!sub)
                return NULL;
 
-       if (!sub->branch)
+       key = xstrfmt("submodule.%s.branch", sub->name);
+       if (repo_config_get_string_const(the_repository, key, &branch))
+               branch = sub->branch;
+       free(key);
+
+       if (!branch)
                return "master";
 
-       if (!strcmp(sub->branch, ".")) {
-               unsigned char sha1[20];
-               const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+       if (!strcmp(branch, ".")) {
+               const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 
                if (!refname)
                        die(_("No such ref: %s"), "HEAD");
@@ -1085,7 +1105,7 @@ static const char *remote_submodule_branch(const char *path)
                return refname;
        }
 
-       return sub->branch;
+       return branch;
 }
 
 static int resolve_remote_submodule_branch(int argc, const char **argv,
@@ -1168,6 +1188,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
                                                break;
                                        die("HEAD does not match the named branch in the superproject");
                                }
+                               /* fallthrough */
                        default:
                                die("src refspec '%s' must name a ref",
                                    rs->src);
@@ -1204,9 +1225,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, embed_gitdir_options,
                             git_submodule_helper_usage, 0);
 
-       gitmodules_config();
-       git_config(submodule_config, NULL);
-
        if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
                return 1;
 
@@ -1222,11 +1240,32 @@ static int is_active(int argc, const char **argv, const char *prefix)
        if (argc != 2)
                die("submodule--helper is-active takes exactly 1 argument");
 
-       gitmodules_config();
-
        return !is_submodule_active(the_repository, argv[1]);
 }
 
+/*
+ * Exit non-zero if any of the submodule names given on the command line is
+ * invalid. If no names are given, filter stdin to print only valid names
+ * (which is primarily intended for testing).
+ */
+static int check_name(int argc, const char **argv, const char *prefix)
+{
+       if (argc > 1) {
+               while (*++argv) {
+                       if (check_submodule_name(*argv) < 0)
+                               return 1;
+               }
+       } else {
+               struct strbuf buf = STRBUF_INIT;
+               while (strbuf_getline(&buf, stdin) != EOF) {
+                       if (!check_submodule_name(buf.buf))
+                               printf("%s\n", buf.buf);
+               }
+               strbuf_release(&buf);
+       }
+       return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -1248,6 +1287,7 @@ static struct cmd_struct commands[] = {
        {"push-check", push_check, 0},
        {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
        {"is-active", is_active, 0},
+       {"check-name", check_name, 0},
 };
 
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)