object-store: move object access functions to object-store.h
[git] / submodule-config.c
1 #include "cache.h"
2 #include "repository.h"
3 #include "config.h"
4 #include "submodule-config.h"
5 #include "submodule.h"
6 #include "strbuf.h"
7 #include "object-store.h"
8 #include "parse-options.h"
9
10 /*
11  * submodule cache lookup structure
12  * There is one shared set of 'struct submodule' entries which can be
13  * looked up by their sha1 blob id of the .gitmodules file and either
14  * using path or name as key.
15  * for_path stores submodule entries with path as key
16  * for_name stores submodule entries with name as key
17  */
18 struct submodule_cache {
19         struct hashmap for_path;
20         struct hashmap for_name;
21         unsigned initialized:1;
22         unsigned gitmodules_read:1;
23 };
24
25 /*
26  * thin wrapper struct needed to insert 'struct submodule' entries to
27  * the hashmap
28  */
29 struct submodule_entry {
30         struct hashmap_entry ent;
31         struct submodule *config;
32 };
33
34 enum lookup_type {
35         lookup_name,
36         lookup_path
37 };
38
39 static int config_path_cmp(const void *unused_cmp_data,
40                            const void *entry,
41                            const void *entry_or_key,
42                            const void *unused_keydata)
43 {
44         const struct submodule_entry *a = entry;
45         const struct submodule_entry *b = entry_or_key;
46
47         return strcmp(a->config->path, b->config->path) ||
48                hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
49 }
50
51 static int config_name_cmp(const void *unused_cmp_data,
52                            const void *entry,
53                            const void *entry_or_key,
54                            const void *unused_keydata)
55 {
56         const struct submodule_entry *a = entry;
57         const struct submodule_entry *b = entry_or_key;
58
59         return strcmp(a->config->name, b->config->name) ||
60                hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
61 }
62
63 static struct submodule_cache *submodule_cache_alloc(void)
64 {
65         return xcalloc(1, sizeof(struct submodule_cache));
66 }
67
68 static void submodule_cache_init(struct submodule_cache *cache)
69 {
70         hashmap_init(&cache->for_path, config_path_cmp, NULL, 0);
71         hashmap_init(&cache->for_name, config_name_cmp, NULL, 0);
72         cache->initialized = 1;
73 }
74
75 static void free_one_config(struct submodule_entry *entry)
76 {
77         free((void *) entry->config->path);
78         free((void *) entry->config->name);
79         free((void *) entry->config->branch);
80         free((void *) entry->config->update_strategy.command);
81         free(entry->config);
82 }
83
84 static void submodule_cache_clear(struct submodule_cache *cache)
85 {
86         struct hashmap_iter iter;
87         struct submodule_entry *entry;
88
89         if (!cache->initialized)
90                 return;
91
92         /*
93          * We iterate over the name hash here to be symmetric with the
94          * allocation of struct submodule entries. Each is allocated by
95          * their .gitmodules blob sha1 and submodule name.
96          */
97         hashmap_iter_init(&cache->for_name, &iter);
98         while ((entry = hashmap_iter_next(&iter)))
99                 free_one_config(entry);
100
101         hashmap_free(&cache->for_path, 1);
102         hashmap_free(&cache->for_name, 1);
103         cache->initialized = 0;
104         cache->gitmodules_read = 0;
105 }
106
107 void submodule_cache_free(struct submodule_cache *cache)
108 {
109         submodule_cache_clear(cache);
110         free(cache);
111 }
112
113 static unsigned int hash_sha1_string(const unsigned char *sha1,
114                                      const char *string)
115 {
116         return memhash(sha1, 20) + strhash(string);
117 }
118
119 static void cache_put_path(struct submodule_cache *cache,
120                            struct submodule *submodule)
121 {
122         unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
123                                              submodule->path);
124         struct submodule_entry *e = xmalloc(sizeof(*e));
125         hashmap_entry_init(e, hash);
126         e->config = submodule;
127         hashmap_put(&cache->for_path, e);
128 }
129
130 static void cache_remove_path(struct submodule_cache *cache,
131                               struct submodule *submodule)
132 {
133         unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
134                                              submodule->path);
135         struct submodule_entry e;
136         struct submodule_entry *removed;
137         hashmap_entry_init(&e, hash);
138         e.config = submodule;
139         removed = hashmap_remove(&cache->for_path, &e, NULL);
140         free(removed);
141 }
142
143 static void cache_add(struct submodule_cache *cache,
144                       struct submodule *submodule)
145 {
146         unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
147                                              submodule->name);
148         struct submodule_entry *e = xmalloc(sizeof(*e));
149         hashmap_entry_init(e, hash);
150         e->config = submodule;
151         hashmap_add(&cache->for_name, e);
152 }
153
154 static const struct submodule *cache_lookup_path(struct submodule_cache *cache,
155                 const unsigned char *gitmodules_sha1, const char *path)
156 {
157         struct submodule_entry *entry;
158         unsigned int hash = hash_sha1_string(gitmodules_sha1, path);
159         struct submodule_entry key;
160         struct submodule key_config;
161
162         hashcpy(key_config.gitmodules_sha1, gitmodules_sha1);
163         key_config.path = path;
164
165         hashmap_entry_init(&key, hash);
166         key.config = &key_config;
167
168         entry = hashmap_get(&cache->for_path, &key, NULL);
169         if (entry)
170                 return entry->config;
171         return NULL;
172 }
173
174 static struct submodule *cache_lookup_name(struct submodule_cache *cache,
175                 const unsigned char *gitmodules_sha1, const char *name)
176 {
177         struct submodule_entry *entry;
178         unsigned int hash = hash_sha1_string(gitmodules_sha1, name);
179         struct submodule_entry key;
180         struct submodule key_config;
181
182         hashcpy(key_config.gitmodules_sha1, gitmodules_sha1);
183         key_config.name = name;
184
185         hashmap_entry_init(&key, hash);
186         key.config = &key_config;
187
188         entry = hashmap_get(&cache->for_name, &key, NULL);
189         if (entry)
190                 return entry->config;
191         return NULL;
192 }
193
194 static int name_and_item_from_var(const char *var, struct strbuf *name,
195                                   struct strbuf *item)
196 {
197         const char *subsection, *key;
198         int subsection_len, parse;
199         parse = parse_config_key(var, "submodule", &subsection,
200                         &subsection_len, &key);
201         if (parse < 0 || !subsection)
202                 return 0;
203
204         strbuf_add(name, subsection, subsection_len);
205         strbuf_addstr(item, key);
206
207         return 1;
208 }
209
210 static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
211                 const unsigned char *gitmodules_sha1, const char *name)
212 {
213         struct submodule *submodule;
214         struct strbuf name_buf = STRBUF_INIT;
215
216         submodule = cache_lookup_name(cache, gitmodules_sha1, name);
217         if (submodule)
218                 return submodule;
219
220         submodule = xmalloc(sizeof(*submodule));
221
222         strbuf_addstr(&name_buf, name);
223         submodule->name = strbuf_detach(&name_buf, NULL);
224
225         submodule->path = NULL;
226         submodule->url = NULL;
227         submodule->update_strategy.type = SM_UPDATE_UNSPECIFIED;
228         submodule->update_strategy.command = NULL;
229         submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
230         submodule->ignore = NULL;
231         submodule->branch = NULL;
232         submodule->recommend_shallow = -1;
233
234         hashcpy(submodule->gitmodules_sha1, gitmodules_sha1);
235
236         cache_add(cache, submodule);
237
238         return submodule;
239 }
240
241 static int parse_fetch_recurse(const char *opt, const char *arg,
242                                int die_on_error)
243 {
244         switch (git_parse_maybe_bool(arg)) {
245         case 1:
246                 return RECURSE_SUBMODULES_ON;
247         case 0:
248                 return RECURSE_SUBMODULES_OFF;
249         default:
250                 if (!strcmp(arg, "on-demand"))
251                         return RECURSE_SUBMODULES_ON_DEMAND;
252
253                 if (die_on_error)
254                         die("bad %s argument: %s", opt, arg);
255                 else
256                         return RECURSE_SUBMODULES_ERROR;
257         }
258 }
259
260 int parse_submodule_fetchjobs(const char *var, const char *value)
261 {
262         int fetchjobs = git_config_int(var, value);
263         if (fetchjobs < 0)
264                 die(_("negative values not allowed for submodule.fetchjobs"));
265         return fetchjobs;
266 }
267
268 int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
269 {
270         return parse_fetch_recurse(opt, arg, 1);
271 }
272
273 int option_fetch_parse_recurse_submodules(const struct option *opt,
274                                           const char *arg, int unset)
275 {
276         int *v;
277
278         if (!opt->value)
279                 return -1;
280
281         v = opt->value;
282
283         if (unset) {
284                 *v = RECURSE_SUBMODULES_OFF;
285         } else {
286                 if (arg)
287                         *v = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
288                 else
289                         *v = RECURSE_SUBMODULES_ON;
290         }
291         return 0;
292 }
293
294 static int parse_update_recurse(const char *opt, const char *arg,
295                                 int die_on_error)
296 {
297         switch (git_parse_maybe_bool(arg)) {
298         case 1:
299                 return RECURSE_SUBMODULES_ON;
300         case 0:
301                 return RECURSE_SUBMODULES_OFF;
302         default:
303                 if (die_on_error)
304                         die("bad %s argument: %s", opt, arg);
305                 return RECURSE_SUBMODULES_ERROR;
306         }
307 }
308
309 int parse_update_recurse_submodules_arg(const char *opt, const char *arg)
310 {
311         return parse_update_recurse(opt, arg, 1);
312 }
313
314 static int parse_push_recurse(const char *opt, const char *arg,
315                                int die_on_error)
316 {
317         switch (git_parse_maybe_bool(arg)) {
318         case 1:
319                 /* There's no simple "on" value when pushing */
320                 if (die_on_error)
321                         die("bad %s argument: %s", opt, arg);
322                 else
323                         return RECURSE_SUBMODULES_ERROR;
324         case 0:
325                 return RECURSE_SUBMODULES_OFF;
326         default:
327                 if (!strcmp(arg, "on-demand"))
328                         return RECURSE_SUBMODULES_ON_DEMAND;
329                 else if (!strcmp(arg, "check"))
330                         return RECURSE_SUBMODULES_CHECK;
331                 else if (!strcmp(arg, "only"))
332                         return RECURSE_SUBMODULES_ONLY;
333                 else if (die_on_error)
334                         die("bad %s argument: %s", opt, arg);
335                 else
336                         return RECURSE_SUBMODULES_ERROR;
337         }
338 }
339
340 int parse_push_recurse_submodules_arg(const char *opt, const char *arg)
341 {
342         return parse_push_recurse(opt, arg, 1);
343 }
344
345 static void warn_multiple_config(const unsigned char *treeish_name,
346                                  const char *name, const char *option)
347 {
348         const char *commit_string = "WORKTREE";
349         if (treeish_name)
350                 commit_string = sha1_to_hex(treeish_name);
351         warning("%s:.gitmodules, multiple configurations found for "
352                         "'submodule.%s.%s'. Skipping second one!",
353                         commit_string, name, option);
354 }
355
356 struct parse_config_parameter {
357         struct submodule_cache *cache;
358         const unsigned char *treeish_name;
359         const unsigned char *gitmodules_sha1;
360         int overwrite;
361 };
362
363 static int parse_config(const char *var, const char *value, void *data)
364 {
365         struct parse_config_parameter *me = data;
366         struct submodule *submodule;
367         struct strbuf name = STRBUF_INIT, item = STRBUF_INIT;
368         int ret = 0;
369
370         /* this also ensures that we only parse submodule entries */
371         if (!name_and_item_from_var(var, &name, &item))
372                 return 0;
373
374         submodule = lookup_or_create_by_name(me->cache,
375                                              me->gitmodules_sha1,
376                                              name.buf);
377
378         if (!strcmp(item.buf, "path")) {
379                 if (!value)
380                         ret = config_error_nonbool(var);
381                 else if (!me->overwrite && submodule->path)
382                         warn_multiple_config(me->treeish_name, submodule->name,
383                                         "path");
384                 else {
385                         if (submodule->path)
386                                 cache_remove_path(me->cache, submodule);
387                         free((void *) submodule->path);
388                         submodule->path = xstrdup(value);
389                         cache_put_path(me->cache, submodule);
390                 }
391         } else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
392                 /* when parsing worktree configurations we can die early */
393                 int die_on_error = is_null_sha1(me->gitmodules_sha1);
394                 if (!me->overwrite &&
395                     submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
396                         warn_multiple_config(me->treeish_name, submodule->name,
397                                         "fetchrecursesubmodules");
398                 else
399                         submodule->fetch_recurse = parse_fetch_recurse(
400                                                                 var, value,
401                                                                 die_on_error);
402         } else if (!strcmp(item.buf, "ignore")) {
403                 if (!value)
404                         ret = config_error_nonbool(var);
405                 else if (!me->overwrite && submodule->ignore)
406                         warn_multiple_config(me->treeish_name, submodule->name,
407                                         "ignore");
408                 else if (strcmp(value, "untracked") &&
409                          strcmp(value, "dirty") &&
410                          strcmp(value, "all") &&
411                          strcmp(value, "none"))
412                         warning("Invalid parameter '%s' for config option "
413                                         "'submodule.%s.ignore'", value, name.buf);
414                 else {
415                         free((void *) submodule->ignore);
416                         submodule->ignore = xstrdup(value);
417                 }
418         } else if (!strcmp(item.buf, "url")) {
419                 if (!value) {
420                         ret = config_error_nonbool(var);
421                 } else if (!me->overwrite && submodule->url) {
422                         warn_multiple_config(me->treeish_name, submodule->name,
423                                         "url");
424                 } else {
425                         free((void *) submodule->url);
426                         submodule->url = xstrdup(value);
427                 }
428         } else if (!strcmp(item.buf, "update")) {
429                 if (!value)
430                         ret = config_error_nonbool(var);
431                 else if (!me->overwrite &&
432                          submodule->update_strategy.type != SM_UPDATE_UNSPECIFIED)
433                         warn_multiple_config(me->treeish_name, submodule->name,
434                                              "update");
435                 else if (parse_submodule_update_strategy(value,
436                          &submodule->update_strategy) < 0)
437                                 die(_("invalid value for %s"), var);
438         } else if (!strcmp(item.buf, "shallow")) {
439                 if (!me->overwrite && submodule->recommend_shallow != -1)
440                         warn_multiple_config(me->treeish_name, submodule->name,
441                                              "shallow");
442                 else
443                         submodule->recommend_shallow =
444                                 git_config_bool(var, value);
445         } else if (!strcmp(item.buf, "branch")) {
446                 if (!me->overwrite && submodule->branch)
447                         warn_multiple_config(me->treeish_name, submodule->name,
448                                              "branch");
449                 else {
450                         free((void *)submodule->branch);
451                         submodule->branch = xstrdup(value);
452                 }
453         }
454
455         strbuf_release(&name);
456         strbuf_release(&item);
457
458         return ret;
459 }
460
461 static int gitmodule_oid_from_commit(const struct object_id *treeish_name,
462                                      struct object_id *gitmodules_oid,
463                                      struct strbuf *rev)
464 {
465         int ret = 0;
466
467         if (is_null_oid(treeish_name)) {
468                 oidclr(gitmodules_oid);
469                 return 1;
470         }
471
472         strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
473         if (get_oid(rev->buf, gitmodules_oid) >= 0)
474                 ret = 1;
475
476         return ret;
477 }
478
479 /* This does a lookup of a submodule configuration by name or by path
480  * (key) with on-demand reading of the appropriate .gitmodules from
481  * revisions.
482  */
483 static const struct submodule *config_from(struct submodule_cache *cache,
484                 const struct object_id *treeish_name, const char *key,
485                 enum lookup_type lookup_type)
486 {
487         struct strbuf rev = STRBUF_INIT;
488         unsigned long config_size;
489         char *config = NULL;
490         struct object_id oid;
491         enum object_type type;
492         const struct submodule *submodule = NULL;
493         struct parse_config_parameter parameter;
494
495         /*
496          * If any parameter except the cache is a NULL pointer just
497          * return the first submodule. Can be used to check whether
498          * there are any submodules parsed.
499          */
500         if (!treeish_name || !key) {
501                 struct hashmap_iter iter;
502                 struct submodule_entry *entry;
503
504                 entry = hashmap_iter_first(&cache->for_name, &iter);
505                 if (!entry)
506                         return NULL;
507                 return entry->config;
508         }
509
510         if (!gitmodule_oid_from_commit(treeish_name, &oid, &rev))
511                 goto out;
512
513         switch (lookup_type) {
514         case lookup_name:
515                 submodule = cache_lookup_name(cache, oid.hash, key);
516                 break;
517         case lookup_path:
518                 submodule = cache_lookup_path(cache, oid.hash, key);
519                 break;
520         }
521         if (submodule)
522                 goto out;
523
524         config = read_object_file(&oid, &type, &config_size);
525         if (!config || type != OBJ_BLOB)
526                 goto out;
527
528         /* fill the submodule config into the cache */
529         parameter.cache = cache;
530         parameter.treeish_name = treeish_name->hash;
531         parameter.gitmodules_sha1 = oid.hash;
532         parameter.overwrite = 0;
533         git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
534                         config, config_size, &parameter);
535         strbuf_release(&rev);
536         free(config);
537
538         switch (lookup_type) {
539         case lookup_name:
540                 return cache_lookup_name(cache, oid.hash, key);
541         case lookup_path:
542                 return cache_lookup_path(cache, oid.hash, key);
543         default:
544                 return NULL;
545         }
546
547 out:
548         strbuf_release(&rev);
549         free(config);
550         return submodule;
551 }
552
553 static void submodule_cache_check_init(struct repository *repo)
554 {
555         if (repo->submodule_cache && repo->submodule_cache->initialized)
556                 return;
557
558         if (!repo->submodule_cache)
559                 repo->submodule_cache = submodule_cache_alloc();
560
561         submodule_cache_init(repo->submodule_cache);
562 }
563
564 static int gitmodules_cb(const char *var, const char *value, void *data)
565 {
566         struct repository *repo = data;
567         struct parse_config_parameter parameter;
568
569         parameter.cache = repo->submodule_cache;
570         parameter.treeish_name = NULL;
571         parameter.gitmodules_sha1 = null_sha1;
572         parameter.overwrite = 1;
573
574         return parse_config(var, value, &parameter);
575 }
576
577 void repo_read_gitmodules(struct repository *repo)
578 {
579         submodule_cache_check_init(repo);
580
581         if (repo->worktree) {
582                 char *gitmodules;
583
584                 if (repo_read_index(repo) < 0)
585                         return;
586
587                 gitmodules = repo_worktree_path(repo, GITMODULES_FILE);
588
589                 if (!is_gitmodules_unmerged(repo->index))
590                         git_config_from_file(gitmodules_cb, gitmodules, repo);
591
592                 free(gitmodules);
593         }
594
595         repo->submodule_cache->gitmodules_read = 1;
596 }
597
598 void gitmodules_config_oid(const struct object_id *commit_oid)
599 {
600         struct strbuf rev = STRBUF_INIT;
601         struct object_id oid;
602
603         submodule_cache_check_init(the_repository);
604
605         if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
606                 git_config_from_blob_oid(gitmodules_cb, rev.buf,
607                                          &oid, the_repository);
608         }
609         strbuf_release(&rev);
610
611         the_repository->submodule_cache->gitmodules_read = 1;
612 }
613
614 static void gitmodules_read_check(struct repository *repo)
615 {
616         submodule_cache_check_init(repo);
617
618         /* read the repo's .gitmodules file if it hasn't been already */
619         if (!repo->submodule_cache->gitmodules_read)
620                 repo_read_gitmodules(repo);
621 }
622
623 const struct submodule *submodule_from_name(const struct object_id *treeish_name,
624                 const char *name)
625 {
626         gitmodules_read_check(the_repository);
627         return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
628 }
629
630 const struct submodule *submodule_from_path(const struct object_id *treeish_name,
631                 const char *path)
632 {
633         gitmodules_read_check(the_repository);
634         return config_from(the_repository->submodule_cache, treeish_name, path, lookup_path);
635 }
636
637 const struct submodule *submodule_from_cache(struct repository *repo,
638                                              const struct object_id *treeish_name,
639                                              const char *key)
640 {
641         gitmodules_read_check(repo);
642         return config_from(repo->submodule_cache, treeish_name,
643                            key, lookup_path);
644 }
645
646 void submodule_free(void)
647 {
648         if (the_repository->submodule_cache)
649                 submodule_cache_clear(the_repository->submodule_cache);
650 }