]> git.proxmox.com Git - libgit2.git/blob - src/submodule.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / src / submodule.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "submodule.h"
9
10 #include "git2/config.h"
11 #include "git2/sys/config.h"
12 #include "git2/types.h"
13 #include "git2/index.h"
14 #include "buffer.h"
15 #include "vector.h"
16 #include "posix.h"
17 #include "config_backend.h"
18 #include "config.h"
19 #include "repository.h"
20 #include "tree.h"
21 #include "iterator.h"
22 #include "path.h"
23 #include "index.h"
24 #include "worktree.h"
25 #include "clone.h"
26
27 #define GIT_MODULES_FILE ".gitmodules"
28
29 static git_configmap _sm_update_map[] = {
30 {GIT_CONFIGMAP_STRING, "checkout", GIT_SUBMODULE_UPDATE_CHECKOUT},
31 {GIT_CONFIGMAP_STRING, "rebase", GIT_SUBMODULE_UPDATE_REBASE},
32 {GIT_CONFIGMAP_STRING, "merge", GIT_SUBMODULE_UPDATE_MERGE},
33 {GIT_CONFIGMAP_STRING, "none", GIT_SUBMODULE_UPDATE_NONE},
34 {GIT_CONFIGMAP_FALSE, NULL, GIT_SUBMODULE_UPDATE_NONE},
35 {GIT_CONFIGMAP_TRUE, NULL, GIT_SUBMODULE_UPDATE_CHECKOUT},
36 };
37
38 static git_configmap _sm_ignore_map[] = {
39 {GIT_CONFIGMAP_STRING, "none", GIT_SUBMODULE_IGNORE_NONE},
40 {GIT_CONFIGMAP_STRING, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED},
41 {GIT_CONFIGMAP_STRING, "dirty", GIT_SUBMODULE_IGNORE_DIRTY},
42 {GIT_CONFIGMAP_STRING, "all", GIT_SUBMODULE_IGNORE_ALL},
43 {GIT_CONFIGMAP_FALSE, NULL, GIT_SUBMODULE_IGNORE_NONE},
44 {GIT_CONFIGMAP_TRUE, NULL, GIT_SUBMODULE_IGNORE_ALL},
45 };
46
47 static git_configmap _sm_recurse_map[] = {
48 {GIT_CONFIGMAP_STRING, "on-demand", GIT_SUBMODULE_RECURSE_ONDEMAND},
49 {GIT_CONFIGMAP_FALSE, NULL, GIT_SUBMODULE_RECURSE_NO},
50 {GIT_CONFIGMAP_TRUE, NULL, GIT_SUBMODULE_RECURSE_YES},
51 };
52
53 enum {
54 CACHE_OK = 0,
55 CACHE_REFRESH = 1,
56 CACHE_FLUSH = 2
57 };
58 enum {
59 GITMODULES_EXISTING = 0,
60 GITMODULES_CREATE = 1,
61 };
62
63 static int submodule_alloc(git_submodule **out, git_repository *repo, const char *name);
64 static git_config_backend *open_gitmodules(git_repository *repo, int gitmod);
65 static int gitmodules_snapshot(git_config **snap, git_repository *repo);
66 static int get_url_base(git_buf *url, git_repository *repo);
67 static int lookup_head_remote_key(git_buf *remote_key, git_repository *repo);
68 static int lookup_default_remote(git_remote **remote, git_repository *repo);
69 static int submodule_load_each(const git_config_entry *entry, void *payload);
70 static int submodule_read_config(git_submodule *sm, git_config *cfg);
71 static int submodule_load_from_wd_lite(git_submodule *);
72 static void submodule_get_index_status(unsigned int *, git_submodule *);
73 static void submodule_get_wd_status(unsigned int *, git_submodule *, git_repository *, git_submodule_ignore_t);
74 static void submodule_update_from_index_entry(git_submodule *sm, const git_index_entry *ie);
75 static void submodule_update_from_head_data(git_submodule *sm, mode_t mode, const git_oid *id);
76
77 static int submodule_cmp(const void *a, const void *b)
78 {
79 return strcmp(((git_submodule *)a)->name, ((git_submodule *)b)->name);
80 }
81
82 static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix)
83 {
84 ssize_t idx = git_buf_rfind(key, '.');
85 git_buf_truncate(key, (size_t)(idx + 1));
86 return git_buf_puts(key, suffix);
87 }
88
89 /*
90 * PUBLIC APIS
91 */
92
93 static void submodule_set_lookup_error(int error, const char *name)
94 {
95 if (!error)
96 return;
97
98 git_error_set(GIT_ERROR_SUBMODULE, (error == GIT_ENOTFOUND) ?
99 "no submodule named '%s'" :
100 "submodule '%s' has not been added yet", name);
101 }
102
103 typedef struct {
104 const char *path;
105 char *name;
106 } fbp_data;
107
108 static int find_by_path(const git_config_entry *entry, void *payload)
109 {
110 fbp_data *data = payload;
111
112 if (!strcmp(entry->value, data->path)) {
113 const char *fdot, *ldot;
114 fdot = strchr(entry->name, '.');
115 ldot = strrchr(entry->name, '.');
116 data->name = git__strndup(fdot + 1, ldot - fdot - 1);
117 GIT_ERROR_CHECK_ALLOC(data->name);
118 }
119
120 return 0;
121 }
122
123 /*
124 * Checks to see if the submodule shares its name with a file or directory that
125 * already exists on the index. If so, the submodule cannot be added.
126 */
127 static int is_path_occupied(bool *occupied, git_repository *repo, const char *path)
128 {
129 int error = 0;
130 git_index *index;
131 git_buf dir = GIT_BUF_INIT;
132 *occupied = false;
133
134 if ((error = git_repository_index__weakptr(&index, repo)) < 0)
135 goto out;
136
137 if ((error = git_index_find(NULL, index, path)) != GIT_ENOTFOUND) {
138 if (!error) {
139 git_error_set(GIT_ERROR_SUBMODULE,
140 "File '%s' already exists in the index", path);
141 *occupied = true;
142 }
143 goto out;
144 }
145
146 if ((error = git_buf_sets(&dir, path)) < 0)
147 goto out;
148
149 if ((error = git_path_to_dir(&dir)) < 0)
150 goto out;
151
152 if ((error = git_index_find_prefix(NULL, index, dir.ptr)) != GIT_ENOTFOUND) {
153 if (!error) {
154 git_error_set(GIT_ERROR_SUBMODULE,
155 "Directory '%s' already exists in the index", path);
156 *occupied = true;
157 }
158 goto out;
159 }
160
161 error = 0;
162
163 out:
164 git_buf_dispose(&dir);
165 return error;
166 }
167
168 /**
169 * Release the name map returned by 'load_submodule_names'.
170 */
171 static void free_submodule_names(git_strmap *names)
172 {
173 const char *key;
174 char *value;
175
176 if (names == NULL)
177 return;
178
179 git_strmap_foreach(names, key, value, {
180 git__free((char *) key);
181 git__free(value);
182 });
183 git_strmap_free(names);
184
185 return;
186 }
187
188 /**
189 * Map submodule paths to names.
190 * TODO: for some use-cases, this might need case-folding on a
191 * case-insensitive filesystem
192 */
193 static int load_submodule_names(git_strmap **out, git_repository *repo, git_config *cfg)
194 {
195 const char *key = "submodule\\..*\\.path";
196 git_config_iterator *iter = NULL;
197 git_config_entry *entry;
198 git_buf buf = GIT_BUF_INIT;
199 git_strmap *names;
200 int isvalid, error;
201
202 *out = NULL;
203
204 if ((error = git_strmap_new(&names)) < 0)
205 goto out;
206
207 if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0)
208 goto out;
209
210 while ((error = git_config_next(&entry, iter)) == 0) {
211 const char *fdot, *ldot;
212 fdot = strchr(entry->name, '.');
213 ldot = strrchr(entry->name, '.');
214
215 if (git_strmap_exists(names, entry->value)) {
216 git_error_set(GIT_ERROR_SUBMODULE,
217 "duplicated submodule path '%s'", entry->value);
218 error = -1;
219 goto out;
220 }
221
222 git_buf_clear(&buf);
223 git_buf_put(&buf, fdot + 1, ldot - fdot - 1);
224 isvalid = git_submodule_name_is_valid(repo, buf.ptr, 0);
225 if (isvalid < 0) {
226 error = isvalid;
227 goto out;
228 }
229 if (!isvalid)
230 continue;
231
232 if ((error = git_strmap_set(names, git__strdup(entry->value), git_buf_detach(&buf))) < 0) {
233 git_error_set(GIT_ERROR_NOMEMORY, "error inserting submodule into hash table");
234 error = -1;
235 goto out;
236 }
237 }
238 if (error == GIT_ITEROVER)
239 error = 0;
240
241 *out = names;
242 names = NULL;
243
244 out:
245 free_submodule_names(names);
246 git_buf_dispose(&buf);
247 git_config_iterator_free(iter);
248 return error;
249 }
250
251 int git_submodule_cache_init(git_strmap **out, git_repository *repo)
252 {
253 int error = 0;
254 git_strmap *cache = NULL;
255 GIT_ASSERT_ARG(out);
256 GIT_ASSERT_ARG(repo);
257 if ((error = git_strmap_new(&cache)) < 0)
258 return error;
259 if ((error = git_submodule__map(repo, cache)) < 0) {
260 git_submodule_cache_free(cache);
261 return error;
262 }
263 *out = cache;
264 return error;
265 }
266
267 int git_submodule_cache_free(git_strmap *cache)
268 {
269 git_submodule *sm = NULL;
270 if (cache == NULL)
271 return 0;
272 git_strmap_foreach_value(cache, sm, {
273 git_submodule_free(sm);
274 });
275 git_strmap_free(cache);
276 return 0;
277 }
278
279 int git_submodule_lookup(
280 git_submodule **out, /* NULL if user only wants to test existence */
281 git_repository *repo,
282 const char *name) /* trailing slash is allowed */
283 {
284 return git_submodule__lookup_with_cache(out, repo, name, repo->submodule_cache);
285 }
286
287 int git_submodule__lookup_with_cache(
288 git_submodule **out, /* NULL if user only wants to test existence */
289 git_repository *repo,
290 const char *name, /* trailing slash is allowed */
291 git_strmap *cache)
292 {
293 int error;
294 unsigned int location;
295 git_submodule *sm;
296
297 GIT_ASSERT_ARG(repo);
298 GIT_ASSERT_ARG(name);
299
300 if (repo->is_bare) {
301 git_error_set(GIT_ERROR_SUBMODULE, "cannot get submodules without a working tree");
302 return -1;
303 }
304
305 if (cache != NULL) {
306 if ((sm = git_strmap_get(cache, name)) != NULL) {
307 if (out) {
308 *out = sm;
309 GIT_REFCOUNT_INC(*out);
310 }
311 return 0;
312 }
313 }
314
315 if ((error = submodule_alloc(&sm, repo, name)) < 0)
316 return error;
317
318 if ((error = git_submodule_reload(sm, false)) < 0) {
319 git_submodule_free(sm);
320 return error;
321 }
322
323 if ((error = git_submodule_location(&location, sm)) < 0) {
324 git_submodule_free(sm);
325 return error;
326 }
327
328 /* If it's not configured or we're looking by path */
329 if (location == 0 || location == GIT_SUBMODULE_STATUS_IN_WD) {
330 git_config_backend *mods;
331 const char *pattern = "submodule\\..*\\.path";
332 git_buf path = GIT_BUF_INIT;
333 fbp_data data = { NULL, NULL };
334
335 git_buf_puts(&path, name);
336 while (path.ptr[path.size-1] == '/') {
337 path.ptr[--path.size] = '\0';
338 }
339 data.path = path.ptr;
340
341 mods = open_gitmodules(repo, GITMODULES_EXISTING);
342
343 if (mods)
344 error = git_config_backend_foreach_match(mods, pattern, find_by_path, &data);
345
346 git_config_backend_free(mods);
347
348 if (error < 0) {
349 git_submodule_free(sm);
350 git_buf_dispose(&path);
351 return error;
352 }
353
354 if (data.name) {
355 git__free(sm->name);
356 sm->name = data.name;
357 sm->path = git_buf_detach(&path);
358
359 /* Try to load again with the right name */
360 if ((error = git_submodule_reload(sm, false)) < 0) {
361 git_submodule_free(sm);
362 return error;
363 }
364 }
365
366 git_buf_dispose(&path);
367 }
368
369 if ((error = git_submodule_location(&location, sm)) < 0) {
370 git_submodule_free(sm);
371 return error;
372 }
373
374 /* If we still haven't found it, do the WD check */
375 if (location == 0 || location == GIT_SUBMODULE_STATUS_IN_WD) {
376 git_submodule_free(sm);
377 error = GIT_ENOTFOUND;
378
379 /* If it's not configured, we still check if there's a repo at the path */
380 if (git_repository_workdir(repo)) {
381 git_buf path = GIT_BUF_INIT;
382 if (git_buf_join3(&path, '/',
383 git_repository_workdir(repo),
384 name, DOT_GIT) < 0 ||
385 git_path_validate_workdir_buf(NULL, &path) < 0)
386 return -1;
387
388 if (git_path_exists(path.ptr))
389 error = GIT_EEXISTS;
390
391 git_buf_dispose(&path);
392 }
393
394 submodule_set_lookup_error(error, name);
395 return error;
396 }
397
398 if (out)
399 *out = sm;
400 else
401 git_submodule_free(sm);
402
403 return 0;
404 }
405
406 int git_submodule_name_is_valid(git_repository *repo, const char *name, int flags)
407 {
408 git_buf buf = GIT_BUF_INIT;
409 int error, isvalid;
410
411 if (flags == 0)
412 flags = GIT_PATH_REJECT_FILESYSTEM_DEFAULTS;
413
414 /* Avoid allocating a new string if we can avoid it */
415 if (strchr(name, '\\') != NULL) {
416 if ((error = git_path_normalize_slashes(&buf, name)) < 0)
417 return error;
418 } else {
419 git_buf_attach_notowned(&buf, name, strlen(name));
420 }
421
422 isvalid = git_path_validate(repo, buf.ptr, 0, flags);
423 git_buf_dispose(&buf);
424
425 return isvalid;
426 }
427
428 static void submodule_free_dup(void *sm)
429 {
430 git_submodule_free(sm);
431 }
432
433 static int submodule_get_or_create(git_submodule **out, git_repository *repo, git_strmap *map, const char *name)
434 {
435 git_submodule *sm = NULL;
436 int error;
437
438 if ((sm = git_strmap_get(map, name)) != NULL)
439 goto done;
440
441 /* if the submodule doesn't exist yet in the map, create it */
442 if ((error = submodule_alloc(&sm, repo, name)) < 0)
443 return error;
444
445 if ((error = git_strmap_set(map, sm->name, sm)) < 0) {
446 git_submodule_free(sm);
447 return error;
448 }
449
450 done:
451 GIT_REFCOUNT_INC(sm);
452 *out = sm;
453 return 0;
454 }
455
456 static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cfg)
457 {
458 int error;
459 git_iterator *i = NULL;
460 const git_index_entry *entry;
461 git_strmap *names;
462
463 if ((error = load_submodule_names(&names, git_index_owner(idx), cfg)))
464 goto done;
465
466 if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0)
467 goto done;
468
469 while (!(error = git_iterator_advance(&entry, i))) {
470 git_submodule *sm;
471
472 if ((sm = git_strmap_get(map, entry->path)) != NULL) {
473 if (S_ISGITLINK(entry->mode))
474 submodule_update_from_index_entry(sm, entry);
475 else
476 sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE;
477 } else if (S_ISGITLINK(entry->mode)) {
478 const char *name;
479
480 if ((name = git_strmap_get(names, entry->path)) == NULL)
481 name = entry->path;
482
483 if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name)) {
484 submodule_update_from_index_entry(sm, entry);
485 git_submodule_free(sm);
486 }
487 }
488 }
489
490 if (error == GIT_ITEROVER)
491 error = 0;
492
493 done:
494 git_iterator_free(i);
495 free_submodule_names(names);
496
497 return error;
498 }
499
500 static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg)
501 {
502 int error;
503 git_iterator *i = NULL;
504 const git_index_entry *entry;
505 git_strmap *names;
506
507 if ((error = load_submodule_names(&names, git_tree_owner(head), cfg)))
508 goto done;
509
510 if ((error = git_iterator_for_tree(&i, head, NULL)) < 0)
511 goto done;
512
513 while (!(error = git_iterator_advance(&entry, i))) {
514 git_submodule *sm;
515
516 if ((sm = git_strmap_get(map, entry->path)) != NULL) {
517 if (S_ISGITLINK(entry->mode))
518 submodule_update_from_head_data(sm, entry->mode, &entry->id);
519 else
520 sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
521 } else if (S_ISGITLINK(entry->mode)) {
522 const char *name;
523
524 if ((name = git_strmap_get(names, entry->path)) == NULL)
525 name = entry->path;
526
527 if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name)) {
528 submodule_update_from_head_data(
529 sm, entry->mode, &entry->id);
530 git_submodule_free(sm);
531 }
532 }
533 }
534
535 if (error == GIT_ITEROVER)
536 error = 0;
537
538 done:
539 git_iterator_free(i);
540 free_submodule_names(names);
541
542 return error;
543 }
544
545 /* If have_sm is true, sm is populated, otherwise map an repo are. */
546 typedef struct {
547 git_config *mods;
548 git_strmap *map;
549 git_repository *repo;
550 } lfc_data;
551
552 int git_submodule__map(git_repository *repo, git_strmap *map)
553 {
554 int error = 0;
555 git_index *idx = NULL;
556 git_tree *head = NULL;
557 git_buf path = GIT_BUF_INIT;
558 git_submodule *sm;
559 git_config *mods = NULL;
560 bool has_workdir;
561
562 GIT_ASSERT_ARG(repo);
563 GIT_ASSERT_ARG(map);
564
565 /* get sources that we will need to check */
566 if (git_repository_index(&idx, repo) < 0)
567 git_error_clear();
568 if (git_repository_head_tree(&head, repo) < 0)
569 git_error_clear();
570
571 has_workdir = git_repository_workdir(repo) != NULL;
572
573 if (has_workdir &&
574 (error = git_repository_workdir_path(&path, repo, GIT_MODULES_FILE)) < 0)
575 goto cleanup;
576
577 /* add submodule information from .gitmodules */
578 if (has_workdir) {
579 lfc_data data = { 0 };
580 data.map = map;
581 data.repo = repo;
582
583 if ((error = gitmodules_snapshot(&mods, repo)) < 0) {
584 if (error == GIT_ENOTFOUND)
585 error = 0;
586 goto cleanup;
587 }
588
589 data.mods = mods;
590 if ((error = git_config_foreach(
591 mods, submodule_load_each, &data)) < 0)
592 goto cleanup;
593 }
594 /* add back submodule information from index */
595 if (mods && idx) {
596 if ((error = submodules_from_index(map, idx, mods)) < 0)
597 goto cleanup;
598 }
599 /* add submodule information from HEAD */
600 if (mods && head) {
601 if ((error = submodules_from_head(map, head, mods)) < 0)
602 goto cleanup;
603 }
604 /* shallow scan submodules in work tree as needed */
605 if (has_workdir) {
606 git_strmap_foreach_value(map, sm, {
607 submodule_load_from_wd_lite(sm);
608 });
609 }
610
611 cleanup:
612 git_config_free(mods);
613 /* TODO: if we got an error, mark submodule config as invalid? */
614 git_index_free(idx);
615 git_tree_free(head);
616 git_buf_dispose(&path);
617 return error;
618 }
619
620 int git_submodule_foreach(
621 git_repository *repo,
622 git_submodule_cb callback,
623 void *payload)
624 {
625 git_vector snapshot = GIT_VECTOR_INIT;
626 git_strmap *submodules;
627 git_submodule *sm;
628 int error;
629 size_t i;
630
631 if (repo->is_bare) {
632 git_error_set(GIT_ERROR_SUBMODULE, "cannot get submodules without a working tree");
633 return -1;
634 }
635
636 if ((error = git_strmap_new(&submodules)) < 0)
637 return error;
638
639 if ((error = git_submodule__map(repo, submodules)) < 0)
640 goto done;
641
642 if (!(error = git_vector_init(
643 &snapshot, git_strmap_size(submodules), submodule_cmp))) {
644
645 git_strmap_foreach_value(submodules, sm, {
646 if ((error = git_vector_insert(&snapshot, sm)) < 0)
647 break;
648 GIT_REFCOUNT_INC(sm);
649 });
650 }
651
652 if (error < 0)
653 goto done;
654
655 git_vector_uniq(&snapshot, submodule_free_dup);
656
657 git_vector_foreach(&snapshot, i, sm) {
658 if ((error = callback(sm, sm->name, payload)) != 0) {
659 git_error_set_after_callback(error);
660 break;
661 }
662 }
663
664 done:
665 git_vector_foreach(&snapshot, i, sm)
666 git_submodule_free(sm);
667 git_vector_free(&snapshot);
668
669 git_strmap_foreach_value(submodules, sm, {
670 git_submodule_free(sm);
671 });
672 git_strmap_free(submodules);
673
674 return error;
675 }
676
677 static int submodule_repo_init(
678 git_repository **out,
679 git_repository *parent_repo,
680 const char *path,
681 const char *url,
682 bool use_gitlink)
683 {
684 int error = 0;
685 git_buf workdir = GIT_BUF_INIT, repodir = GIT_BUF_INIT;
686 git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
687 git_repository *subrepo = NULL;
688
689 error = git_repository_workdir_path(&workdir, parent_repo, path);
690 if (error < 0)
691 goto cleanup;
692
693 initopt.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_REINIT;
694 initopt.origin_url = url;
695
696 /* init submodule repository and add origin remote as needed */
697
698 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
699 * gitlink in the sub-repo workdir directory to that repository
700 *
701 * Old style: sub-repo goes directly into repo/<name>/.git/
702 */
703 if (use_gitlink) {
704 error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
705 if (error < 0)
706 goto cleanup;
707 error = git_buf_joinpath(&repodir, repodir.ptr, path);
708 if (error < 0)
709 goto cleanup;
710
711 initopt.workdir_path = workdir.ptr;
712 initopt.flags |=
713 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR |
714 GIT_REPOSITORY_INIT_RELATIVE_GITLINK;
715
716 error = git_repository_init_ext(&subrepo, repodir.ptr, &initopt);
717 } else
718 error = git_repository_init_ext(&subrepo, workdir.ptr, &initopt);
719
720 cleanup:
721 git_buf_dispose(&workdir);
722 git_buf_dispose(&repodir);
723
724 *out = subrepo;
725
726 return error;
727 }
728
729 int git_submodule_add_setup(
730 git_submodule **out,
731 git_repository *repo,
732 const char *url,
733 const char *path,
734 int use_gitlink)
735 {
736 int error = 0;
737 git_config_backend *mods = NULL;
738 git_submodule *sm = NULL;
739 git_buf name = GIT_BUF_INIT, real_url = GIT_BUF_INIT;
740 git_repository *subrepo = NULL;
741 bool path_occupied;
742
743 GIT_ASSERT_ARG(repo);
744 GIT_ASSERT_ARG(url);
745 GIT_ASSERT_ARG(path);
746
747 /* see if there is already an entry for this submodule */
748
749 if (git_submodule_lookup(NULL, repo, path) < 0)
750 git_error_clear();
751 else {
752 git_error_set(GIT_ERROR_SUBMODULE,
753 "attempt to add submodule '%s' that already exists", path);
754 return GIT_EEXISTS;
755 }
756
757 /* validate and normalize path */
758
759 if (git__prefixcmp(path, git_repository_workdir(repo)) == 0)
760 path += strlen(git_repository_workdir(repo));
761
762 if (git_path_root(path) >= 0) {
763 git_error_set(GIT_ERROR_SUBMODULE, "submodule path must be a relative path");
764 error = -1;
765 goto cleanup;
766 }
767
768 if ((error = is_path_occupied(&path_occupied, repo, path)) < 0)
769 goto cleanup;
770
771 if (path_occupied) {
772 error = GIT_EEXISTS;
773 goto cleanup;
774 }
775
776 /* update .gitmodules */
777
778 if (!(mods = open_gitmodules(repo, GITMODULES_CREATE))) {
779 git_error_set(GIT_ERROR_SUBMODULE,
780 "adding submodules to a bare repository is not supported");
781 return -1;
782 }
783
784 if ((error = git_buf_printf(&name, "submodule.%s.path", path)) < 0 ||
785 (error = git_config_backend_set_string(mods, name.ptr, path)) < 0)
786 goto cleanup;
787
788 if ((error = submodule_config_key_trunc_puts(&name, "url")) < 0 ||
789 (error = git_config_backend_set_string(mods, name.ptr, url)) < 0)
790 goto cleanup;
791
792 git_buf_clear(&name);
793
794 /* init submodule repository and add origin remote as needed */
795
796 error = git_repository_workdir_path(&name, repo, path);
797 if (error < 0)
798 goto cleanup;
799
800 /* if the repo does not already exist, then init a new repo and add it.
801 * Otherwise, just add the existing repo.
802 */
803 if (!(git_path_exists(name.ptr) &&
804 git_path_contains(&name, DOT_GIT))) {
805
806 /* resolve the actual URL to use */
807 if ((error = git_submodule_resolve_url(&real_url, repo, url)) < 0)
808 goto cleanup;
809
810 if ((error = submodule_repo_init(&subrepo, repo, path, real_url.ptr, use_gitlink)) < 0)
811 goto cleanup;
812 }
813
814 if ((error = git_submodule_lookup(&sm, repo, path)) < 0)
815 goto cleanup;
816
817 error = git_submodule_init(sm, false);
818
819 cleanup:
820 if (error && sm) {
821 git_submodule_free(sm);
822 sm = NULL;
823 }
824 if (out != NULL)
825 *out = sm;
826
827 git_config_backend_free(mods);
828 git_repository_free(subrepo);
829 git_buf_dispose(&real_url);
830 git_buf_dispose(&name);
831
832 return error;
833 }
834
835 int git_submodule_repo_init(
836 git_repository **out,
837 const git_submodule *sm,
838 int use_gitlink)
839 {
840 int error;
841 git_repository *sub_repo = NULL;
842 const char *configured_url;
843 git_config *cfg = NULL;
844 git_buf buf = GIT_BUF_INIT;
845
846 GIT_ASSERT_ARG(out);
847 GIT_ASSERT_ARG(sm);
848
849 /* get the configured remote url of the submodule */
850 if ((error = git_buf_printf(&buf, "submodule.%s.url", sm->name)) < 0 ||
851 (error = git_repository_config_snapshot(&cfg, sm->repo)) < 0 ||
852 (error = git_config_get_string(&configured_url, cfg, buf.ptr)) < 0 ||
853 (error = submodule_repo_init(&sub_repo, sm->repo, sm->path, configured_url, use_gitlink)) < 0)
854 goto done;
855
856 *out = sub_repo;
857
858 done:
859 git_config_free(cfg);
860 git_buf_dispose(&buf);
861 return error;
862 }
863
864 static int clone_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
865 {
866 GIT_UNUSED(url);
867 GIT_UNUSED(payload);
868 return git_remote_lookup(out, repo, name);
869 }
870
871 static int clone_return_repo(git_repository **out, const char *path, int bare, void *payload)
872 {
873 git_submodule *sm = payload;
874
875 GIT_UNUSED(path);
876 GIT_UNUSED(bare);
877 return git_submodule_open(out, sm);
878 }
879
880 int git_submodule_clone(git_repository **out, git_submodule *submodule, const git_submodule_update_options *given_opts)
881 {
882 int error;
883 git_repository *clone;
884 git_buf rel_path = GIT_BUF_INIT;
885 git_submodule_update_options sub_opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
886 git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
887
888 GIT_ASSERT_ARG(submodule);
889
890 if (given_opts)
891 memcpy(&sub_opts, given_opts, sizeof(sub_opts));
892
893 GIT_ERROR_CHECK_VERSION(&sub_opts, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, "git_submodule_update_options");
894
895 memcpy(&opts.checkout_opts, &sub_opts.checkout_opts, sizeof(sub_opts.checkout_opts));
896 memcpy(&opts.fetch_opts, &sub_opts.fetch_opts, sizeof(sub_opts.fetch_opts));
897 opts.repository_cb = clone_return_repo;
898 opts.repository_cb_payload = submodule;
899 opts.remote_cb = clone_return_origin;
900 opts.remote_cb_payload = submodule;
901
902 error = git_repository_workdir_path(&rel_path, git_submodule_owner(submodule), git_submodule_path(submodule));
903 if (error < 0)
904 goto cleanup;
905
906 error = git_clone__submodule(&clone, git_submodule_url(submodule), git_buf_cstr(&rel_path), &opts);
907 if (error < 0)
908 goto cleanup;
909
910 if (!out)
911 git_repository_free(clone);
912 else
913 *out = clone;
914
915 cleanup:
916 git_buf_dispose(&rel_path);
917
918 return error;
919 }
920
921 int git_submodule_add_finalize(git_submodule *sm)
922 {
923 int error;
924 git_index *index;
925
926 GIT_ASSERT_ARG(sm);
927
928 if ((error = git_repository_index__weakptr(&index, sm->repo)) < 0 ||
929 (error = git_index_add_bypath(index, GIT_MODULES_FILE)) < 0)
930 return error;
931
932 return git_submodule_add_to_index(sm, true);
933 }
934
935 int git_submodule_add_to_index(git_submodule *sm, int write_index)
936 {
937 int error;
938 git_repository *sm_repo = NULL;
939 git_index *index;
940 git_buf path = GIT_BUF_INIT;
941 git_commit *head;
942 git_index_entry entry;
943 struct stat st;
944
945 GIT_ASSERT_ARG(sm);
946
947 /* force reload of wd OID by git_submodule_open */
948 sm->flags = sm->flags & ~GIT_SUBMODULE_STATUS__WD_OID_VALID;
949
950 if ((error = git_repository_index__weakptr(&index, sm->repo)) < 0 ||
951 (error = git_repository_workdir_path(&path, sm->repo, sm->path)) < 0 ||
952 (error = git_submodule_open(&sm_repo, sm)) < 0)
953 goto cleanup;
954
955 /* read stat information for submodule working directory */
956 if (p_stat(path.ptr, &st) < 0) {
957 git_error_set(GIT_ERROR_SUBMODULE,
958 "cannot add submodule without working directory");
959 error = -1;
960 goto cleanup;
961 }
962
963 memset(&entry, 0, sizeof(entry));
964 entry.path = sm->path;
965 git_index_entry__init_from_stat(
966 &entry, &st, !(git_index_caps(index) & GIT_INDEX_CAPABILITY_NO_FILEMODE));
967
968 /* calling git_submodule_open will have set sm->wd_oid if possible */
969 if ((sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) == 0) {
970 git_error_set(GIT_ERROR_SUBMODULE,
971 "cannot add submodule without HEAD to index");
972 error = -1;
973 goto cleanup;
974 }
975 git_oid_cpy(&entry.id, &sm->wd_oid);
976
977 if ((error = git_commit_lookup(&head, sm_repo, &sm->wd_oid)) < 0)
978 goto cleanup;
979
980 entry.ctime.seconds = (int32_t)git_commit_time(head);
981 entry.ctime.nanoseconds = 0;
982 entry.mtime.seconds = (int32_t)git_commit_time(head);
983 entry.mtime.nanoseconds = 0;
984
985 git_commit_free(head);
986
987 /* add it */
988 error = git_index_add(index, &entry);
989
990 /* write it, if requested */
991 if (!error && write_index) {
992 error = git_index_write(index);
993
994 if (!error)
995 git_oid_cpy(&sm->index_oid, &sm->wd_oid);
996 }
997
998 cleanup:
999 git_repository_free(sm_repo);
1000 git_buf_dispose(&path);
1001 return error;
1002 }
1003
1004 static const char *submodule_update_to_str(git_submodule_update_t update)
1005 {
1006 int i;
1007 for (i = 0; i < (int)ARRAY_SIZE(_sm_update_map); ++i)
1008 if (_sm_update_map[i].map_value == (int)update)
1009 return _sm_update_map[i].str_match;
1010 return NULL;
1011 }
1012
1013 git_repository *git_submodule_owner(git_submodule *submodule)
1014 {
1015 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1016 return submodule->repo;
1017 }
1018
1019 const char *git_submodule_name(git_submodule *submodule)
1020 {
1021 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1022 return submodule->name;
1023 }
1024
1025 const char *git_submodule_path(git_submodule *submodule)
1026 {
1027 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1028 return submodule->path;
1029 }
1030
1031 const char *git_submodule_url(git_submodule *submodule)
1032 {
1033 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1034 return submodule->url;
1035 }
1036
1037 int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url)
1038 {
1039 int error = 0;
1040 git_buf normalized = GIT_BUF_INIT;
1041
1042 GIT_ASSERT_ARG(out);
1043 GIT_ASSERT_ARG(repo);
1044 GIT_ASSERT_ARG(url);
1045
1046 if ((error = git_buf_sanitize(out)) < 0)
1047 return error;
1048
1049 /* We do this in all platforms in case someone on Windows created the .gitmodules */
1050 if (strchr(url, '\\')) {
1051 if ((error = git_path_normalize_slashes(&normalized, url)) < 0)
1052 return error;
1053
1054 url = normalized.ptr;
1055 }
1056
1057
1058 if (git_path_is_relative(url)) {
1059 if (!(error = get_url_base(out, repo)))
1060 error = git_path_apply_relative(out, url);
1061 } else if (strchr(url, ':') != NULL || url[0] == '/') {
1062 error = git_buf_sets(out, url);
1063 } else {
1064 git_error_set(GIT_ERROR_SUBMODULE, "invalid format for submodule URL");
1065 error = -1;
1066 }
1067
1068 git_buf_dispose(&normalized);
1069 return error;
1070 }
1071
1072 static int write_var(git_repository *repo, const char *name, const char *var, const char *val)
1073 {
1074 git_buf key = GIT_BUF_INIT;
1075 git_config_backend *mods;
1076 int error;
1077
1078 mods = open_gitmodules(repo, GITMODULES_CREATE);
1079 if (!mods)
1080 return -1;
1081
1082 if ((error = git_buf_printf(&key, "submodule.%s.%s", name, var)) < 0)
1083 goto cleanup;
1084
1085 if (val)
1086 error = git_config_backend_set_string(mods, key.ptr, val);
1087 else
1088 error = git_config_backend_delete(mods, key.ptr);
1089
1090 git_buf_dispose(&key);
1091
1092 cleanup:
1093 git_config_backend_free(mods);
1094 return error;
1095 }
1096
1097 static int write_mapped_var(git_repository *repo, const char *name, git_configmap *maps, size_t nmaps, const char *var, int ival)
1098 {
1099 git_configmap_t type;
1100 const char *val;
1101
1102 if (git_config_lookup_map_enum(&type, &val, maps, nmaps, ival) < 0) {
1103 git_error_set(GIT_ERROR_SUBMODULE, "invalid value for %s", var);
1104 return -1;
1105 }
1106
1107 if (type == GIT_CONFIGMAP_TRUE)
1108 val = "true";
1109
1110 return write_var(repo, name, var, val);
1111 }
1112
1113 const char *git_submodule_branch(git_submodule *submodule)
1114 {
1115 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1116 return submodule->branch;
1117 }
1118
1119 int git_submodule_set_branch(git_repository *repo, const char *name, const char *branch)
1120 {
1121 GIT_ASSERT_ARG(repo);
1122 GIT_ASSERT_ARG(name);
1123
1124 return write_var(repo, name, "branch", branch);
1125 }
1126
1127 int git_submodule_set_url(git_repository *repo, const char *name, const char *url)
1128 {
1129 GIT_ASSERT_ARG(repo);
1130 GIT_ASSERT_ARG(name);
1131 GIT_ASSERT_ARG(url);
1132
1133 return write_var(repo, name, "url", url);
1134 }
1135
1136 const git_oid *git_submodule_index_id(git_submodule *submodule)
1137 {
1138 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1139
1140 if (submodule->flags & GIT_SUBMODULE_STATUS__INDEX_OID_VALID)
1141 return &submodule->index_oid;
1142 else
1143 return NULL;
1144 }
1145
1146 const git_oid *git_submodule_head_id(git_submodule *submodule)
1147 {
1148 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1149
1150 if (submodule->flags & GIT_SUBMODULE_STATUS__HEAD_OID_VALID)
1151 return &submodule->head_oid;
1152 else
1153 return NULL;
1154 }
1155
1156 const git_oid *git_submodule_wd_id(git_submodule *submodule)
1157 {
1158 GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
1159
1160 /* load unless we think we have a valid oid */
1161 if (!(submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)) {
1162 git_repository *subrepo;
1163
1164 /* calling submodule open grabs the HEAD OID if possible */
1165 if (!git_submodule_open_bare(&subrepo, submodule))
1166 git_repository_free(subrepo);
1167 else
1168 git_error_clear();
1169 }
1170
1171 if (submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)
1172 return &submodule->wd_oid;
1173 else
1174 return NULL;
1175 }
1176
1177 git_submodule_ignore_t git_submodule_ignore(git_submodule *submodule)
1178 {
1179 GIT_ASSERT_ARG_WITH_RETVAL(submodule, GIT_SUBMODULE_IGNORE_UNSPECIFIED);
1180
1181 return (submodule->ignore < GIT_SUBMODULE_IGNORE_NONE) ?
1182 GIT_SUBMODULE_IGNORE_NONE : submodule->ignore;
1183 }
1184
1185 int git_submodule_set_ignore(git_repository *repo, const char *name, git_submodule_ignore_t ignore)
1186 {
1187 GIT_ASSERT_ARG(repo);
1188 GIT_ASSERT_ARG(name);
1189
1190 return write_mapped_var(repo, name, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), "ignore", ignore);
1191 }
1192
1193 git_submodule_update_t git_submodule_update_strategy(git_submodule *submodule)
1194 {
1195 GIT_ASSERT_ARG_WITH_RETVAL(submodule, GIT_SUBMODULE_UPDATE_NONE);
1196
1197 return (submodule->update < GIT_SUBMODULE_UPDATE_CHECKOUT) ?
1198 GIT_SUBMODULE_UPDATE_CHECKOUT : submodule->update;
1199 }
1200
1201 int git_submodule_set_update(git_repository *repo, const char *name, git_submodule_update_t update)
1202 {
1203 GIT_ASSERT_ARG(repo);
1204 GIT_ASSERT_ARG(name);
1205
1206 return write_mapped_var(repo, name, _sm_update_map, ARRAY_SIZE(_sm_update_map), "update", update);
1207 }
1208
1209 git_submodule_recurse_t git_submodule_fetch_recurse_submodules(
1210 git_submodule *submodule)
1211 {
1212 GIT_ASSERT_ARG_WITH_RETVAL(submodule, GIT_SUBMODULE_RECURSE_NO);
1213 return submodule->fetch_recurse;
1214 }
1215
1216 int git_submodule_set_fetch_recurse_submodules(git_repository *repo, const char *name, git_submodule_recurse_t recurse)
1217 {
1218 GIT_ASSERT_ARG(repo);
1219 GIT_ASSERT_ARG(name);
1220
1221 return write_mapped_var(repo, name, _sm_recurse_map, ARRAY_SIZE(_sm_recurse_map), "fetchRecurseSubmodules", recurse);
1222 }
1223
1224 static int submodule_repo_create(
1225 git_repository **out,
1226 git_repository *parent_repo,
1227 const char *path)
1228 {
1229 int error = 0;
1230 git_buf workdir = GIT_BUF_INIT, repodir = GIT_BUF_INIT;
1231 git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
1232 git_repository *subrepo = NULL;
1233
1234 initopt.flags =
1235 GIT_REPOSITORY_INIT_MKPATH |
1236 GIT_REPOSITORY_INIT_NO_REINIT |
1237 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR |
1238 GIT_REPOSITORY_INIT_RELATIVE_GITLINK;
1239
1240 /* Workdir: path to sub-repo working directory */
1241 error = git_repository_workdir_path(&workdir, parent_repo, path);
1242 if (error < 0)
1243 goto cleanup;
1244
1245 initopt.workdir_path = workdir.ptr;
1246
1247 /**
1248 * Repodir: path to the sub-repo. sub-repo goes in:
1249 * <repo-dir>/modules/<name>/ with a gitlink in the
1250 * sub-repo workdir directory to that repository.
1251 */
1252 error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
1253 if (error < 0)
1254 goto cleanup;
1255 error = git_buf_joinpath(&repodir, repodir.ptr, path);
1256 if (error < 0)
1257 goto cleanup;
1258
1259 error = git_repository_init_ext(&subrepo, repodir.ptr, &initopt);
1260
1261 cleanup:
1262 git_buf_dispose(&workdir);
1263 git_buf_dispose(&repodir);
1264
1265 *out = subrepo;
1266
1267 return error;
1268 }
1269
1270 /**
1271 * Callback to override sub-repository creation when
1272 * cloning a sub-repository.
1273 */
1274 static int git_submodule_update_repo_init_cb(
1275 git_repository **out,
1276 const char *path,
1277 int bare,
1278 void *payload)
1279 {
1280 git_submodule *sm;
1281
1282 GIT_UNUSED(bare);
1283
1284 sm = payload;
1285
1286 return submodule_repo_create(out, sm->repo, path);
1287 }
1288
1289 int git_submodule_update_options_init(git_submodule_update_options *opts, unsigned int version)
1290 {
1291 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1292 opts, version, git_submodule_update_options, GIT_SUBMODULE_UPDATE_OPTIONS_INIT);
1293 return 0;
1294 }
1295
1296 #ifndef GIT_DEPRECATE_HARD
1297 int git_submodule_update_init_options(git_submodule_update_options *opts, unsigned int version)
1298 {
1299 return git_submodule_update_options_init(opts, version);
1300 }
1301 #endif
1302
1303 int git_submodule_update(git_submodule *sm, int init, git_submodule_update_options *_update_options)
1304 {
1305 int error;
1306 unsigned int submodule_status;
1307 git_config *config = NULL;
1308 const char *submodule_url;
1309 git_repository *sub_repo = NULL;
1310 git_remote *remote = NULL;
1311 git_object *target_commit = NULL;
1312 git_buf buf = GIT_BUF_INIT;
1313 git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
1314 git_clone_options clone_options = GIT_CLONE_OPTIONS_INIT;
1315
1316 GIT_ASSERT_ARG(sm);
1317
1318 if (_update_options)
1319 memcpy(&update_options, _update_options, sizeof(git_submodule_update_options));
1320
1321 GIT_ERROR_CHECK_VERSION(&update_options, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, "git_submodule_update_options");
1322
1323 /* Copy over the remote callbacks */
1324 memcpy(&clone_options.fetch_opts, &update_options.fetch_opts, sizeof(git_fetch_options));
1325
1326 /* Get the status of the submodule to determine if it is already initialized */
1327 if ((error = git_submodule_status(&submodule_status, sm->repo, sm->name, GIT_SUBMODULE_IGNORE_UNSPECIFIED)) < 0)
1328 goto done;
1329
1330 /*
1331 * If submodule work dir is not already initialized, check to see
1332 * what we need to do (initialize, clone, return error...)
1333 */
1334 if (submodule_status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) {
1335 /*
1336 * Work dir is not initialized, check to see if the submodule
1337 * info has been copied into .git/config
1338 */
1339 if ((error = git_repository_config_snapshot(&config, sm->repo)) < 0 ||
1340 (error = git_buf_printf(&buf, "submodule.%s.url", git_submodule_name(sm))) < 0)
1341 goto done;
1342
1343 if ((error = git_config_get_string(&submodule_url, config, git_buf_cstr(&buf))) < 0) {
1344 /*
1345 * If the error is not "not found" or if it is "not found" and we are not
1346 * initializing the submodule, then return error.
1347 */
1348 if (error != GIT_ENOTFOUND)
1349 goto done;
1350
1351 if (!init) {
1352 git_error_set(GIT_ERROR_SUBMODULE, "submodule is not initialized");
1353 error = GIT_ERROR;
1354 goto done;
1355 }
1356
1357 /* The submodule has not been initialized yet - initialize it now.*/
1358 if ((error = git_submodule_init(sm, 0)) < 0)
1359 goto done;
1360
1361 git_config_free(config);
1362 config = NULL;
1363
1364 if ((error = git_repository_config_snapshot(&config, sm->repo)) < 0 ||
1365 (error = git_config_get_string(&submodule_url, config, git_buf_cstr(&buf))) < 0)
1366 goto done;
1367 }
1368
1369 /** submodule is initialized - now clone it **/
1370 /* override repo creation */
1371 clone_options.repository_cb = git_submodule_update_repo_init_cb;
1372 clone_options.repository_cb_payload = sm;
1373
1374 /*
1375 * Do not perform checkout as part of clone, instead we
1376 * will checkout the specific commit manually.
1377 */
1378 clone_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
1379
1380 if ((error = git_clone(&sub_repo, submodule_url, sm->path, &clone_options)) < 0 ||
1381 (error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0 ||
1382 (error = git_checkout_head(sub_repo, &update_options.checkout_opts)) != 0)
1383 goto done;
1384 } else {
1385 const git_oid *oid;
1386
1387 /**
1388 * Work dir is initialized - look up the commit in the parent repository's index,
1389 * update the workdir contents of the subrepository, and set the subrepository's
1390 * head to the new commit.
1391 */
1392 if ((error = git_submodule_open(&sub_repo, sm)) < 0)
1393 goto done;
1394
1395 if ((oid = git_submodule_index_id(sm)) == NULL) {
1396 git_error_set(GIT_ERROR_SUBMODULE, "could not get ID of submodule in index");
1397 error = -1;
1398 goto done;
1399 }
1400
1401 /* Look up the target commit in the submodule. */
1402 if ((error = git_object_lookup(&target_commit, sub_repo, oid, GIT_OBJECT_COMMIT)) < 0) {
1403 /* If it isn't found then fetch and try again. */
1404 if (error != GIT_ENOTFOUND || !update_options.allow_fetch ||
1405 (error = lookup_default_remote(&remote, sub_repo)) < 0 ||
1406 (error = git_remote_fetch(remote, NULL, &update_options.fetch_opts, NULL)) < 0 ||
1407 (error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJECT_COMMIT)) < 0)
1408 goto done;
1409 }
1410
1411 if ((error = git_checkout_tree(sub_repo, target_commit, &update_options.checkout_opts)) != 0 ||
1412 (error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0)
1413 goto done;
1414
1415 /* Invalidate the wd flags as the workdir has been updated. */
1416 sm->flags = sm->flags &
1417 ~(GIT_SUBMODULE_STATUS_IN_WD |
1418 GIT_SUBMODULE_STATUS__WD_OID_VALID |
1419 GIT_SUBMODULE_STATUS__WD_SCANNED);
1420 }
1421
1422 done:
1423 git_buf_dispose(&buf);
1424 git_config_free(config);
1425 git_object_free(target_commit);
1426 git_remote_free(remote);
1427 git_repository_free(sub_repo);
1428
1429 return error;
1430 }
1431
1432 int git_submodule_init(git_submodule *sm, int overwrite)
1433 {
1434 int error;
1435 const char *val;
1436 git_buf key = GIT_BUF_INIT, effective_submodule_url = GIT_BUF_INIT;
1437 git_config *cfg = NULL;
1438
1439 if (!sm->url) {
1440 git_error_set(GIT_ERROR_SUBMODULE,
1441 "no URL configured for submodule '%s'", sm->name);
1442 return -1;
1443 }
1444
1445 if ((error = git_repository_config(&cfg, sm->repo)) < 0)
1446 return error;
1447
1448 /* write "submodule.NAME.url" */
1449
1450 if ((error = git_submodule_resolve_url(&effective_submodule_url, sm->repo, sm->url)) < 0 ||
1451 (error = git_buf_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
1452 (error = git_config__update_entry(
1453 cfg, key.ptr, effective_submodule_url.ptr, overwrite != 0, false)) < 0)
1454 goto cleanup;
1455
1456 /* write "submodule.NAME.update" if not default */
1457
1458 val = (sm->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ?
1459 NULL : submodule_update_to_str(sm->update);
1460
1461 if ((error = git_buf_printf(&key, "submodule.%s.update", sm->name)) < 0 ||
1462 (error = git_config__update_entry(
1463 cfg, key.ptr, val, overwrite != 0, false)) < 0)
1464 goto cleanup;
1465
1466 /* success */
1467
1468 cleanup:
1469 git_config_free(cfg);
1470 git_buf_dispose(&key);
1471 git_buf_dispose(&effective_submodule_url);
1472
1473 return error;
1474 }
1475
1476 int git_submodule_sync(git_submodule *sm)
1477 {
1478 git_buf key = GIT_BUF_INIT, url = GIT_BUF_INIT, remote_name = GIT_BUF_INIT;
1479 git_repository *smrepo = NULL;
1480 git_config *cfg = NULL;
1481 int error = 0;
1482
1483 if (!sm->url) {
1484 git_error_set(GIT_ERROR_SUBMODULE, "no URL configured for submodule '%s'", sm->name);
1485 return -1;
1486 }
1487
1488 /* copy URL over to config only if it already exists */
1489 if ((error = git_repository_config__weakptr(&cfg, sm->repo)) < 0 ||
1490 (error = git_buf_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
1491 (error = git_submodule_resolve_url(&url, sm->repo, sm->url)) < 0 ||
1492 (error = git_config__update_entry(cfg, key.ptr, url.ptr, true, true)) < 0)
1493 goto out;
1494
1495 if (!(sm->flags & GIT_SUBMODULE_STATUS_IN_WD))
1496 goto out;
1497
1498 /* if submodule exists in the working directory, update remote url */
1499 if ((error = git_submodule_open(&smrepo, sm)) < 0 ||
1500 (error = git_repository_config__weakptr(&cfg, smrepo)) < 0)
1501 goto out;
1502
1503 if (lookup_head_remote_key(&remote_name, smrepo) == 0) {
1504 if ((error = git_buf_join3(&key, '.', "remote", remote_name.ptr, "url")) < 0)
1505 goto out;
1506 } else if ((error = git_buf_sets(&key, "remote.origin.url")) < 0) {
1507 goto out;
1508 }
1509
1510 if ((error = git_config__update_entry(cfg, key.ptr, url.ptr, true, false)) < 0)
1511 goto out;
1512
1513 out:
1514 git_repository_free(smrepo);
1515 git_buf_dispose(&remote_name);
1516 git_buf_dispose(&key);
1517 git_buf_dispose(&url);
1518 return error;
1519 }
1520
1521 static int git_submodule__open(
1522 git_repository **subrepo, git_submodule *sm, bool bare)
1523 {
1524 int error;
1525 git_buf path = GIT_BUF_INIT;
1526 unsigned int flags = GIT_REPOSITORY_OPEN_NO_SEARCH;
1527 const char *wd;
1528
1529 GIT_ASSERT_ARG(sm);
1530 GIT_ASSERT_ARG(subrepo);
1531
1532 if (git_repository__ensure_not_bare(
1533 sm->repo, "open submodule repository") < 0)
1534 return GIT_EBAREREPO;
1535
1536 wd = git_repository_workdir(sm->repo);
1537
1538 if (git_buf_join3(&path, '/', wd, sm->path, DOT_GIT) < 0)
1539 return -1;
1540
1541 sm->flags = sm->flags &
1542 ~(GIT_SUBMODULE_STATUS_IN_WD |
1543 GIT_SUBMODULE_STATUS__WD_OID_VALID |
1544 GIT_SUBMODULE_STATUS__WD_SCANNED);
1545
1546 if (bare)
1547 flags |= GIT_REPOSITORY_OPEN_BARE;
1548
1549 error = git_repository_open_ext(subrepo, path.ptr, flags, wd);
1550
1551 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1552 if (!error) {
1553 sm->flags |= GIT_SUBMODULE_STATUS_IN_WD |
1554 GIT_SUBMODULE_STATUS__WD_SCANNED;
1555
1556 if (!git_reference_name_to_id(&sm->wd_oid, *subrepo, GIT_HEAD_FILE))
1557 sm->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID;
1558 else
1559 git_error_clear();
1560 } else if (git_path_exists(path.ptr)) {
1561 sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED |
1562 GIT_SUBMODULE_STATUS_IN_WD;
1563 } else {
1564 git_buf_rtruncate_at_char(&path, '/'); /* remove "/.git" */
1565
1566 if (git_path_isdir(path.ptr))
1567 sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED;
1568 }
1569
1570 git_buf_dispose(&path);
1571
1572 return error;
1573 }
1574
1575 int git_submodule_open_bare(git_repository **subrepo, git_submodule *sm)
1576 {
1577 return git_submodule__open(subrepo, sm, true);
1578 }
1579
1580 int git_submodule_open(git_repository **subrepo, git_submodule *sm)
1581 {
1582 return git_submodule__open(subrepo, sm, false);
1583 }
1584
1585 static void submodule_update_from_index_entry(
1586 git_submodule *sm, const git_index_entry *ie)
1587 {
1588 bool already_found = (sm->flags & GIT_SUBMODULE_STATUS_IN_INDEX) != 0;
1589
1590 if (!S_ISGITLINK(ie->mode)) {
1591 if (!already_found)
1592 sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE;
1593 } else {
1594 if (already_found)
1595 sm->flags |= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES;
1596 else
1597 git_oid_cpy(&sm->index_oid, &ie->id);
1598
1599 sm->flags |= GIT_SUBMODULE_STATUS_IN_INDEX |
1600 GIT_SUBMODULE_STATUS__INDEX_OID_VALID;
1601 }
1602 }
1603
1604 static int submodule_update_index(git_submodule *sm)
1605 {
1606 git_index *index;
1607 const git_index_entry *ie;
1608
1609 if (git_repository_index__weakptr(&index, sm->repo) < 0)
1610 return -1;
1611
1612 sm->flags = sm->flags &
1613 ~(GIT_SUBMODULE_STATUS_IN_INDEX |
1614 GIT_SUBMODULE_STATUS__INDEX_OID_VALID);
1615
1616 if (!(ie = git_index_get_bypath(index, sm->path, 0)))
1617 return 0;
1618
1619 submodule_update_from_index_entry(sm, ie);
1620
1621 return 0;
1622 }
1623
1624 static void submodule_update_from_head_data(
1625 git_submodule *sm, mode_t mode, const git_oid *id)
1626 {
1627 if (!S_ISGITLINK(mode))
1628 sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
1629 else {
1630 git_oid_cpy(&sm->head_oid, id);
1631
1632 sm->flags |= GIT_SUBMODULE_STATUS_IN_HEAD |
1633 GIT_SUBMODULE_STATUS__HEAD_OID_VALID;
1634 }
1635 }
1636
1637 static int submodule_update_head(git_submodule *submodule)
1638 {
1639 git_tree *head = NULL;
1640 git_tree_entry *te = NULL;
1641
1642 submodule->flags = submodule->flags &
1643 ~(GIT_SUBMODULE_STATUS_IN_HEAD |
1644 GIT_SUBMODULE_STATUS__HEAD_OID_VALID);
1645
1646 /* if we can't look up file in current head, then done */
1647 if (git_repository_head_tree(&head, submodule->repo) < 0 ||
1648 git_tree_entry_bypath(&te, head, submodule->path) < 0)
1649 git_error_clear();
1650 else
1651 submodule_update_from_head_data(submodule, te->attr, git_tree_entry_id(te));
1652
1653 git_tree_entry_free(te);
1654 git_tree_free(head);
1655 return 0;
1656 }
1657
1658 int git_submodule_reload(git_submodule *sm, int force)
1659 {
1660 git_config *mods = NULL;
1661 int error;
1662
1663 GIT_UNUSED(force);
1664
1665 GIT_ASSERT_ARG(sm);
1666
1667 if ((error = git_submodule_name_is_valid(sm->repo, sm->name, 0)) <= 0)
1668 /* This should come with a warning, but we've no API for that */
1669 goto out;
1670
1671 if (git_repository_is_bare(sm->repo))
1672 goto out;
1673
1674 /* refresh config data */
1675 if ((error = gitmodules_snapshot(&mods, sm->repo)) < 0 && error != GIT_ENOTFOUND)
1676 goto out;
1677
1678 if (mods != NULL && (error = submodule_read_config(sm, mods)) < 0)
1679 goto out;
1680
1681 /* refresh wd data */
1682 sm->flags &=
1683 ~(GIT_SUBMODULE_STATUS_IN_WD |
1684 GIT_SUBMODULE_STATUS__WD_OID_VALID |
1685 GIT_SUBMODULE_STATUS__WD_FLAGS);
1686
1687 if ((error = submodule_load_from_wd_lite(sm)) < 0 ||
1688 (error = submodule_update_index(sm)) < 0 ||
1689 (error = submodule_update_head(sm)) < 0)
1690 goto out;
1691
1692 out:
1693 git_config_free(mods);
1694 return error;
1695 }
1696
1697 static void submodule_copy_oid_maybe(
1698 git_oid *tgt, const git_oid *src, bool valid)
1699 {
1700 if (tgt) {
1701 if (valid)
1702 memcpy(tgt, src, sizeof(*tgt));
1703 else
1704 memset(tgt, 0, sizeof(*tgt));
1705 }
1706 }
1707
1708 int git_submodule__status(
1709 unsigned int *out_status,
1710 git_oid *out_head_id,
1711 git_oid *out_index_id,
1712 git_oid *out_wd_id,
1713 git_submodule *sm,
1714 git_submodule_ignore_t ign)
1715 {
1716 unsigned int status;
1717 git_repository *smrepo = NULL;
1718
1719 if (ign == GIT_SUBMODULE_IGNORE_UNSPECIFIED)
1720 ign = sm->ignore;
1721
1722 /* only return location info if ignore == all */
1723 if (ign == GIT_SUBMODULE_IGNORE_ALL) {
1724 *out_status = (sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS);
1725 return 0;
1726 }
1727
1728 /* If the user has requested caching submodule state, performing these
1729 * expensive operations (especially `submodule_update_head`, which is
1730 * bottlenecked on `git_repository_head_tree`) eliminates much of the
1731 * advantage. We will, therefore, interpret the request for caching to
1732 * apply here to and skip them.
1733 */
1734
1735 if (sm->repo->submodule_cache == NULL) {
1736 /* refresh the index OID */
1737 if (submodule_update_index(sm) < 0)
1738 return -1;
1739
1740 /* refresh the HEAD OID */
1741 if (submodule_update_head(sm) < 0)
1742 return -1;
1743 }
1744
1745 /* for ignore == dirty, don't scan the working directory */
1746 if (ign == GIT_SUBMODULE_IGNORE_DIRTY) {
1747 /* git_submodule_open_bare will load WD OID data */
1748 if (git_submodule_open_bare(&smrepo, sm) < 0)
1749 git_error_clear();
1750 else
1751 git_repository_free(smrepo);
1752 smrepo = NULL;
1753 } else if (git_submodule_open(&smrepo, sm) < 0) {
1754 git_error_clear();
1755 smrepo = NULL;
1756 }
1757
1758 status = GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm->flags);
1759
1760 submodule_get_index_status(&status, sm);
1761 submodule_get_wd_status(&status, sm, smrepo, ign);
1762
1763 git_repository_free(smrepo);
1764
1765 *out_status = status;
1766
1767 submodule_copy_oid_maybe(out_head_id, &sm->head_oid,
1768 (sm->flags & GIT_SUBMODULE_STATUS__HEAD_OID_VALID) != 0);
1769 submodule_copy_oid_maybe(out_index_id, &sm->index_oid,
1770 (sm->flags & GIT_SUBMODULE_STATUS__INDEX_OID_VALID) != 0);
1771 submodule_copy_oid_maybe(out_wd_id, &sm->wd_oid,
1772 (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) != 0);
1773
1774 return 0;
1775 }
1776
1777 int git_submodule_status(unsigned int *status, git_repository *repo, const char *name, git_submodule_ignore_t ignore)
1778 {
1779 git_submodule *sm;
1780 int error;
1781
1782 GIT_ASSERT_ARG(status);
1783 GIT_ASSERT_ARG(repo);
1784 GIT_ASSERT_ARG(name);
1785
1786 if ((error = git_submodule_lookup(&sm, repo, name)) < 0)
1787 return error;
1788
1789 error = git_submodule__status(status, NULL, NULL, NULL, sm, ignore);
1790 git_submodule_free(sm);
1791
1792 return error;
1793 }
1794
1795 int git_submodule_location(unsigned int *location, git_submodule *sm)
1796 {
1797 GIT_ASSERT_ARG(location);
1798 GIT_ASSERT_ARG(sm);
1799
1800 return git_submodule__status(
1801 location, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_ALL);
1802 }
1803
1804 /*
1805 * INTERNAL FUNCTIONS
1806 */
1807
1808 static int submodule_alloc(
1809 git_submodule **out, git_repository *repo, const char *name)
1810 {
1811 size_t namelen;
1812 git_submodule *sm;
1813
1814 if (!name || !(namelen = strlen(name))) {
1815 git_error_set(GIT_ERROR_SUBMODULE, "invalid submodule name");
1816 return -1;
1817 }
1818
1819 sm = git__calloc(1, sizeof(git_submodule));
1820 GIT_ERROR_CHECK_ALLOC(sm);
1821
1822 sm->name = sm->path = git__strdup(name);
1823 if (!sm->name) {
1824 git__free(sm);
1825 return -1;
1826 }
1827
1828 GIT_REFCOUNT_INC(sm);
1829 sm->ignore = sm->ignore_default = GIT_SUBMODULE_IGNORE_NONE;
1830 sm->update = sm->update_default = GIT_SUBMODULE_UPDATE_CHECKOUT;
1831 sm->fetch_recurse = sm->fetch_recurse_default = GIT_SUBMODULE_RECURSE_NO;
1832 sm->repo = repo;
1833 sm->branch = NULL;
1834
1835 *out = sm;
1836 return 0;
1837 }
1838
1839 static void submodule_release(git_submodule *sm)
1840 {
1841 if (!sm)
1842 return;
1843
1844 if (sm->repo) {
1845 sm->repo = NULL;
1846 }
1847
1848 if (sm->path != sm->name)
1849 git__free(sm->path);
1850 git__free(sm->name);
1851 git__free(sm->url);
1852 git__free(sm->branch);
1853 git__memzero(sm, sizeof(*sm));
1854 git__free(sm);
1855 }
1856
1857 int git_submodule_dup(git_submodule **out, git_submodule *source)
1858 {
1859 GIT_ASSERT_ARG(out);
1860 GIT_ASSERT_ARG(source);
1861
1862 GIT_REFCOUNT_INC(source);
1863
1864 *out = source;
1865 return 0;
1866 }
1867
1868 void git_submodule_free(git_submodule *sm)
1869 {
1870 if (!sm)
1871 return;
1872 GIT_REFCOUNT_DEC(sm, submodule_release);
1873 }
1874
1875 static int submodule_config_error(const char *property, const char *value)
1876 {
1877 git_error_set(GIT_ERROR_INVALID,
1878 "invalid value for submodule '%s' property: '%s'", property, value);
1879 return -1;
1880 }
1881
1882 int git_submodule_parse_ignore(git_submodule_ignore_t *out, const char *value)
1883 {
1884 int val;
1885
1886 if (git_config_lookup_map_value(
1887 &val, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), value) < 0) {
1888 *out = GIT_SUBMODULE_IGNORE_NONE;
1889 return submodule_config_error("ignore", value);
1890 }
1891
1892 *out = (git_submodule_ignore_t)val;
1893 return 0;
1894 }
1895
1896 int git_submodule_parse_update(git_submodule_update_t *out, const char *value)
1897 {
1898 int val;
1899
1900 if (git_config_lookup_map_value(
1901 &val, _sm_update_map, ARRAY_SIZE(_sm_update_map), value) < 0) {
1902 *out = GIT_SUBMODULE_UPDATE_CHECKOUT;
1903 return submodule_config_error("update", value);
1904 }
1905
1906 *out = (git_submodule_update_t)val;
1907 return 0;
1908 }
1909
1910 static int submodule_parse_recurse(git_submodule_recurse_t *out, const char *value)
1911 {
1912 int val;
1913
1914 if (git_config_lookup_map_value(
1915 &val, _sm_recurse_map, ARRAY_SIZE(_sm_recurse_map), value) < 0) {
1916 *out = GIT_SUBMODULE_RECURSE_YES;
1917 return submodule_config_error("recurse", value);
1918 }
1919
1920 *out = (git_submodule_recurse_t)val;
1921 return 0;
1922 }
1923
1924 static int get_value(const char **out, git_config *cfg, git_buf *buf, const char *name, const char *field)
1925 {
1926 int error;
1927
1928 git_buf_clear(buf);
1929
1930 if ((error = git_buf_printf(buf, "submodule.%s.%s", name, field)) < 0 ||
1931 (error = git_config_get_string(out, cfg, buf->ptr)) < 0)
1932 return error;
1933
1934 return error;
1935 }
1936
1937 static bool looks_like_command_line_option(const char *s)
1938 {
1939 if (s && s[0] == '-')
1940 return true;
1941
1942 return false;
1943 }
1944
1945 static int submodule_read_config(git_submodule *sm, git_config *cfg)
1946 {
1947 git_buf key = GIT_BUF_INIT;
1948 const char *value;
1949 int error, in_config = 0;
1950
1951 /*
1952 * TODO: Look up path in index and if it is present but not a GITLINK
1953 * then this should be deleted (at least to match git's behavior)
1954 */
1955
1956 if ((error = get_value(&value, cfg, &key, sm->name, "path")) == 0) {
1957 in_config = 1;
1958 /* We would warn here if we had that API */
1959 if (!looks_like_command_line_option(value)) {
1960 /*
1961 * TODO: if case insensitive filesystem, then the following strcmp
1962 * should be strcasecmp
1963 */
1964 if (strcmp(sm->name, value) != 0) {
1965 if (sm->path != sm->name)
1966 git__free(sm->path);
1967 sm->path = git__strdup(value);
1968 GIT_ERROR_CHECK_ALLOC(sm->path);
1969 }
1970
1971 }
1972 } else if (error != GIT_ENOTFOUND) {
1973 goto cleanup;
1974 }
1975
1976 if ((error = get_value(&value, cfg, &key, sm->name, "url")) == 0) {
1977 /* We would warn here if we had that API */
1978 if (!looks_like_command_line_option(value)) {
1979 in_config = 1;
1980 sm->url = git__strdup(value);
1981 GIT_ERROR_CHECK_ALLOC(sm->url);
1982 }
1983 } else if (error != GIT_ENOTFOUND) {
1984 goto cleanup;
1985 }
1986
1987 if ((error = get_value(&value, cfg, &key, sm->name, "branch")) == 0) {
1988 in_config = 1;
1989 sm->branch = git__strdup(value);
1990 GIT_ERROR_CHECK_ALLOC(sm->branch);
1991 } else if (error != GIT_ENOTFOUND) {
1992 goto cleanup;
1993 }
1994
1995 if ((error = get_value(&value, cfg, &key, sm->name, "update")) == 0) {
1996 in_config = 1;
1997 if ((error = git_submodule_parse_update(&sm->update, value)) < 0)
1998 goto cleanup;
1999 sm->update_default = sm->update;
2000 } else if (error != GIT_ENOTFOUND) {
2001 goto cleanup;
2002 }
2003
2004 if ((error = get_value(&value, cfg, &key, sm->name, "fetchRecurseSubmodules")) == 0) {
2005 in_config = 1;
2006 if ((error = submodule_parse_recurse(&sm->fetch_recurse, value)) < 0)
2007 goto cleanup;
2008 sm->fetch_recurse_default = sm->fetch_recurse;
2009 } else if (error != GIT_ENOTFOUND) {
2010 goto cleanup;
2011 }
2012
2013 if ((error = get_value(&value, cfg, &key, sm->name, "ignore")) == 0) {
2014 in_config = 1;
2015 if ((error = git_submodule_parse_ignore(&sm->ignore, value)) < 0)
2016 goto cleanup;
2017 sm->ignore_default = sm->ignore;
2018 } else if (error != GIT_ENOTFOUND) {
2019 goto cleanup;
2020 }
2021
2022 if (in_config)
2023 sm->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
2024
2025 error = 0;
2026
2027 cleanup:
2028 git_buf_dispose(&key);
2029 return error;
2030 }
2031
2032 static int submodule_load_each(const git_config_entry *entry, void *payload)
2033 {
2034 lfc_data *data = payload;
2035 const char *namestart, *property;
2036 git_strmap *map = data->map;
2037 git_buf name = GIT_BUF_INIT;
2038 git_submodule *sm;
2039 int error, isvalid;
2040
2041 if (git__prefixcmp(entry->name, "submodule.") != 0)
2042 return 0;
2043
2044 namestart = entry->name + strlen("submodule.");
2045 property = strrchr(namestart, '.');
2046
2047 if (!property || (property == namestart))
2048 return 0;
2049
2050 property++;
2051
2052 if ((error = git_buf_set(&name, namestart, property - namestart -1)) < 0)
2053 return error;
2054
2055 isvalid = git_submodule_name_is_valid(data->repo, name.ptr, 0);
2056 if (isvalid <= 0) {
2057 error = isvalid;
2058 goto done;
2059 }
2060
2061 /*
2062 * Now that we have the submodule's name, we can use that to
2063 * figure out whether it's in the map. If it's not, we create
2064 * a new submodule, load the config and insert it. If it's
2065 * already inserted, we've already loaded it, so we skip.
2066 */
2067 if (git_strmap_exists(map, name.ptr)) {
2068 error = 0;
2069 goto done;
2070 }
2071
2072 if ((error = submodule_alloc(&sm, data->repo, name.ptr)) < 0)
2073 goto done;
2074
2075 if ((error = submodule_read_config(sm, data->mods)) < 0) {
2076 git_submodule_free(sm);
2077 goto done;
2078 }
2079
2080 if ((error = git_strmap_set(map, sm->name, sm)) < 0)
2081 goto done;
2082
2083 error = 0;
2084
2085 done:
2086 git_buf_dispose(&name);
2087 return error;
2088 }
2089
2090 static int submodule_load_from_wd_lite(git_submodule *sm)
2091 {
2092 git_buf path = GIT_BUF_INIT;
2093
2094 if (git_repository_workdir_path(&path, sm->repo, sm->path) < 0)
2095 return -1;
2096
2097 if (git_path_isdir(path.ptr))
2098 sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED;
2099
2100 if (git_path_contains(&path, DOT_GIT))
2101 sm->flags |= GIT_SUBMODULE_STATUS_IN_WD;
2102
2103 git_buf_dispose(&path);
2104 return 0;
2105 }
2106
2107 /**
2108 * Requests a snapshot of $WORK_TREE/.gitmodules.
2109 *
2110 * Returns GIT_ENOTFOUND in case no .gitmodules file exist
2111 */
2112 static int gitmodules_snapshot(git_config **snap, git_repository *repo)
2113 {
2114 git_config *mods = NULL;
2115 git_buf path = GIT_BUF_INIT;
2116 int error;
2117
2118 if (git_repository_workdir(repo) == NULL)
2119 return GIT_ENOTFOUND;
2120
2121 if ((error = git_repository_workdir_path(&path, repo, GIT_MODULES_FILE)) < 0)
2122 return error;
2123
2124 if ((error = git_config_open_ondisk(&mods, path.ptr)) < 0)
2125 goto cleanup;
2126 git_buf_dispose(&path);
2127
2128 if ((error = git_config_snapshot(snap, mods)) < 0)
2129 goto cleanup;
2130
2131 error = 0;
2132
2133 cleanup:
2134 if (mods)
2135 git_config_free(mods);
2136 git_buf_dispose(&path);
2137
2138 return error;
2139 }
2140
2141 static git_config_backend *open_gitmodules(
2142 git_repository *repo,
2143 int okay_to_create)
2144 {
2145 git_buf path = GIT_BUF_INIT;
2146 git_config_backend *mods = NULL;
2147
2148 if (git_repository_workdir(repo) != NULL) {
2149 if (git_repository_workdir_path(&path, repo, GIT_MODULES_FILE) != 0)
2150 return NULL;
2151
2152 if (okay_to_create || git_path_isfile(path.ptr)) {
2153 /* git_config_backend_from_file should only fail if OOM */
2154 if (git_config_backend_from_file(&mods, path.ptr) < 0)
2155 mods = NULL;
2156 /* open should only fail here if the file is malformed */
2157 else if (git_config_backend_open(mods, GIT_CONFIG_LEVEL_LOCAL, repo) < 0) {
2158 git_config_backend_free(mods);
2159 mods = NULL;
2160 }
2161 }
2162 }
2163
2164 git_buf_dispose(&path);
2165
2166 return mods;
2167 }
2168
2169 /* Lookup name of remote of the local tracking branch HEAD points to */
2170 static int lookup_head_remote_key(git_buf *remote_name, git_repository *repo)
2171 {
2172 int error;
2173 git_reference *head = NULL;
2174 git_buf upstream_name = GIT_BUF_INIT;
2175
2176 /* lookup and dereference HEAD */
2177 if ((error = git_repository_head(&head, repo)) < 0)
2178 return error;
2179
2180 /**
2181 * If head does not refer to a branch, then return
2182 * GIT_ENOTFOUND to indicate that we could not find
2183 * a remote key for the local tracking branch HEAD points to.
2184 **/
2185 if (!git_reference_is_branch(head)) {
2186 git_error_set(GIT_ERROR_INVALID,
2187 "HEAD does not refer to a branch.");
2188 error = GIT_ENOTFOUND;
2189 goto done;
2190 }
2191
2192 /* lookup remote tracking branch of HEAD */
2193 if ((error = git_branch_upstream_name(
2194 &upstream_name,
2195 repo,
2196 git_reference_name(head))) < 0)
2197 goto done;
2198
2199 /* lookup remote of remote tracking branch */
2200 if ((error = git_branch_remote_name(remote_name, repo, upstream_name.ptr)) < 0)
2201 goto done;
2202
2203 done:
2204 git_buf_dispose(&upstream_name);
2205 git_reference_free(head);
2206
2207 return error;
2208 }
2209
2210 /* Lookup the remote of the local tracking branch HEAD points to */
2211 static int lookup_head_remote(git_remote **remote, git_repository *repo)
2212 {
2213 int error;
2214 git_buf remote_name = GIT_BUF_INIT;
2215
2216 /* lookup remote of remote tracking branch name */
2217 if (!(error = lookup_head_remote_key(&remote_name, repo)))
2218 error = git_remote_lookup(remote, repo, remote_name.ptr);
2219
2220 git_buf_dispose(&remote_name);
2221
2222 return error;
2223 }
2224
2225 /* Lookup remote, either from HEAD or fall back on origin */
2226 static int lookup_default_remote(git_remote **remote, git_repository *repo)
2227 {
2228 int error = lookup_head_remote(remote, repo);
2229
2230 /* if that failed, use 'origin' instead */
2231 if (error == GIT_ENOTFOUND || error == GIT_EUNBORNBRANCH)
2232 error = git_remote_lookup(remote, repo, "origin");
2233
2234 if (error == GIT_ENOTFOUND)
2235 git_error_set(
2236 GIT_ERROR_SUBMODULE,
2237 "cannot get default remote for submodule - no local tracking "
2238 "branch for HEAD and origin does not exist");
2239
2240 return error;
2241 }
2242
2243 static int get_url_base(git_buf *url, git_repository *repo)
2244 {
2245 int error;
2246 git_worktree *wt = NULL;
2247 git_remote *remote = NULL;
2248
2249 if ((error = lookup_default_remote(&remote, repo)) == 0) {
2250 error = git_buf_sets(url, git_remote_url(remote));
2251 goto out;
2252 } else if (error != GIT_ENOTFOUND)
2253 goto out;
2254 else
2255 git_error_clear();
2256
2257 /* if repository does not have a default remote, use workdir instead */
2258 if (git_repository_is_worktree(repo)) {
2259 if ((error = git_worktree_open_from_repository(&wt, repo)) < 0)
2260 goto out;
2261 error = git_buf_sets(url, wt->parent_path);
2262 } else {
2263 error = git_buf_sets(url, git_repository_workdir(repo));
2264 }
2265
2266 out:
2267 git_remote_free(remote);
2268 git_worktree_free(wt);
2269
2270 return error;
2271 }
2272
2273 static void submodule_get_index_status(unsigned int *status, git_submodule *sm)
2274 {
2275 const git_oid *head_oid = git_submodule_head_id(sm);
2276 const git_oid *index_oid = git_submodule_index_id(sm);
2277
2278 *status = *status & ~GIT_SUBMODULE_STATUS__INDEX_FLAGS;
2279
2280 if (!head_oid) {
2281 if (index_oid)
2282 *status |= GIT_SUBMODULE_STATUS_INDEX_ADDED;
2283 }
2284 else if (!index_oid)
2285 *status |= GIT_SUBMODULE_STATUS_INDEX_DELETED;
2286 else if (!git_oid_equal(head_oid, index_oid))
2287 *status |= GIT_SUBMODULE_STATUS_INDEX_MODIFIED;
2288 }
2289
2290
2291 static void submodule_get_wd_status(
2292 unsigned int *status,
2293 git_submodule *sm,
2294 git_repository *sm_repo,
2295 git_submodule_ignore_t ign)
2296 {
2297 const git_oid *index_oid = git_submodule_index_id(sm);
2298 const git_oid *wd_oid =
2299 (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) ? &sm->wd_oid : NULL;
2300 git_tree *sm_head = NULL;
2301 git_index *index = NULL;
2302 git_diff_options opt = GIT_DIFF_OPTIONS_INIT;
2303 git_diff *diff;
2304
2305 *status = *status & ~GIT_SUBMODULE_STATUS__WD_FLAGS;
2306
2307 if (!index_oid) {
2308 if (wd_oid)
2309 *status |= GIT_SUBMODULE_STATUS_WD_ADDED;
2310 }
2311 else if (!wd_oid) {
2312 if ((sm->flags & GIT_SUBMODULE_STATUS__WD_SCANNED) != 0 &&
2313 (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) == 0)
2314 *status |= GIT_SUBMODULE_STATUS_WD_UNINITIALIZED;
2315 else
2316 *status |= GIT_SUBMODULE_STATUS_WD_DELETED;
2317 }
2318 else if (!git_oid_equal(index_oid, wd_oid))
2319 *status |= GIT_SUBMODULE_STATUS_WD_MODIFIED;
2320
2321 /* if we have no repo, then we're done */
2322 if (!sm_repo)
2323 return;
2324
2325 /* the diffs below could be optimized with an early termination
2326 * option to the git_diff functions, but for now this is sufficient
2327 * (and certainly no worse that what core git does).
2328 */
2329
2330 if (ign == GIT_SUBMODULE_IGNORE_NONE)
2331 opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
2332
2333 (void)git_repository_index__weakptr(&index, sm_repo);
2334
2335 /* if we don't have an unborn head, check diff with index */
2336 if (git_repository_head_tree(&sm_head, sm_repo) < 0)
2337 git_error_clear();
2338 else {
2339 /* perform head to index diff on submodule */
2340 if (git_diff_tree_to_index(&diff, sm_repo, sm_head, index, &opt) < 0)
2341 git_error_clear();
2342 else {
2343 if (git_diff_num_deltas(diff) > 0)
2344 *status |= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED;
2345 git_diff_free(diff);
2346 diff = NULL;
2347 }
2348
2349 git_tree_free(sm_head);
2350 }
2351
2352 /* perform index-to-workdir diff on submodule */
2353 if (git_diff_index_to_workdir(&diff, sm_repo, index, &opt) < 0)
2354 git_error_clear();
2355 else {
2356 size_t untracked =
2357 git_diff_num_deltas_of_type(diff, GIT_DELTA_UNTRACKED);
2358
2359 if (untracked > 0)
2360 *status |= GIT_SUBMODULE_STATUS_WD_UNTRACKED;
2361
2362 if (git_diff_num_deltas(diff) != untracked)
2363 *status |= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED;
2364
2365 git_diff_free(diff);
2366 diff = NULL;
2367 }
2368 }