Merge branch 'rs/userformat-find-requirements-simplify'
[git/gitster.git] / submodule-config.c
blobb6908e295f4292d7f1991a11f7d4a33b8545427a
1 #include "git-compat-util.h"
2 #include "alloc.h"
3 #include "dir.h"
4 #include "environment.h"
5 #include "gettext.h"
6 #include "hex.h"
7 #include "path.h"
8 #include "repository.h"
9 #include "config.h"
10 #include "submodule-config.h"
11 #include "submodule.h"
12 #include "strbuf.h"
13 #include "object-name.h"
14 #include "object-store-ll.h"
15 #include "parse-options.h"
16 #include "thread-utils.h"
17 #include "tree-walk.h"
20 * submodule cache lookup structure
21 * There is one shared set of 'struct submodule' entries which can be
22 * looked up by their sha1 blob id of the .gitmodules file and either
23 * using path or name as key.
24 * for_path stores submodule entries with path as key
25 * for_name stores submodule entries with name as key
27 struct submodule_cache {
28 struct hashmap for_path;
29 struct hashmap for_name;
30 unsigned initialized:1;
31 unsigned gitmodules_read:1;
35 * thin wrapper struct needed to insert 'struct submodule' entries to
36 * the hashmap
38 struct submodule_entry {
39 struct hashmap_entry ent;
40 struct submodule *config;
43 enum lookup_type {
44 lookup_name,
45 lookup_path
48 static int config_path_cmp(const void *cmp_data UNUSED,
49 const struct hashmap_entry *eptr,
50 const struct hashmap_entry *entry_or_key,
51 const void *keydata UNUSED)
53 const struct submodule_entry *a, *b;
55 a = container_of(eptr, const struct submodule_entry, ent);
56 b = container_of(entry_or_key, const struct submodule_entry, ent);
58 return strcmp(a->config->path, b->config->path) ||
59 !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
62 static int config_name_cmp(const void *cmp_data UNUSED,
63 const struct hashmap_entry *eptr,
64 const struct hashmap_entry *entry_or_key,
65 const void *keydata UNUSED)
67 const struct submodule_entry *a, *b;
69 a = container_of(eptr, const struct submodule_entry, ent);
70 b = container_of(entry_or_key, const struct submodule_entry, ent);
72 return strcmp(a->config->name, b->config->name) ||
73 !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
76 static struct submodule_cache *submodule_cache_alloc(void)
78 return xcalloc(1, sizeof(struct submodule_cache));
81 static void submodule_cache_init(struct submodule_cache *cache)
83 hashmap_init(&cache->for_path, config_path_cmp, NULL, 0);
84 hashmap_init(&cache->for_name, config_name_cmp, NULL, 0);
85 cache->initialized = 1;
88 static void free_one_config(struct submodule_entry *entry)
90 free((void *) entry->config->path);
91 free((void *) entry->config->name);
92 free((void *) entry->config->branch);
93 free((void *) entry->config->update_strategy.command);
94 free(entry->config);
97 static void submodule_cache_clear(struct submodule_cache *cache)
99 struct hashmap_iter iter;
100 struct submodule_entry *entry;
102 if (!cache->initialized)
103 return;
106 * We iterate over the name hash here to be symmetric with the
107 * allocation of struct submodule entries. Each is allocated by
108 * their .gitmodules blob sha1 and submodule name.
110 hashmap_for_each_entry(&cache->for_name, &iter, entry,
111 ent /* member name */)
112 free_one_config(entry);
114 hashmap_clear_and_free(&cache->for_path, struct submodule_entry, ent);
115 hashmap_clear_and_free(&cache->for_name, struct submodule_entry, ent);
116 cache->initialized = 0;
117 cache->gitmodules_read = 0;
120 void submodule_cache_free(struct submodule_cache *cache)
122 submodule_cache_clear(cache);
123 free(cache);
126 static unsigned int hash_oid_string(const struct object_id *oid,
127 const char *string)
129 return memhash(oid->hash, the_hash_algo->rawsz) + strhash(string);
132 static void cache_put_path(struct submodule_cache *cache,
133 struct submodule *submodule)
135 unsigned int hash = hash_oid_string(&submodule->gitmodules_oid,
136 submodule->path);
137 struct submodule_entry *e = xmalloc(sizeof(*e));
138 hashmap_entry_init(&e->ent, hash);
139 e->config = submodule;
140 hashmap_put(&cache->for_path, &e->ent);
143 static void cache_remove_path(struct submodule_cache *cache,
144 struct submodule *submodule)
146 unsigned int hash = hash_oid_string(&submodule->gitmodules_oid,
147 submodule->path);
148 struct submodule_entry e;
149 struct submodule_entry *removed;
150 hashmap_entry_init(&e.ent, hash);
151 e.config = submodule;
152 removed = hashmap_remove_entry(&cache->for_path, &e, ent, NULL);
153 free(removed);
156 static void cache_add(struct submodule_cache *cache,
157 struct submodule *submodule)
159 unsigned int hash = hash_oid_string(&submodule->gitmodules_oid,
160 submodule->name);
161 struct submodule_entry *e = xmalloc(sizeof(*e));
162 hashmap_entry_init(&e->ent, hash);
163 e->config = submodule;
164 hashmap_add(&cache->for_name, &e->ent);
167 static const struct submodule *cache_lookup_path(struct submodule_cache *cache,
168 const struct object_id *gitmodules_oid, const char *path)
170 struct submodule_entry *entry;
171 unsigned int hash = hash_oid_string(gitmodules_oid, path);
172 struct submodule_entry key;
173 struct submodule key_config;
175 oidcpy(&key_config.gitmodules_oid, gitmodules_oid);
176 key_config.path = path;
178 hashmap_entry_init(&key.ent, hash);
179 key.config = &key_config;
181 entry = hashmap_get_entry(&cache->for_path, &key, ent, NULL);
182 if (entry)
183 return entry->config;
184 return NULL;
187 static struct submodule *cache_lookup_name(struct submodule_cache *cache,
188 const struct object_id *gitmodules_oid, const char *name)
190 struct submodule_entry *entry;
191 unsigned int hash = hash_oid_string(gitmodules_oid, name);
192 struct submodule_entry key;
193 struct submodule key_config;
195 oidcpy(&key_config.gitmodules_oid, gitmodules_oid);
196 key_config.name = name;
198 hashmap_entry_init(&key.ent, hash);
199 key.config = &key_config;
201 entry = hashmap_get_entry(&cache->for_name, &key, ent, NULL);
202 if (entry)
203 return entry->config;
204 return NULL;
207 int check_submodule_name(const char *name)
209 /* Disallow empty names */
210 if (!*name)
211 return -1;
214 * Look for '..' as a path component. Check is_xplatform_dir_sep() as
215 * separators rather than is_dir_sep(), because we want the name rules
216 * to be consistent across platforms.
218 goto in_component; /* always start inside component */
219 while (*name) {
220 char c = *name++;
221 if (is_xplatform_dir_sep(c)) {
222 in_component:
223 if (name[0] == '.' && name[1] == '.' &&
224 (!name[2] || is_xplatform_dir_sep(name[2])))
225 return -1;
229 return 0;
232 static int name_and_item_from_var(const char *var, struct strbuf *name,
233 struct strbuf *item)
235 const char *subsection, *key;
236 size_t subsection_len;
237 int parse;
238 parse = parse_config_key(var, "submodule", &subsection,
239 &subsection_len, &key);
240 if (parse < 0 || !subsection)
241 return 0;
243 strbuf_add(name, subsection, subsection_len);
244 if (check_submodule_name(name->buf) < 0) {
245 warning(_("ignoring suspicious submodule name: %s"), name->buf);
246 strbuf_release(name);
247 return 0;
250 strbuf_addstr(item, key);
252 return 1;
255 static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
256 const struct object_id *gitmodules_oid, const char *name)
258 struct submodule *submodule;
259 struct strbuf name_buf = STRBUF_INIT;
261 submodule = cache_lookup_name(cache, gitmodules_oid, name);
262 if (submodule)
263 return submodule;
265 submodule = xmalloc(sizeof(*submodule));
267 strbuf_addstr(&name_buf, name);
268 submodule->name = strbuf_detach(&name_buf, NULL);
270 submodule->path = NULL;
271 submodule->url = NULL;
272 submodule->update_strategy.type = SM_UPDATE_UNSPECIFIED;
273 submodule->update_strategy.command = NULL;
274 submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
275 submodule->ignore = NULL;
276 submodule->branch = NULL;
277 submodule->recommend_shallow = -1;
279 oidcpy(&submodule->gitmodules_oid, gitmodules_oid);
281 cache_add(cache, submodule);
283 return submodule;
286 static int parse_fetch_recurse(const char *opt, const char *arg,
287 int die_on_error)
289 switch (git_parse_maybe_bool(arg)) {
290 case 1:
291 return RECURSE_SUBMODULES_ON;
292 case 0:
293 return RECURSE_SUBMODULES_OFF;
294 default:
295 if (!strcmp(arg, "on-demand"))
296 return RECURSE_SUBMODULES_ON_DEMAND;
298 * Please update $__git_fetch_recurse_submodules in
299 * git-completion.bash when you add new options.
301 if (die_on_error)
302 die("bad %s argument: %s", opt, arg);
303 else
304 return RECURSE_SUBMODULES_ERROR;
308 int parse_submodule_fetchjobs(const char *var, const char *value,
309 const struct key_value_info *kvi)
311 int fetchjobs = git_config_int(var, value, kvi);
312 if (fetchjobs < 0)
313 die(_("negative values not allowed for submodule.fetchJobs"));
314 if (!fetchjobs)
315 fetchjobs = online_cpus();
316 return fetchjobs;
319 int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
321 return parse_fetch_recurse(opt, arg, 1);
324 int option_fetch_parse_recurse_submodules(const struct option *opt,
325 const char *arg, int unset)
327 int *v;
329 if (!opt->value)
330 return -1;
332 v = opt->value;
334 if (unset) {
335 *v = RECURSE_SUBMODULES_OFF;
336 } else {
337 if (arg)
338 *v = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
339 else
340 *v = RECURSE_SUBMODULES_ON;
342 return 0;
345 static int parse_update_recurse(const char *opt, const char *arg,
346 int die_on_error)
348 switch (git_parse_maybe_bool(arg)) {
349 case 1:
350 return RECURSE_SUBMODULES_ON;
351 case 0:
352 return RECURSE_SUBMODULES_OFF;
353 default:
354 if (die_on_error)
355 die("bad %s argument: %s", opt, arg);
356 return RECURSE_SUBMODULES_ERROR;
360 int parse_update_recurse_submodules_arg(const char *opt, const char *arg)
362 return parse_update_recurse(opt, arg, 1);
365 static int parse_push_recurse(const char *opt, const char *arg,
366 int die_on_error)
368 switch (git_parse_maybe_bool(arg)) {
369 case 1:
370 /* There's no simple "on" value when pushing */
371 if (die_on_error)
372 die("bad %s argument: %s", opt, arg);
373 else
374 return RECURSE_SUBMODULES_ERROR;
375 case 0:
376 return RECURSE_SUBMODULES_OFF;
377 default:
378 if (!strcmp(arg, "on-demand"))
379 return RECURSE_SUBMODULES_ON_DEMAND;
380 else if (!strcmp(arg, "check"))
381 return RECURSE_SUBMODULES_CHECK;
382 else if (!strcmp(arg, "only"))
383 return RECURSE_SUBMODULES_ONLY;
385 * Please update $__git_push_recurse_submodules in
386 * git-completion.bash when you add new modes.
388 else if (die_on_error)
389 die("bad %s argument: %s", opt, arg);
390 else
391 return RECURSE_SUBMODULES_ERROR;
395 int parse_push_recurse_submodules_arg(const char *opt, const char *arg)
397 return parse_push_recurse(opt, arg, 1);
400 static void warn_multiple_config(const struct object_id *treeish_name,
401 const char *name, const char *option)
403 const char *commit_string = "WORKTREE";
404 if (treeish_name)
405 commit_string = oid_to_hex(treeish_name);
406 warning("%s:.gitmodules, multiple configurations found for "
407 "'submodule.%s.%s'. Skipping second one!",
408 commit_string, name, option);
411 static void warn_command_line_option(const char *var, const char *value)
413 warning(_("ignoring '%s' which may be interpreted as"
414 " a command-line option: %s"), var, value);
417 struct parse_config_parameter {
418 struct submodule_cache *cache;
419 const struct object_id *treeish_name;
420 const struct object_id *gitmodules_oid;
421 int overwrite;
425 * Parse a config item from .gitmodules.
427 * This does not handle submodule-related configuration from the main
428 * config store (.git/config, etc). Callers are responsible for
429 * checking for overrides in the main config store when appropriate.
431 static int parse_config(const char *var, const char *value,
432 const struct config_context *ctx UNUSED, void *data)
434 struct parse_config_parameter *me = data;
435 struct submodule *submodule;
436 struct strbuf name = STRBUF_INIT, item = STRBUF_INIT;
437 int ret = 0;
439 /* this also ensures that we only parse submodule entries */
440 if (!name_and_item_from_var(var, &name, &item))
441 return 0;
443 submodule = lookup_or_create_by_name(me->cache,
444 me->gitmodules_oid,
445 name.buf);
447 if (!strcmp(item.buf, "path")) {
448 if (!value)
449 ret = config_error_nonbool(var);
450 else if (looks_like_command_line_option(value))
451 warn_command_line_option(var, value);
452 else if (!me->overwrite && submodule->path)
453 warn_multiple_config(me->treeish_name, submodule->name,
454 "path");
455 else {
456 if (submodule->path)
457 cache_remove_path(me->cache, submodule);
458 free((void *) submodule->path);
459 submodule->path = xstrdup(value);
460 cache_put_path(me->cache, submodule);
462 } else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
463 /* when parsing worktree configurations we can die early */
464 int die_on_error = is_null_oid(me->gitmodules_oid);
465 if (!me->overwrite &&
466 submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
467 warn_multiple_config(me->treeish_name, submodule->name,
468 "fetchrecursesubmodules");
469 else
470 submodule->fetch_recurse = parse_fetch_recurse(
471 var, value,
472 die_on_error);
473 } else if (!strcmp(item.buf, "ignore")) {
474 if (!value)
475 ret = config_error_nonbool(var);
476 else if (!me->overwrite && submodule->ignore)
477 warn_multiple_config(me->treeish_name, submodule->name,
478 "ignore");
479 else if (strcmp(value, "untracked") &&
480 strcmp(value, "dirty") &&
481 strcmp(value, "all") &&
482 strcmp(value, "none"))
483 warning("Invalid parameter '%s' for config option "
484 "'submodule.%s.ignore'", value, name.buf);
485 else {
486 free((void *) submodule->ignore);
487 submodule->ignore = xstrdup(value);
489 } else if (!strcmp(item.buf, "url")) {
490 if (!value) {
491 ret = config_error_nonbool(var);
492 } else if (looks_like_command_line_option(value)) {
493 warn_command_line_option(var, value);
494 } else if (!me->overwrite && submodule->url) {
495 warn_multiple_config(me->treeish_name, submodule->name,
496 "url");
497 } else {
498 free((void *) submodule->url);
499 submodule->url = xstrdup(value);
501 } else if (!strcmp(item.buf, "update")) {
502 if (!value)
503 ret = config_error_nonbool(var);
504 else if (!me->overwrite &&
505 submodule->update_strategy.type != SM_UPDATE_UNSPECIFIED)
506 warn_multiple_config(me->treeish_name, submodule->name,
507 "update");
508 else if (parse_submodule_update_strategy(value,
509 &submodule->update_strategy) < 0 ||
510 submodule->update_strategy.type == SM_UPDATE_COMMAND)
511 die(_("invalid value for '%s'"), var);
512 } else if (!strcmp(item.buf, "shallow")) {
513 if (!me->overwrite && submodule->recommend_shallow != -1)
514 warn_multiple_config(me->treeish_name, submodule->name,
515 "shallow");
516 else
517 submodule->recommend_shallow =
518 git_config_bool(var, value);
519 } else if (!strcmp(item.buf, "branch")) {
520 if (!me->overwrite && submodule->branch)
521 warn_multiple_config(me->treeish_name, submodule->name,
522 "branch");
523 else {
524 free((void *)submodule->branch);
525 submodule->branch = xstrdup(value);
529 strbuf_release(&name);
530 strbuf_release(&item);
532 return ret;
535 static int gitmodule_oid_from_commit(const struct object_id *treeish_name,
536 struct object_id *gitmodules_oid,
537 struct strbuf *rev)
539 int ret = 0;
541 if (is_null_oid(treeish_name)) {
542 oidclr(gitmodules_oid);
543 return 1;
546 strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
547 if (repo_get_oid(the_repository, rev->buf, gitmodules_oid) >= 0)
548 ret = 1;
550 return ret;
553 /* This does a lookup of a submodule configuration by name or by path
554 * (key) with on-demand reading of the appropriate .gitmodules from
555 * revisions.
557 static const struct submodule *config_from(struct submodule_cache *cache,
558 const struct object_id *treeish_name, const char *key,
559 enum lookup_type lookup_type)
561 struct strbuf rev = STRBUF_INIT;
562 unsigned long config_size;
563 char *config = NULL;
564 struct object_id oid;
565 enum object_type type;
566 const struct submodule *submodule = NULL;
567 struct parse_config_parameter parameter;
570 * If any parameter except the cache is a NULL pointer just
571 * return the first submodule. Can be used to check whether
572 * there are any submodules parsed.
574 if (!treeish_name || !key) {
575 struct hashmap_iter iter;
576 struct submodule_entry *entry;
578 entry = hashmap_iter_first_entry(&cache->for_name, &iter,
579 struct submodule_entry,
580 ent /* member name */);
581 if (!entry)
582 return NULL;
583 return entry->config;
586 if (!gitmodule_oid_from_commit(treeish_name, &oid, &rev))
587 goto out;
589 switch (lookup_type) {
590 case lookup_name:
591 submodule = cache_lookup_name(cache, &oid, key);
592 break;
593 case lookup_path:
594 submodule = cache_lookup_path(cache, &oid, key);
595 break;
597 if (submodule)
598 goto out;
600 config = repo_read_object_file(the_repository, &oid, &type,
601 &config_size);
602 if (!config || type != OBJ_BLOB)
603 goto out;
605 /* fill the submodule config into the cache */
606 parameter.cache = cache;
607 parameter.treeish_name = treeish_name;
608 parameter.gitmodules_oid = &oid;
609 parameter.overwrite = 0;
610 git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
611 config, config_size, &parameter, CONFIG_SCOPE_UNKNOWN, NULL);
612 strbuf_release(&rev);
613 free(config);
615 switch (lookup_type) {
616 case lookup_name:
617 return cache_lookup_name(cache, &oid, key);
618 case lookup_path:
619 return cache_lookup_path(cache, &oid, key);
620 default:
621 return NULL;
624 out:
625 strbuf_release(&rev);
626 free(config);
627 return submodule;
630 static void submodule_cache_check_init(struct repository *repo)
632 if (repo->submodule_cache && repo->submodule_cache->initialized)
633 return;
635 if (!repo->submodule_cache)
636 repo->submodule_cache = submodule_cache_alloc();
638 submodule_cache_init(repo->submodule_cache);
642 * Note: This function is private for a reason, the '.gitmodules' file should
643 * not be used as a mechanism to retrieve arbitrary configuration stored in
644 * the repository.
646 * Runs the provided config function on the '.gitmodules' file found in the
647 * working directory.
649 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
651 if (repo->worktree) {
652 struct git_config_source config_source = {
653 0, .scope = CONFIG_SCOPE_SUBMODULE
655 const struct config_options opts = { 0 };
656 struct object_id oid;
657 char *file;
658 char *oidstr = NULL;
660 file = repo_worktree_path(repo, GITMODULES_FILE);
661 if (file_exists(file)) {
662 config_source.file = file;
663 } else if (repo_get_oid(repo, GITMODULES_INDEX, &oid) >= 0 ||
664 repo_get_oid(repo, GITMODULES_HEAD, &oid) >= 0) {
665 config_source.blob = oidstr = xstrdup(oid_to_hex(&oid));
666 if (repo != the_repository)
667 add_submodule_odb_by_path(repo->objects->odb->path);
668 } else {
669 goto out;
672 config_with_options(fn, data, &config_source, repo, &opts);
674 out:
675 free(oidstr);
676 free(file);
680 static int gitmodules_cb(const char *var, const char *value,
681 const struct config_context *ctx, void *data)
683 struct repository *repo = data;
684 struct parse_config_parameter parameter;
686 parameter.cache = repo->submodule_cache;
687 parameter.treeish_name = NULL;
688 parameter.gitmodules_oid = null_oid();
689 parameter.overwrite = 1;
691 return parse_config(var, value, ctx, &parameter);
694 void repo_read_gitmodules(struct repository *repo, int skip_if_read)
696 submodule_cache_check_init(repo);
698 if (repo->submodule_cache->gitmodules_read && skip_if_read)
699 return;
701 if (repo_read_index(repo) < 0)
702 return;
704 if (!is_gitmodules_unmerged(repo->index))
705 config_from_gitmodules(gitmodules_cb, repo, repo);
707 repo->submodule_cache->gitmodules_read = 1;
710 void gitmodules_config_oid(const struct object_id *commit_oid)
712 struct strbuf rev = STRBUF_INIT;
713 struct object_id oid;
715 submodule_cache_check_init(the_repository);
717 if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
718 git_config_from_blob_oid(gitmodules_cb, rev.buf,
719 the_repository, &oid, the_repository,
720 CONFIG_SCOPE_UNKNOWN);
722 strbuf_release(&rev);
724 the_repository->submodule_cache->gitmodules_read = 1;
727 const struct submodule *submodule_from_name(struct repository *r,
728 const struct object_id *treeish_name,
729 const char *name)
731 repo_read_gitmodules(r, 1);
732 return config_from(r->submodule_cache, treeish_name, name, lookup_name);
735 const struct submodule *submodule_from_path(struct repository *r,
736 const struct object_id *treeish_name,
737 const char *path)
739 repo_read_gitmodules(r, 1);
740 return config_from(r->submodule_cache, treeish_name, path, lookup_path);
744 * Used internally by submodules_of_tree(). Recurses into 'treeish_name'
745 * and appends submodule entries to 'out'. The submodule_cache expects
746 * a root-level treeish_name and paths, so keep track of these values
747 * with 'root_tree' and 'prefix'.
749 static void traverse_tree_submodules(struct repository *r,
750 const struct object_id *root_tree,
751 char *prefix,
752 const struct object_id *treeish_name,
753 struct submodule_entry_list *out)
755 struct tree_desc tree;
756 struct submodule_tree_entry *st_entry;
757 struct name_entry *name_entry;
758 char *tree_path = NULL;
760 name_entry = xmalloc(sizeof(*name_entry));
762 fill_tree_descriptor(r, &tree, treeish_name);
763 while (tree_entry(&tree, name_entry)) {
764 if (prefix)
765 tree_path =
766 mkpathdup("%s/%s", prefix, name_entry->path);
767 else
768 tree_path = xstrdup(name_entry->path);
770 if (S_ISGITLINK(name_entry->mode) &&
771 is_tree_submodule_active(r, root_tree, tree_path)) {
772 ALLOC_GROW(out->entries, out->entry_nr + 1,
773 out->entry_alloc);
774 st_entry = &out->entries[out->entry_nr++];
776 st_entry->name_entry = xmalloc(sizeof(*st_entry->name_entry));
777 *st_entry->name_entry = *name_entry;
778 st_entry->submodule =
779 submodule_from_path(r, root_tree, tree_path);
780 st_entry->repo = xmalloc(sizeof(*st_entry->repo));
781 if (repo_submodule_init(st_entry->repo, r, tree_path,
782 root_tree))
783 FREE_AND_NULL(st_entry->repo);
785 } else if (S_ISDIR(name_entry->mode))
786 traverse_tree_submodules(r, root_tree, tree_path,
787 &name_entry->oid, out);
788 free(tree_path);
792 void submodules_of_tree(struct repository *r,
793 const struct object_id *treeish_name,
794 struct submodule_entry_list *out)
796 CALLOC_ARRAY(out->entries, 0);
797 out->entry_nr = 0;
798 out->entry_alloc = 0;
800 traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out);
803 void submodule_free(struct repository *r)
805 if (r->submodule_cache)
806 submodule_cache_clear(r->submodule_cache);
809 static int config_print_callback(const char *var, const char *value,
810 const struct config_context *ctx UNUSED,
811 void *cb_data)
813 char *wanted_key = cb_data;
815 if (!strcmp(wanted_key, var))
816 printf("%s\n", value);
818 return 0;
821 int print_config_from_gitmodules(struct repository *repo, const char *key)
823 int ret;
824 char *store_key;
826 ret = git_config_parse_key(key, &store_key, NULL);
827 if (ret < 0)
828 return CONFIG_INVALID_KEY;
830 config_from_gitmodules(config_print_callback, repo, store_key);
832 free(store_key);
833 return 0;
836 int config_set_in_gitmodules_file_gently(const char *key, const char *value)
838 int ret;
840 ret = git_config_set_in_file_gently(GITMODULES_FILE, key, value);
841 if (ret < 0)
842 /* Maybe the user already did that, don't error out here */
843 warning(_("Could not update .gitmodules entry %s"), key);
845 return ret;
848 struct fetch_config {
849 int *max_children;
850 int *recurse_submodules;
853 static int gitmodules_fetch_config(const char *var, const char *value,
854 const struct config_context *ctx,
855 void *cb)
857 struct fetch_config *config = cb;
858 if (!strcmp(var, "submodule.fetchjobs")) {
859 if (config->max_children)
860 *(config->max_children) =
861 parse_submodule_fetchjobs(var, value, ctx->kvi);
862 return 0;
863 } else if (!strcmp(var, "fetch.recursesubmodules")) {
864 if (config->recurse_submodules)
865 *(config->recurse_submodules) =
866 parse_fetch_recurse_submodules_arg(var, value);
867 return 0;
870 return 0;
873 void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules)
875 struct fetch_config config = {
876 .max_children = max_children,
877 .recurse_submodules = recurse_submodules
879 config_from_gitmodules(gitmodules_fetch_config, the_repository, &config);
882 static int gitmodules_update_clone_config(const char *var, const char *value,
883 const struct config_context *ctx,
884 void *cb)
886 int *max_jobs = cb;
887 if (!strcmp(var, "submodule.fetchjobs"))
888 *max_jobs = parse_submodule_fetchjobs(var, value, ctx->kvi);
889 return 0;
892 void update_clone_config_from_gitmodules(int *max_jobs)
894 config_from_gitmodules(gitmodules_update_clone_config, the_repository, &max_jobs);