]> git.ipfire.org Git - thirdparty/git.git/blob - submodule-config.c
treewide: be explicit about dependence on gettext.h
[thirdparty/git.git] / submodule-config.c
1 #include "cache.h"
2 #include "alloc.h"
3 #include "dir.h"
4 #include "gettext.h"
5 #include "hex.h"
6 #include "repository.h"
7 #include "config.h"
8 #include "submodule-config.h"
9 #include "submodule.h"
10 #include "strbuf.h"
11 #include "object-store.h"
12 #include "parse-options.h"
13 #include "tree-walk.h"
14
15 /*
16 * submodule cache lookup structure
17 * There is one shared set of 'struct submodule' entries which can be
18 * looked up by their sha1 blob id of the .gitmodules file and either
19 * using path or name as key.
20 * for_path stores submodule entries with path as key
21 * for_name stores submodule entries with name as key
22 */
23 struct submodule_cache {
24 struct hashmap for_path;
25 struct hashmap for_name;
26 unsigned initialized:1;
27 unsigned gitmodules_read:1;
28 };
29
30 /*
31 * thin wrapper struct needed to insert 'struct submodule' entries to
32 * the hashmap
33 */
34 struct submodule_entry {
35 struct hashmap_entry ent;
36 struct submodule *config;
37 };
38
39 enum lookup_type {
40 lookup_name,
41 lookup_path
42 };
43
44 static int config_path_cmp(const void *cmp_data UNUSED,
45 const struct hashmap_entry *eptr,
46 const struct hashmap_entry *entry_or_key,
47 const void *keydata UNUSED)
48 {
49 const struct submodule_entry *a, *b;
50
51 a = container_of(eptr, const struct submodule_entry, ent);
52 b = container_of(entry_or_key, const struct submodule_entry, ent);
53
54 return strcmp(a->config->path, b->config->path) ||
55 !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
56 }
57
58 static int config_name_cmp(const void *cmp_data UNUSED,
59 const struct hashmap_entry *eptr,
60 const struct hashmap_entry *entry_or_key,
61 const void *keydata UNUSED)
62 {
63 const struct submodule_entry *a, *b;
64
65 a = container_of(eptr, const struct submodule_entry, ent);
66 b = container_of(entry_or_key, const struct submodule_entry, ent);
67
68 return strcmp(a->config->name, b->config->name) ||
69 !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid);
70 }
71
72 static struct submodule_cache *submodule_cache_alloc(void)
73 {
74 return xcalloc(1, sizeof(struct submodule_cache));
75 }
76
77 static void submodule_cache_init(struct submodule_cache *cache)
78 {
79 hashmap_init(&cache->for_path, config_path_cmp, NULL, 0);
80 hashmap_init(&cache->for_name, config_name_cmp, NULL, 0);
81 cache->initialized = 1;
82 }
83
84 static void free_one_config(struct submodule_entry *entry)
85 {
86 free((void *) entry->config->path);
87 free((void *) entry->config->name);
88 free((void *) entry->config->branch);
89 free((void *) entry->config->update_strategy.command);
90 free(entry->config);
91 }
92
93 static void submodule_cache_clear(struct submodule_cache *cache)
94 {
95 struct hashmap_iter iter;
96 struct submodule_entry *entry;
97
98 if (!cache->initialized)
99 return;
100
101 /*
102 * We iterate over the name hash here to be symmetric with the
103 * allocation of struct submodule entries. Each is allocated by
104 * their .gitmodules blob sha1 and submodule name.
105 */
106 hashmap_for_each_entry(&cache->for_name, &iter, entry,
107 ent /* member name */)
108 free_one_config(entry);
109
110 hashmap_clear_and_free(&cache->for_path, struct submodule_entry, ent);
111 hashmap_clear_and_free(&cache->for_name, struct submodule_entry, ent);
112 cache->initialized = 0;
113 cache->gitmodules_read = 0;
114 }
115
116 void submodule_cache_free(struct submodule_cache *cache)
117 {
118 submodule_cache_clear(cache);
119 free(cache);
120 }
121
122 static unsigned int hash_oid_string(const struct object_id *oid,
123 const char *string)
124 {
125 return memhash(oid->hash, the_hash_algo->rawsz) + strhash(string);
126 }
127
128 static void cache_put_path(struct submodule_cache *cache,
129 struct submodule *submodule)
130 {
131 unsigned int hash = hash_oid_string(&submodule->gitmodules_oid,
132 submodule->path);
133 struct submodule_entry *e = xmalloc(sizeof(*e));
134 hashmap_entry_init(&e->ent, hash);
135 e->config = submodule;
136 hashmap_put(&cache->for_path, &e->ent);
137 }
138
139 static void cache_remove_path(struct submodule_cache *cache,
140 struct submodule *submodule)
141 {
142 unsigned int hash = hash_oid_string(&submodule->gitmodules_oid,
143 submodule->path);
144 struct submodule_entry e;
145 struct submodule_entry *removed;
146 hashmap_entry_init(&e.ent, hash);
147 e.config = submodule;
148 removed = hashmap_remove_entry(&cache->for_path, &e, ent, NULL);
149 free(removed);
150 }
151
152 static void cache_add(struct submodule_cache *cache,
153 struct submodule *submodule)
154 {
155 unsigned int hash = hash_oid_string(&submodule->gitmodules_oid,
156 submodule->name);
157 struct submodule_entry *e = xmalloc(sizeof(*e));
158 hashmap_entry_init(&e->ent, hash);
159 e->config = submodule;
160 hashmap_add(&cache->for_name, &e->ent);
161 }
162
163 static const struct submodule *cache_lookup_path(struct submodule_cache *cache,
164 const struct object_id *gitmodules_oid, const char *path)
165 {
166 struct submodule_entry *entry;
167 unsigned int hash = hash_oid_string(gitmodules_oid, path);
168 struct submodule_entry key;
169 struct submodule key_config;
170
171 oidcpy(&key_config.gitmodules_oid, gitmodules_oid);
172 key_config.path = path;
173
174 hashmap_entry_init(&key.ent, hash);
175 key.config = &key_config;
176
177 entry = hashmap_get_entry(&cache->for_path, &key, ent, NULL);
178 if (entry)
179 return entry->config;
180 return NULL;
181 }
182
183 static struct submodule *cache_lookup_name(struct submodule_cache *cache,
184 const struct object_id *gitmodules_oid, const char *name)
185 {
186 struct submodule_entry *entry;
187 unsigned int hash = hash_oid_string(gitmodules_oid, name);
188 struct submodule_entry key;
189 struct submodule key_config;
190
191 oidcpy(&key_config.gitmodules_oid, gitmodules_oid);
192 key_config.name = name;
193
194 hashmap_entry_init(&key.ent, hash);
195 key.config = &key_config;
196
197 entry = hashmap_get_entry(&cache->for_name, &key, ent, NULL);
198 if (entry)
199 return entry->config;
200 return NULL;
201 }
202
203 int check_submodule_name(const char *name)
204 {
205 /* Disallow empty names */
206 if (!*name)
207 return -1;
208
209 /*
210 * Look for '..' as a path component. Check is_xplatform_dir_sep() as
211 * separators rather than is_dir_sep(), because we want the name rules
212 * to be consistent across platforms.
213 */
214 goto in_component; /* always start inside component */
215 while (*name) {
216 char c = *name++;
217 if (is_xplatform_dir_sep(c)) {
218 in_component:
219 if (name[0] == '.' && name[1] == '.' &&
220 (!name[2] || is_xplatform_dir_sep(name[2])))
221 return -1;
222 }
223 }
224
225 return 0;
226 }
227
228 static int name_and_item_from_var(const char *var, struct strbuf *name,
229 struct strbuf *item)
230 {
231 const char *subsection, *key;
232 size_t subsection_len;
233 int parse;
234 parse = parse_config_key(var, "submodule", &subsection,
235 &subsection_len, &key);
236 if (parse < 0 || !subsection)
237 return 0;
238
239 strbuf_add(name, subsection, subsection_len);
240 if (check_submodule_name(name->buf) < 0) {
241 warning(_("ignoring suspicious submodule name: %s"), name->buf);
242 strbuf_release(name);
243 return 0;
244 }
245
246 strbuf_addstr(item, key);
247
248 return 1;
249 }
250
251 static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
252 const struct object_id *gitmodules_oid, const char *name)
253 {
254 struct submodule *submodule;
255 struct strbuf name_buf = STRBUF_INIT;
256
257 submodule = cache_lookup_name(cache, gitmodules_oid, name);
258 if (submodule)
259 return submodule;
260
261 submodule = xmalloc(sizeof(*submodule));
262
263 strbuf_addstr(&name_buf, name);
264 submodule->name = strbuf_detach(&name_buf, NULL);
265
266 submodule->path = NULL;
267 submodule->url = NULL;
268 submodule->update_strategy.type = SM_UPDATE_UNSPECIFIED;
269 submodule->update_strategy.command = NULL;
270 submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
271 submodule->ignore = NULL;
272 submodule->branch = NULL;
273 submodule->recommend_shallow = -1;
274
275 oidcpy(&submodule->gitmodules_oid, gitmodules_oid);
276
277 cache_add(cache, submodule);
278
279 return submodule;
280 }
281
282 static int parse_fetch_recurse(const char *opt, const char *arg,
283 int die_on_error)
284 {
285 switch (git_parse_maybe_bool(arg)) {
286 case 1:
287 return RECURSE_SUBMODULES_ON;
288 case 0:
289 return RECURSE_SUBMODULES_OFF;
290 default:
291 if (!strcmp(arg, "on-demand"))
292 return RECURSE_SUBMODULES_ON_DEMAND;
293 /*
294 * Please update $__git_fetch_recurse_submodules in
295 * git-completion.bash when you add new options.
296 */
297 if (die_on_error)
298 die("bad %s argument: %s", opt, arg);
299 else
300 return RECURSE_SUBMODULES_ERROR;
301 }
302 }
303
304 int parse_submodule_fetchjobs(const char *var, const char *value)
305 {
306 int fetchjobs = git_config_int(var, value);
307 if (fetchjobs < 0)
308 die(_("negative values not allowed for submodule.fetchJobs"));
309 if (!fetchjobs)
310 fetchjobs = online_cpus();
311 return fetchjobs;
312 }
313
314 int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
315 {
316 return parse_fetch_recurse(opt, arg, 1);
317 }
318
319 int option_fetch_parse_recurse_submodules(const struct option *opt,
320 const char *arg, int unset)
321 {
322 int *v;
323
324 if (!opt->value)
325 return -1;
326
327 v = opt->value;
328
329 if (unset) {
330 *v = RECURSE_SUBMODULES_OFF;
331 } else {
332 if (arg)
333 *v = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
334 else
335 *v = RECURSE_SUBMODULES_ON;
336 }
337 return 0;
338 }
339
340 static int parse_update_recurse(const char *opt, const char *arg,
341 int die_on_error)
342 {
343 switch (git_parse_maybe_bool(arg)) {
344 case 1:
345 return RECURSE_SUBMODULES_ON;
346 case 0:
347 return RECURSE_SUBMODULES_OFF;
348 default:
349 if (die_on_error)
350 die("bad %s argument: %s", opt, arg);
351 return RECURSE_SUBMODULES_ERROR;
352 }
353 }
354
355 int parse_update_recurse_submodules_arg(const char *opt, const char *arg)
356 {
357 return parse_update_recurse(opt, arg, 1);
358 }
359
360 static int parse_push_recurse(const char *opt, const char *arg,
361 int die_on_error)
362 {
363 switch (git_parse_maybe_bool(arg)) {
364 case 1:
365 /* There's no simple "on" value when pushing */
366 if (die_on_error)
367 die("bad %s argument: %s", opt, arg);
368 else
369 return RECURSE_SUBMODULES_ERROR;
370 case 0:
371 return RECURSE_SUBMODULES_OFF;
372 default:
373 if (!strcmp(arg, "on-demand"))
374 return RECURSE_SUBMODULES_ON_DEMAND;
375 else if (!strcmp(arg, "check"))
376 return RECURSE_SUBMODULES_CHECK;
377 else if (!strcmp(arg, "only"))
378 return RECURSE_SUBMODULES_ONLY;
379 /*
380 * Please update $__git_push_recurse_submodules in
381 * git-completion.bash when you add new modes.
382 */
383 else if (die_on_error)
384 die("bad %s argument: %s", opt, arg);
385 else
386 return RECURSE_SUBMODULES_ERROR;
387 }
388 }
389
390 int parse_push_recurse_submodules_arg(const char *opt, const char *arg)
391 {
392 return parse_push_recurse(opt, arg, 1);
393 }
394
395 static void warn_multiple_config(const struct object_id *treeish_name,
396 const char *name, const char *option)
397 {
398 const char *commit_string = "WORKTREE";
399 if (treeish_name)
400 commit_string = oid_to_hex(treeish_name);
401 warning("%s:.gitmodules, multiple configurations found for "
402 "'submodule.%s.%s'. Skipping second one!",
403 commit_string, name, option);
404 }
405
406 static void warn_command_line_option(const char *var, const char *value)
407 {
408 warning(_("ignoring '%s' which may be interpreted as"
409 " a command-line option: %s"), var, value);
410 }
411
412 struct parse_config_parameter {
413 struct submodule_cache *cache;
414 const struct object_id *treeish_name;
415 const struct object_id *gitmodules_oid;
416 int overwrite;
417 };
418
419 /*
420 * Parse a config item from .gitmodules.
421 *
422 * This does not handle submodule-related configuration from the main
423 * config store (.git/config, etc). Callers are responsible for
424 * checking for overrides in the main config store when appropriate.
425 */
426 static int parse_config(const char *var, const char *value, void *data)
427 {
428 struct parse_config_parameter *me = data;
429 struct submodule *submodule;
430 struct strbuf name = STRBUF_INIT, item = STRBUF_INIT;
431 int ret = 0;
432
433 /* this also ensures that we only parse submodule entries */
434 if (!name_and_item_from_var(var, &name, &item))
435 return 0;
436
437 submodule = lookup_or_create_by_name(me->cache,
438 me->gitmodules_oid,
439 name.buf);
440
441 if (!strcmp(item.buf, "path")) {
442 if (!value)
443 ret = config_error_nonbool(var);
444 else if (looks_like_command_line_option(value))
445 warn_command_line_option(var, value);
446 else if (!me->overwrite && submodule->path)
447 warn_multiple_config(me->treeish_name, submodule->name,
448 "path");
449 else {
450 if (submodule->path)
451 cache_remove_path(me->cache, submodule);
452 free((void *) submodule->path);
453 submodule->path = xstrdup(value);
454 cache_put_path(me->cache, submodule);
455 }
456 } else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
457 /* when parsing worktree configurations we can die early */
458 int die_on_error = is_null_oid(me->gitmodules_oid);
459 if (!me->overwrite &&
460 submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
461 warn_multiple_config(me->treeish_name, submodule->name,
462 "fetchrecursesubmodules");
463 else
464 submodule->fetch_recurse = parse_fetch_recurse(
465 var, value,
466 die_on_error);
467 } else if (!strcmp(item.buf, "ignore")) {
468 if (!value)
469 ret = config_error_nonbool(var);
470 else if (!me->overwrite && submodule->ignore)
471 warn_multiple_config(me->treeish_name, submodule->name,
472 "ignore");
473 else if (strcmp(value, "untracked") &&
474 strcmp(value, "dirty") &&
475 strcmp(value, "all") &&
476 strcmp(value, "none"))
477 warning("Invalid parameter '%s' for config option "
478 "'submodule.%s.ignore'", value, name.buf);
479 else {
480 free((void *) submodule->ignore);
481 submodule->ignore = xstrdup(value);
482 }
483 } else if (!strcmp(item.buf, "url")) {
484 if (!value) {
485 ret = config_error_nonbool(var);
486 } else if (looks_like_command_line_option(value)) {
487 warn_command_line_option(var, value);
488 } else if (!me->overwrite && submodule->url) {
489 warn_multiple_config(me->treeish_name, submodule->name,
490 "url");
491 } else {
492 free((void *) submodule->url);
493 submodule->url = xstrdup(value);
494 }
495 } else if (!strcmp(item.buf, "update")) {
496 if (!value)
497 ret = config_error_nonbool(var);
498 else if (!me->overwrite &&
499 submodule->update_strategy.type != SM_UPDATE_UNSPECIFIED)
500 warn_multiple_config(me->treeish_name, submodule->name,
501 "update");
502 else if (parse_submodule_update_strategy(value,
503 &submodule->update_strategy) < 0 ||
504 submodule->update_strategy.type == SM_UPDATE_COMMAND)
505 die(_("invalid value for '%s'"), var);
506 } else if (!strcmp(item.buf, "shallow")) {
507 if (!me->overwrite && submodule->recommend_shallow != -1)
508 warn_multiple_config(me->treeish_name, submodule->name,
509 "shallow");
510 else
511 submodule->recommend_shallow =
512 git_config_bool(var, value);
513 } else if (!strcmp(item.buf, "branch")) {
514 if (!me->overwrite && submodule->branch)
515 warn_multiple_config(me->treeish_name, submodule->name,
516 "branch");
517 else {
518 free((void *)submodule->branch);
519 submodule->branch = xstrdup(value);
520 }
521 }
522
523 strbuf_release(&name);
524 strbuf_release(&item);
525
526 return ret;
527 }
528
529 static int gitmodule_oid_from_commit(const struct object_id *treeish_name,
530 struct object_id *gitmodules_oid,
531 struct strbuf *rev)
532 {
533 int ret = 0;
534
535 if (is_null_oid(treeish_name)) {
536 oidclr(gitmodules_oid);
537 return 1;
538 }
539
540 strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
541 if (get_oid(rev->buf, gitmodules_oid) >= 0)
542 ret = 1;
543
544 return ret;
545 }
546
547 /* This does a lookup of a submodule configuration by name or by path
548 * (key) with on-demand reading of the appropriate .gitmodules from
549 * revisions.
550 */
551 static const struct submodule *config_from(struct submodule_cache *cache,
552 const struct object_id *treeish_name, const char *key,
553 enum lookup_type lookup_type)
554 {
555 struct strbuf rev = STRBUF_INIT;
556 unsigned long config_size;
557 char *config = NULL;
558 struct object_id oid;
559 enum object_type type;
560 const struct submodule *submodule = NULL;
561 struct parse_config_parameter parameter;
562
563 /*
564 * If any parameter except the cache is a NULL pointer just
565 * return the first submodule. Can be used to check whether
566 * there are any submodules parsed.
567 */
568 if (!treeish_name || !key) {
569 struct hashmap_iter iter;
570 struct submodule_entry *entry;
571
572 entry = hashmap_iter_first_entry(&cache->for_name, &iter,
573 struct submodule_entry,
574 ent /* member name */);
575 if (!entry)
576 return NULL;
577 return entry->config;
578 }
579
580 if (!gitmodule_oid_from_commit(treeish_name, &oid, &rev))
581 goto out;
582
583 switch (lookup_type) {
584 case lookup_name:
585 submodule = cache_lookup_name(cache, &oid, key);
586 break;
587 case lookup_path:
588 submodule = cache_lookup_path(cache, &oid, key);
589 break;
590 }
591 if (submodule)
592 goto out;
593
594 config = read_object_file(&oid, &type, &config_size);
595 if (!config || type != OBJ_BLOB)
596 goto out;
597
598 /* fill the submodule config into the cache */
599 parameter.cache = cache;
600 parameter.treeish_name = treeish_name;
601 parameter.gitmodules_oid = &oid;
602 parameter.overwrite = 0;
603 git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
604 config, config_size, &parameter, NULL);
605 strbuf_release(&rev);
606 free(config);
607
608 switch (lookup_type) {
609 case lookup_name:
610 return cache_lookup_name(cache, &oid, key);
611 case lookup_path:
612 return cache_lookup_path(cache, &oid, key);
613 default:
614 return NULL;
615 }
616
617 out:
618 strbuf_release(&rev);
619 free(config);
620 return submodule;
621 }
622
623 static void submodule_cache_check_init(struct repository *repo)
624 {
625 if (repo->submodule_cache && repo->submodule_cache->initialized)
626 return;
627
628 if (!repo->submodule_cache)
629 repo->submodule_cache = submodule_cache_alloc();
630
631 submodule_cache_init(repo->submodule_cache);
632 }
633
634 /*
635 * Note: This function is private for a reason, the '.gitmodules' file should
636 * not be used as a mechanism to retrieve arbitrary configuration stored in
637 * the repository.
638 *
639 * Runs the provided config function on the '.gitmodules' file found in the
640 * working directory.
641 */
642 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
643 {
644 if (repo->worktree) {
645 struct git_config_source config_source = {
646 0, .scope = CONFIG_SCOPE_SUBMODULE
647 };
648 const struct config_options opts = { 0 };
649 struct object_id oid;
650 char *file;
651 char *oidstr = NULL;
652
653 file = repo_worktree_path(repo, GITMODULES_FILE);
654 if (file_exists(file)) {
655 config_source.file = file;
656 } else if (repo_get_oid(repo, GITMODULES_INDEX, &oid) >= 0 ||
657 repo_get_oid(repo, GITMODULES_HEAD, &oid) >= 0) {
658 config_source.repo = repo;
659 config_source.blob = oidstr = xstrdup(oid_to_hex(&oid));
660 if (repo != the_repository)
661 add_submodule_odb_by_path(repo->objects->odb->path);
662 } else {
663 goto out;
664 }
665
666 config_with_options(fn, data, &config_source, &opts);
667
668 out:
669 free(oidstr);
670 free(file);
671 }
672 }
673
674 static int gitmodules_cb(const char *var, const char *value, void *data)
675 {
676 struct repository *repo = data;
677 struct parse_config_parameter parameter;
678
679 parameter.cache = repo->submodule_cache;
680 parameter.treeish_name = NULL;
681 parameter.gitmodules_oid = null_oid();
682 parameter.overwrite = 1;
683
684 return parse_config(var, value, &parameter);
685 }
686
687 void repo_read_gitmodules(struct repository *repo, int skip_if_read)
688 {
689 submodule_cache_check_init(repo);
690
691 if (repo->submodule_cache->gitmodules_read && skip_if_read)
692 return;
693
694 if (repo_read_index(repo) < 0)
695 return;
696
697 if (!is_gitmodules_unmerged(repo->index))
698 config_from_gitmodules(gitmodules_cb, repo, repo);
699
700 repo->submodule_cache->gitmodules_read = 1;
701 }
702
703 void gitmodules_config_oid(const struct object_id *commit_oid)
704 {
705 struct strbuf rev = STRBUF_INIT;
706 struct object_id oid;
707
708 submodule_cache_check_init(the_repository);
709
710 if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
711 git_config_from_blob_oid(gitmodules_cb, rev.buf,
712 the_repository, &oid, the_repository);
713 }
714 strbuf_release(&rev);
715
716 the_repository->submodule_cache->gitmodules_read = 1;
717 }
718
719 const struct submodule *submodule_from_name(struct repository *r,
720 const struct object_id *treeish_name,
721 const char *name)
722 {
723 repo_read_gitmodules(r, 1);
724 return config_from(r->submodule_cache, treeish_name, name, lookup_name);
725 }
726
727 const struct submodule *submodule_from_path(struct repository *r,
728 const struct object_id *treeish_name,
729 const char *path)
730 {
731 repo_read_gitmodules(r, 1);
732 return config_from(r->submodule_cache, treeish_name, path, lookup_path);
733 }
734
735 /**
736 * Used internally by submodules_of_tree(). Recurses into 'treeish_name'
737 * and appends submodule entries to 'out'. The submodule_cache expects
738 * a root-level treeish_name and paths, so keep track of these values
739 * with 'root_tree' and 'prefix'.
740 */
741 static void traverse_tree_submodules(struct repository *r,
742 const struct object_id *root_tree,
743 char *prefix,
744 const struct object_id *treeish_name,
745 struct submodule_entry_list *out)
746 {
747 struct tree_desc tree;
748 struct submodule_tree_entry *st_entry;
749 struct name_entry *name_entry;
750 char *tree_path = NULL;
751
752 name_entry = xmalloc(sizeof(*name_entry));
753
754 fill_tree_descriptor(r, &tree, treeish_name);
755 while (tree_entry(&tree, name_entry)) {
756 if (prefix)
757 tree_path =
758 mkpathdup("%s/%s", prefix, name_entry->path);
759 else
760 tree_path = xstrdup(name_entry->path);
761
762 if (S_ISGITLINK(name_entry->mode) &&
763 is_tree_submodule_active(r, root_tree, tree_path)) {
764 ALLOC_GROW(out->entries, out->entry_nr + 1,
765 out->entry_alloc);
766 st_entry = &out->entries[out->entry_nr++];
767
768 st_entry->name_entry = xmalloc(sizeof(*st_entry->name_entry));
769 *st_entry->name_entry = *name_entry;
770 st_entry->submodule =
771 submodule_from_path(r, root_tree, tree_path);
772 st_entry->repo = xmalloc(sizeof(*st_entry->repo));
773 if (repo_submodule_init(st_entry->repo, r, tree_path,
774 root_tree))
775 FREE_AND_NULL(st_entry->repo);
776
777 } else if (S_ISDIR(name_entry->mode))
778 traverse_tree_submodules(r, root_tree, tree_path,
779 &name_entry->oid, out);
780 free(tree_path);
781 }
782 }
783
784 void submodules_of_tree(struct repository *r,
785 const struct object_id *treeish_name,
786 struct submodule_entry_list *out)
787 {
788 CALLOC_ARRAY(out->entries, 0);
789 out->entry_nr = 0;
790 out->entry_alloc = 0;
791
792 traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out);
793 }
794
795 void submodule_free(struct repository *r)
796 {
797 if (r->submodule_cache)
798 submodule_cache_clear(r->submodule_cache);
799 }
800
801 static int config_print_callback(const char *var, const char *value, void *cb_data)
802 {
803 char *wanted_key = cb_data;
804
805 if (!strcmp(wanted_key, var))
806 printf("%s\n", value);
807
808 return 0;
809 }
810
811 int print_config_from_gitmodules(struct repository *repo, const char *key)
812 {
813 int ret;
814 char *store_key;
815
816 ret = git_config_parse_key(key, &store_key, NULL);
817 if (ret < 0)
818 return CONFIG_INVALID_KEY;
819
820 config_from_gitmodules(config_print_callback, repo, store_key);
821
822 free(store_key);
823 return 0;
824 }
825
826 int config_set_in_gitmodules_file_gently(const char *key, const char *value)
827 {
828 int ret;
829
830 ret = git_config_set_in_file_gently(GITMODULES_FILE, key, value);
831 if (ret < 0)
832 /* Maybe the user already did that, don't error out here */
833 warning(_("Could not update .gitmodules entry %s"), key);
834
835 return ret;
836 }
837
838 struct fetch_config {
839 int *max_children;
840 int *recurse_submodules;
841 };
842
843 static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
844 {
845 struct fetch_config *config = cb;
846 if (!strcmp(var, "submodule.fetchjobs")) {
847 if (config->max_children)
848 *(config->max_children) =
849 parse_submodule_fetchjobs(var, value);
850 return 0;
851 } else if (!strcmp(var, "fetch.recursesubmodules")) {
852 if (config->recurse_submodules)
853 *(config->recurse_submodules) =
854 parse_fetch_recurse_submodules_arg(var, value);
855 return 0;
856 }
857
858 return 0;
859 }
860
861 void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules)
862 {
863 struct fetch_config config = {
864 .max_children = max_children,
865 .recurse_submodules = recurse_submodules
866 };
867 config_from_gitmodules(gitmodules_fetch_config, the_repository, &config);
868 }
869
870 static int gitmodules_update_clone_config(const char *var, const char *value,
871 void *cb)
872 {
873 int *max_jobs = cb;
874 if (!strcmp(var, "submodule.fetchjobs"))
875 *max_jobs = parse_submodule_fetchjobs(var, value);
876 return 0;
877 }
878
879 void update_clone_config_from_gitmodules(int *max_jobs)
880 {
881 config_from_gitmodules(gitmodules_update_clone_config, the_repository, &max_jobs);
882 }