Merge branch 'cb/xdiff-no-system-includes-in-dot-c' into maint
[gitweb.git] / submodule-config.c
index 6b212bae31c31edb651a381cfb473d3de7ae7ca6..4264ee216f49773c86e2e161d28ceec656a1273c 100644 (file)
@@ -1,9 +1,11 @@
 #include "cache.h"
+#include "dir.h"
 #include "repository.h"
 #include "config.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "strbuf.h"
+#include "object-store.h"
 #include "parse-options.h"
 
 /*
@@ -44,7 +46,7 @@ static int config_path_cmp(const void *unused_cmp_data,
        const struct submodule_entry *b = entry_or_key;
 
        return strcmp(a->config->path, b->config->path) ||
-              oidcmp(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
+              !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
 }
 
 static int config_name_cmp(const void *unused_cmp_data,
@@ -56,7 +58,7 @@ static int config_name_cmp(const void *unused_cmp_data,
        const struct submodule_entry *b = entry_or_key;
 
        return strcmp(a->config->name, b->config->name) ||
-              oidcmp(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
+              !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
 }
 
 static struct submodule_cache *submodule_cache_alloc(void)
@@ -279,7 +281,10 @@ static int parse_fetch_recurse(const char *opt, const char *arg,
        default:
                if (!strcmp(arg, "on-demand"))
                        return RECURSE_SUBMODULES_ON_DEMAND;
-
+               /*
+                * Please update $__git_fetch_recurse_submodules in
+                * git-completion.bash when you add new options.
+                */
                if (die_on_error)
                        die("bad %s argument: %s", opt, arg);
                else
@@ -360,6 +365,10 @@ static int parse_push_recurse(const char *opt, const char *arg,
                        return RECURSE_SUBMODULES_CHECK;
                else if (!strcmp(arg, "only"))
                        return RECURSE_SUBMODULES_ONLY;
+               /*
+                * Please update $__git_push_recurse_submodules in
+                * git-completion.bash when you add new modes.
+                */
                else if (die_on_error)
                        die("bad %s argument: %s", opt, arg);
                else
@@ -571,7 +580,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
        parameter.gitmodules_oid = &oid;
        parameter.overwrite = 0;
        git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
-                       config, config_size, &parameter);
+                       config, config_size, &parameter, NULL);
        strbuf_release(&rev);
        free(config);
 
@@ -601,6 +610,43 @@ static void submodule_cache_check_init(struct repository *repo)
        submodule_cache_init(repo->submodule_cache);
 }
 
+/*
+ * Note: This function is private for a reason, the '.gitmodules' file should
+ * not be used as as a mechanism to retrieve arbitrary configuration stored in
+ * the repository.
+ *
+ * Runs the provided config function on the '.gitmodules' file found in the
+ * working directory.
+ */
+static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
+{
+       if (repo->worktree) {
+               struct git_config_source config_source = { 0 };
+               const struct config_options opts = { 0 };
+               struct object_id oid;
+               char *file;
+               char *oidstr = NULL;
+
+               file = repo_worktree_path(repo, GITMODULES_FILE);
+               if (file_exists(file)) {
+                       config_source.file = file;
+               } else if (repo_get_oid(repo, GITMODULES_INDEX, &oid) >= 0 ||
+                          repo_get_oid(repo, GITMODULES_HEAD, &oid) >= 0) {
+                       config_source.blob = oidstr = xstrdup(oid_to_hex(&oid));
+                       if (repo != the_repository)
+                               add_to_alternates_memory(repo->objects->odb->path);
+               } else {
+                       goto out;
+               }
+
+               config_with_options(fn, data, &config_source, &opts);
+
+out:
+               free(oidstr);
+               free(file);
+       }
+}
+
 static int gitmodules_cb(const char *var, const char *value, void *data)
 {
        struct repository *repo = data;
@@ -618,19 +664,11 @@ void repo_read_gitmodules(struct repository *repo)
 {
        submodule_cache_check_init(repo);
 
-       if (repo->worktree) {
-               char *gitmodules;
-
-               if (repo_read_index(repo) < 0)
-                       return;
-
-               gitmodules = repo_worktree_path(repo, GITMODULES_FILE);
-
-               if (!is_gitmodules_unmerged(repo->index))
-                       git_config_from_file(gitmodules_cb, gitmodules, repo);
+       if (repo_read_index(repo) < 0)
+               return;
 
-               free(gitmodules);
-       }
+       if (!is_gitmodules_unmerged(repo->index))
+               config_from_gitmodules(gitmodules_cb, repo, repo);
 
        repo->submodule_cache->gitmodules_read = 1;
 }
@@ -681,3 +719,82 @@ void submodule_free(struct repository *r)
        if (r->submodule_cache)
                submodule_cache_clear(r->submodule_cache);
 }
+
+static int config_print_callback(const char *var, const char *value, void *cb_data)
+{
+       char *wanted_key = cb_data;
+
+       if (!strcmp(wanted_key, var))
+               printf("%s\n", value);
+
+       return 0;
+}
+
+int print_config_from_gitmodules(struct repository *repo, const char *key)
+{
+       int ret;
+       char *store_key;
+
+       ret = git_config_parse_key(key, &store_key, NULL);
+       if (ret < 0)
+               return CONFIG_INVALID_KEY;
+
+       config_from_gitmodules(config_print_callback, repo, store_key);
+
+       free(store_key);
+       return 0;
+}
+
+int config_set_in_gitmodules_file_gently(const char *key, const char *value)
+{
+       int ret;
+
+       ret = git_config_set_in_file_gently(GITMODULES_FILE, key, value);
+       if (ret < 0)
+               /* Maybe the user already did that, don't error out here */
+               warning(_("Could not update .gitmodules entry %s"), key);
+
+       return ret;
+}
+
+struct fetch_config {
+       int *max_children;
+       int *recurse_submodules;
+};
+
+static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
+{
+       struct fetch_config *config = cb;
+       if (!strcmp(var, "submodule.fetchjobs")) {
+               *(config->max_children) = parse_submodule_fetchjobs(var, value);
+               return 0;
+       } else if (!strcmp(var, "fetch.recursesubmodules")) {
+               *(config->recurse_submodules) = parse_fetch_recurse_submodules_arg(var, value);
+               return 0;
+       }
+
+       return 0;
+}
+
+void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules)
+{
+       struct fetch_config config = {
+               .max_children = max_children,
+               .recurse_submodules = recurse_submodules
+       };
+       config_from_gitmodules(gitmodules_fetch_config, the_repository, &config);
+}
+
+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;
+}
+
+void update_clone_config_from_gitmodules(int *max_jobs)
+{
+       config_from_gitmodules(gitmodules_update_clone_config, the_repository, &max_jobs);
+}