2 * Copyright (C) the libgit2 contributors. All rights reserved.
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.
14 #include "config_backend.h"
16 #include "repository.h"
26 #include "git2/config.h"
27 #include "git2/sys/config.h"
28 #include "git2/types.h"
29 #include "git2/index.h"
31 #define GIT_MODULES_FILE ".gitmodules"
33 static git_configmap _sm_update_map
[] = {
34 {GIT_CONFIGMAP_STRING
, "checkout", GIT_SUBMODULE_UPDATE_CHECKOUT
},
35 {GIT_CONFIGMAP_STRING
, "rebase", GIT_SUBMODULE_UPDATE_REBASE
},
36 {GIT_CONFIGMAP_STRING
, "merge", GIT_SUBMODULE_UPDATE_MERGE
},
37 {GIT_CONFIGMAP_STRING
, "none", GIT_SUBMODULE_UPDATE_NONE
},
38 {GIT_CONFIGMAP_FALSE
, NULL
, GIT_SUBMODULE_UPDATE_NONE
},
39 {GIT_CONFIGMAP_TRUE
, NULL
, GIT_SUBMODULE_UPDATE_CHECKOUT
},
42 static git_configmap _sm_ignore_map
[] = {
43 {GIT_CONFIGMAP_STRING
, "none", GIT_SUBMODULE_IGNORE_NONE
},
44 {GIT_CONFIGMAP_STRING
, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED
},
45 {GIT_CONFIGMAP_STRING
, "dirty", GIT_SUBMODULE_IGNORE_DIRTY
},
46 {GIT_CONFIGMAP_STRING
, "all", GIT_SUBMODULE_IGNORE_ALL
},
47 {GIT_CONFIGMAP_FALSE
, NULL
, GIT_SUBMODULE_IGNORE_NONE
},
48 {GIT_CONFIGMAP_TRUE
, NULL
, GIT_SUBMODULE_IGNORE_ALL
},
51 static git_configmap _sm_recurse_map
[] = {
52 {GIT_CONFIGMAP_STRING
, "on-demand", GIT_SUBMODULE_RECURSE_ONDEMAND
},
53 {GIT_CONFIGMAP_FALSE
, NULL
, GIT_SUBMODULE_RECURSE_NO
},
54 {GIT_CONFIGMAP_TRUE
, NULL
, GIT_SUBMODULE_RECURSE_YES
},
63 GITMODULES_EXISTING
= 0,
67 static int submodule_alloc(git_submodule
**out
, git_repository
*repo
, const char *name
);
68 static git_config_backend
*open_gitmodules(git_repository
*repo
, int gitmod
);
69 static int gitmodules_snapshot(git_config
**snap
, git_repository
*repo
);
70 static int get_url_base(git_str
*url
, git_repository
*repo
);
71 static int lookup_head_remote_key(git_str
*remote_key
, git_repository
*repo
);
72 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
);
73 static int submodule_load_each(const git_config_entry
*entry
, void *payload
);
74 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
);
75 static int submodule_load_from_wd_lite(git_submodule
*);
76 static void submodule_get_index_status(unsigned int *, git_submodule
*);
77 static void submodule_get_wd_status(unsigned int *, git_submodule
*, git_repository
*, git_submodule_ignore_t
);
78 static void submodule_update_from_index_entry(git_submodule
*sm
, const git_index_entry
*ie
);
79 static void submodule_update_from_head_data(git_submodule
*sm
, mode_t mode
, const git_oid
*id
);
81 static int submodule_cmp(const void *a
, const void *b
)
83 return strcmp(((git_submodule
*)a
)->name
, ((git_submodule
*)b
)->name
);
86 static int submodule_config_key_trunc_puts(git_str
*key
, const char *suffix
)
88 ssize_t idx
= git_str_rfind(key
, '.');
89 git_str_truncate(key
, (size_t)(idx
+ 1));
90 return git_str_puts(key
, suffix
);
97 static void submodule_set_lookup_error(int error
, const char *name
)
102 git_error_set(GIT_ERROR_SUBMODULE
, (error
== GIT_ENOTFOUND
) ?
103 "no submodule named '%s'" :
104 "submodule '%s' has not been added yet", name
);
112 static int find_by_path(const git_config_entry
*entry
, void *payload
)
114 fbp_data
*data
= payload
;
116 if (!strcmp(entry
->value
, data
->path
)) {
117 const char *fdot
, *ldot
;
118 fdot
= strchr(entry
->name
, '.');
119 ldot
= strrchr(entry
->name
, '.');
120 data
->name
= git__strndup(fdot
+ 1, ldot
- fdot
- 1);
121 GIT_ERROR_CHECK_ALLOC(data
->name
);
128 * Checks to see if the submodule shares its name with a file or directory that
129 * already exists on the index. If so, the submodule cannot be added.
131 static int is_path_occupied(bool *occupied
, git_repository
*repo
, const char *path
)
135 git_str dir
= GIT_STR_INIT
;
138 if ((error
= git_repository_index__weakptr(&index
, repo
)) < 0)
141 if ((error
= git_index_find(NULL
, index
, path
)) != GIT_ENOTFOUND
) {
143 git_error_set(GIT_ERROR_SUBMODULE
,
144 "File '%s' already exists in the index", path
);
150 if ((error
= git_str_sets(&dir
, path
)) < 0)
153 if ((error
= git_fs_path_to_dir(&dir
)) < 0)
156 if ((error
= git_index_find_prefix(NULL
, index
, dir
.ptr
)) != GIT_ENOTFOUND
) {
158 git_error_set(GIT_ERROR_SUBMODULE
,
159 "Directory '%s' already exists in the index", path
);
168 git_str_dispose(&dir
);
173 * Release the name map returned by 'load_submodule_names'.
175 static void free_submodule_names(git_strmap
*names
)
183 git_strmap_foreach(names
, key
, value
, {
184 git__free((char *) key
);
187 git_strmap_free(names
);
193 * Map submodule paths to names.
194 * TODO: for some use-cases, this might need case-folding on a
195 * case-insensitive filesystem
197 static int load_submodule_names(git_strmap
**out
, git_repository
*repo
, git_config
*cfg
)
199 const char *key
= "submodule\\..*\\.path";
200 git_config_iterator
*iter
= NULL
;
201 git_config_entry
*entry
;
202 git_str buf
= GIT_STR_INIT
;
208 if ((error
= git_strmap_new(&names
)) < 0)
211 if ((error
= git_config_iterator_glob_new(&iter
, cfg
, key
)) < 0)
214 while ((error
= git_config_next(&entry
, iter
)) == 0) {
215 const char *fdot
, *ldot
;
216 fdot
= strchr(entry
->name
, '.');
217 ldot
= strrchr(entry
->name
, '.');
219 if (git_strmap_exists(names
, entry
->value
)) {
220 git_error_set(GIT_ERROR_SUBMODULE
,
221 "duplicated submodule path '%s'", entry
->value
);
227 git_str_put(&buf
, fdot
+ 1, ldot
- fdot
- 1);
228 isvalid
= git_submodule_name_is_valid(repo
, buf
.ptr
, 0);
236 if ((error
= git_strmap_set(names
, git__strdup(entry
->value
), git_str_detach(&buf
))) < 0) {
237 git_error_set(GIT_ERROR_NOMEMORY
, "error inserting submodule into hash table");
242 if (error
== GIT_ITEROVER
)
249 free_submodule_names(names
);
250 git_str_dispose(&buf
);
251 git_config_iterator_free(iter
);
255 int git_submodule_cache_init(git_strmap
**out
, git_repository
*repo
)
258 git_strmap
*cache
= NULL
;
260 GIT_ASSERT_ARG(repo
);
261 if ((error
= git_strmap_new(&cache
)) < 0)
263 if ((error
= git_submodule__map(repo
, cache
)) < 0) {
264 git_submodule_cache_free(cache
);
271 int git_submodule_cache_free(git_strmap
*cache
)
273 git_submodule
*sm
= NULL
;
276 git_strmap_foreach_value(cache
, sm
, {
277 git_submodule_free(sm
);
279 git_strmap_free(cache
);
283 int git_submodule_lookup(
284 git_submodule
**out
, /* NULL if user only wants to test existence */
285 git_repository
*repo
,
286 const char *name
) /* trailing slash is allowed */
288 return git_submodule__lookup_with_cache(out
, repo
, name
, repo
->submodule_cache
);
291 int git_submodule__lookup_with_cache(
292 git_submodule
**out
, /* NULL if user only wants to test existence */
293 git_repository
*repo
,
294 const char *name
, /* trailing slash is allowed */
298 unsigned int location
;
301 GIT_ASSERT_ARG(repo
);
302 GIT_ASSERT_ARG(name
);
305 git_error_set(GIT_ERROR_SUBMODULE
, "cannot get submodules without a working tree");
310 if ((sm
= git_strmap_get(cache
, name
)) != NULL
) {
313 GIT_REFCOUNT_INC(*out
);
319 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
322 if ((error
= git_submodule_reload(sm
, false)) < 0) {
323 git_submodule_free(sm
);
327 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
328 git_submodule_free(sm
);
332 /* If it's not configured or we're looking by path */
333 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
334 git_config_backend
*mods
;
335 const char *pattern
= "submodule\\..*\\.path";
336 git_str path
= GIT_STR_INIT
;
337 fbp_data data
= { NULL
, NULL
};
339 git_str_puts(&path
, name
);
340 while (path
.ptr
[path
.size
-1] == '/') {
341 path
.ptr
[--path
.size
] = '\0';
343 data
.path
= path
.ptr
;
345 mods
= open_gitmodules(repo
, GITMODULES_EXISTING
);
348 error
= git_config_backend_foreach_match(mods
, pattern
, find_by_path
, &data
);
350 git_config_backend_free(mods
);
353 git_submodule_free(sm
);
354 git_str_dispose(&path
);
360 sm
->name
= data
.name
;
361 sm
->path
= git_str_detach(&path
);
363 /* Try to load again with the right name */
364 if ((error
= git_submodule_reload(sm
, false)) < 0) {
365 git_submodule_free(sm
);
370 git_str_dispose(&path
);
373 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
374 git_submodule_free(sm
);
378 /* If we still haven't found it, do the WD check */
379 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
380 git_submodule_free(sm
);
381 error
= GIT_ENOTFOUND
;
383 /* If it's not configured, we still check if there's a repo at the path */
384 if (git_repository_workdir(repo
)) {
385 git_str path
= GIT_STR_INIT
;
386 if (git_str_join3(&path
, '/',
387 git_repository_workdir(repo
),
388 name
, DOT_GIT
) < 0 ||
389 git_path_validate_str_length(NULL
, &path
) < 0)
392 if (git_fs_path_exists(path
.ptr
))
395 git_str_dispose(&path
);
398 submodule_set_lookup_error(error
, name
);
405 git_submodule_free(sm
);
410 int git_submodule_name_is_valid(git_repository
*repo
, const char *name
, int flags
)
412 git_str buf
= GIT_STR_INIT
;
416 flags
= GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS
;
418 /* Avoid allocating a new string if we can avoid it */
419 if (strchr(name
, '\\') != NULL
) {
420 if ((error
= git_fs_path_normalize_slashes(&buf
, name
)) < 0)
423 git_str_attach_notowned(&buf
, name
, strlen(name
));
426 isvalid
= git_path_is_valid(repo
, buf
.ptr
, 0, flags
);
427 git_str_dispose(&buf
);
432 static void submodule_free_dup(void *sm
)
434 git_submodule_free(sm
);
437 static int submodule_get_or_create(git_submodule
**out
, git_repository
*repo
, git_strmap
*map
, const char *name
)
439 git_submodule
*sm
= NULL
;
442 if ((sm
= git_strmap_get(map
, name
)) != NULL
)
445 /* if the submodule doesn't exist yet in the map, create it */
446 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
449 if ((error
= git_strmap_set(map
, sm
->name
, sm
)) < 0) {
450 git_submodule_free(sm
);
455 GIT_REFCOUNT_INC(sm
);
460 static int submodules_from_index(git_strmap
*map
, git_index
*idx
, git_config
*cfg
)
463 git_iterator
*i
= NULL
;
464 const git_index_entry
*entry
;
467 if ((error
= load_submodule_names(&names
, git_index_owner(idx
), cfg
)))
470 if ((error
= git_iterator_for_index(&i
, git_index_owner(idx
), idx
, NULL
)) < 0)
473 while (!(error
= git_iterator_advance(&entry
, i
))) {
476 if ((sm
= git_strmap_get(map
, entry
->path
)) != NULL
) {
477 if (S_ISGITLINK(entry
->mode
))
478 submodule_update_from_index_entry(sm
, entry
);
480 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
481 } else if (S_ISGITLINK(entry
->mode
)) {
484 if ((name
= git_strmap_get(names
, entry
->path
)) == NULL
)
487 if (!submodule_get_or_create(&sm
, git_index_owner(idx
), map
, name
)) {
488 submodule_update_from_index_entry(sm
, entry
);
489 git_submodule_free(sm
);
494 if (error
== GIT_ITEROVER
)
498 git_iterator_free(i
);
499 free_submodule_names(names
);
504 static int submodules_from_head(git_strmap
*map
, git_tree
*head
, git_config
*cfg
)
507 git_iterator
*i
= NULL
;
508 const git_index_entry
*entry
;
511 if ((error
= load_submodule_names(&names
, git_tree_owner(head
), cfg
)))
514 if ((error
= git_iterator_for_tree(&i
, head
, NULL
)) < 0)
517 while (!(error
= git_iterator_advance(&entry
, i
))) {
520 if ((sm
= git_strmap_get(map
, entry
->path
)) != NULL
) {
521 if (S_ISGITLINK(entry
->mode
))
522 submodule_update_from_head_data(sm
, entry
->mode
, &entry
->id
);
524 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
525 } else if (S_ISGITLINK(entry
->mode
)) {
528 if ((name
= git_strmap_get(names
, entry
->path
)) == NULL
)
531 if (!submodule_get_or_create(&sm
, git_tree_owner(head
), map
, name
)) {
532 submodule_update_from_head_data(
533 sm
, entry
->mode
, &entry
->id
);
534 git_submodule_free(sm
);
539 if (error
== GIT_ITEROVER
)
543 git_iterator_free(i
);
544 free_submodule_names(names
);
549 /* If have_sm is true, sm is populated, otherwise map an repo are. */
553 git_repository
*repo
;
556 int git_submodule__map(git_repository
*repo
, git_strmap
*map
)
559 git_index
*idx
= NULL
;
560 git_tree
*head
= NULL
;
561 git_str path
= GIT_STR_INIT
;
563 git_config
*mods
= NULL
;
566 GIT_ASSERT_ARG(repo
);
569 /* get sources that we will need to check */
570 if (git_repository_index(&idx
, repo
) < 0)
572 if (git_repository_head_tree(&head
, repo
) < 0)
575 has_workdir
= git_repository_workdir(repo
) != NULL
;
578 (error
= git_repository_workdir_path(&path
, repo
, GIT_MODULES_FILE
)) < 0)
581 /* add submodule information from .gitmodules */
583 lfc_data data
= { 0 };
587 if ((error
= gitmodules_snapshot(&mods
, repo
)) < 0) {
588 if (error
== GIT_ENOTFOUND
)
594 if ((error
= git_config_foreach(
595 mods
, submodule_load_each
, &data
)) < 0)
598 /* add back submodule information from index */
600 if ((error
= submodules_from_index(map
, idx
, mods
)) < 0)
603 /* add submodule information from HEAD */
605 if ((error
= submodules_from_head(map
, head
, mods
)) < 0)
608 /* shallow scan submodules in work tree as needed */
610 git_strmap_foreach_value(map
, sm
, {
611 submodule_load_from_wd_lite(sm
);
616 git_config_free(mods
);
617 /* TODO: if we got an error, mark submodule config as invalid? */
620 git_str_dispose(&path
);
624 int git_submodule_foreach(
625 git_repository
*repo
,
626 git_submodule_cb callback
,
629 git_vector snapshot
= GIT_VECTOR_INIT
;
630 git_strmap
*submodules
;
636 git_error_set(GIT_ERROR_SUBMODULE
, "cannot get submodules without a working tree");
640 if ((error
= git_strmap_new(&submodules
)) < 0)
643 if ((error
= git_submodule__map(repo
, submodules
)) < 0)
646 if (!(error
= git_vector_init(
647 &snapshot
, git_strmap_size(submodules
), submodule_cmp
))) {
649 git_strmap_foreach_value(submodules
, sm
, {
650 if ((error
= git_vector_insert(&snapshot
, sm
)) < 0)
652 GIT_REFCOUNT_INC(sm
);
659 git_vector_uniq(&snapshot
, submodule_free_dup
);
661 git_vector_foreach(&snapshot
, i
, sm
) {
662 if ((error
= callback(sm
, sm
->name
, payload
)) != 0) {
663 git_error_set_after_callback(error
);
669 git_vector_foreach(&snapshot
, i
, sm
)
670 git_submodule_free(sm
);
671 git_vector_free(&snapshot
);
673 git_strmap_foreach_value(submodules
, sm
, {
674 git_submodule_free(sm
);
676 git_strmap_free(submodules
);
681 static int submodule_repo_init(
682 git_repository
**out
,
683 git_repository
*parent_repo
,
689 git_str workdir
= GIT_STR_INIT
, repodir
= GIT_STR_INIT
;
690 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
691 git_repository
*subrepo
= NULL
;
693 error
= git_repository_workdir_path(&workdir
, parent_repo
, path
);
697 initopt
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_NO_REINIT
;
698 initopt
.origin_url
= url
;
700 /* init submodule repository and add origin remote as needed */
702 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
703 * gitlink in the sub-repo workdir directory to that repository
705 * Old style: sub-repo goes directly into repo/<name>/.git/
708 error
= git_repository__item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
711 error
= git_str_joinpath(&repodir
, repodir
.ptr
, path
);
715 initopt
.workdir_path
= workdir
.ptr
;
717 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
718 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
720 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
722 error
= git_repository_init_ext(&subrepo
, workdir
.ptr
, &initopt
);
725 git_str_dispose(&workdir
);
726 git_str_dispose(&repodir
);
733 static int git_submodule__resolve_url(
735 git_repository
*repo
,
739 git_str normalized
= GIT_STR_INIT
;
742 GIT_ASSERT_ARG(repo
);
745 /* We do this in all platforms in case someone on Windows created the .gitmodules */
746 if (strchr(url
, '\\')) {
747 if ((error
= git_fs_path_normalize_slashes(&normalized
, url
)) < 0)
750 url
= normalized
.ptr
;
754 if (git_fs_path_is_relative(url
)) {
755 if (!(error
= get_url_base(out
, repo
)))
756 error
= git_fs_path_apply_relative(out
, url
);
757 } else if (strchr(url
, ':') != NULL
|| url
[0] == '/') {
758 error
= git_str_sets(out
, url
);
760 git_error_set(GIT_ERROR_SUBMODULE
, "invalid format for submodule URL");
764 git_str_dispose(&normalized
);
768 int git_submodule_resolve_url(
770 git_repository
*repo
,
773 GIT_BUF_WRAP_PRIVATE(out
, git_submodule__resolve_url
, repo
, url
);
776 int git_submodule_add_setup(
778 git_repository
*repo
,
784 git_config_backend
*mods
= NULL
;
785 git_submodule
*sm
= NULL
;
786 git_str name
= GIT_STR_INIT
, real_url
= GIT_STR_INIT
;
787 git_repository
*subrepo
= NULL
;
790 GIT_ASSERT_ARG(repo
);
792 GIT_ASSERT_ARG(path
);
794 /* see if there is already an entry for this submodule */
796 if (git_submodule_lookup(NULL
, repo
, path
) < 0)
799 git_error_set(GIT_ERROR_SUBMODULE
,
800 "attempt to add submodule '%s' that already exists", path
);
804 /* validate and normalize path */
806 if (git__prefixcmp(path
, git_repository_workdir(repo
)) == 0)
807 path
+= strlen(git_repository_workdir(repo
));
809 if (git_fs_path_root(path
) >= 0) {
810 git_error_set(GIT_ERROR_SUBMODULE
, "submodule path must be a relative path");
815 if ((error
= is_path_occupied(&path_occupied
, repo
, path
)) < 0)
823 /* update .gitmodules */
825 if (!(mods
= open_gitmodules(repo
, GITMODULES_CREATE
))) {
826 git_error_set(GIT_ERROR_SUBMODULE
,
827 "adding submodules to a bare repository is not supported");
831 if ((error
= git_str_printf(&name
, "submodule.%s.path", path
)) < 0 ||
832 (error
= git_config_backend_set_string(mods
, name
.ptr
, path
)) < 0)
835 if ((error
= submodule_config_key_trunc_puts(&name
, "url")) < 0 ||
836 (error
= git_config_backend_set_string(mods
, name
.ptr
, url
)) < 0)
839 git_str_clear(&name
);
841 /* init submodule repository and add origin remote as needed */
843 error
= git_repository_workdir_path(&name
, repo
, path
);
847 /* if the repo does not already exist, then init a new repo and add it.
848 * Otherwise, just add the existing repo.
850 if (!(git_fs_path_exists(name
.ptr
) &&
851 git_fs_path_contains(&name
, DOT_GIT
))) {
853 /* resolve the actual URL to use */
854 if ((error
= git_submodule__resolve_url(&real_url
, repo
, url
)) < 0)
857 if ((error
= submodule_repo_init(&subrepo
, repo
, path
, real_url
.ptr
, use_gitlink
)) < 0)
861 if ((error
= git_submodule_lookup(&sm
, repo
, path
)) < 0)
864 error
= git_submodule_init(sm
, false);
868 git_submodule_free(sm
);
874 git_config_backend_free(mods
);
875 git_repository_free(subrepo
);
876 git_str_dispose(&real_url
);
877 git_str_dispose(&name
);
882 int git_submodule_repo_init(
883 git_repository
**out
,
884 const git_submodule
*sm
,
888 git_repository
*sub_repo
= NULL
;
889 const char *configured_url
;
890 git_config
*cfg
= NULL
;
891 git_str buf
= GIT_STR_INIT
;
896 /* get the configured remote url of the submodule */
897 if ((error
= git_str_printf(&buf
, "submodule.%s.url", sm
->name
)) < 0 ||
898 (error
= git_repository_config_snapshot(&cfg
, sm
->repo
)) < 0 ||
899 (error
= git_config_get_string(&configured_url
, cfg
, buf
.ptr
)) < 0 ||
900 (error
= submodule_repo_init(&sub_repo
, sm
->repo
, sm
->path
, configured_url
, use_gitlink
)) < 0)
906 git_config_free(cfg
);
907 git_str_dispose(&buf
);
911 static int clone_return_origin(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, void *payload
)
915 return git_remote_lookup(out
, repo
, name
);
918 static int clone_return_repo(git_repository
**out
, const char *path
, int bare
, void *payload
)
920 git_submodule
*sm
= payload
;
924 return git_submodule_open(out
, sm
);
927 int git_submodule_clone(git_repository
**out
, git_submodule
*submodule
, const git_submodule_update_options
*given_opts
)
930 git_repository
*clone
;
931 git_str rel_path
= GIT_STR_INIT
;
932 git_submodule_update_options sub_opts
= GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
933 git_clone_options opts
= GIT_CLONE_OPTIONS_INIT
;
935 GIT_ASSERT_ARG(submodule
);
938 memcpy(&sub_opts
, given_opts
, sizeof(sub_opts
));
940 GIT_ERROR_CHECK_VERSION(&sub_opts
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
942 memcpy(&opts
.checkout_opts
, &sub_opts
.checkout_opts
, sizeof(sub_opts
.checkout_opts
));
943 memcpy(&opts
.fetch_opts
, &sub_opts
.fetch_opts
, sizeof(sub_opts
.fetch_opts
));
944 opts
.repository_cb
= clone_return_repo
;
945 opts
.repository_cb_payload
= submodule
;
946 opts
.remote_cb
= clone_return_origin
;
947 opts
.remote_cb_payload
= submodule
;
949 error
= git_repository_workdir_path(&rel_path
, git_submodule_owner(submodule
), git_submodule_path(submodule
));
953 error
= git_clone__submodule(&clone
, git_submodule_url(submodule
), git_str_cstr(&rel_path
), &opts
);
958 git_repository_free(clone
);
963 git_str_dispose(&rel_path
);
968 int git_submodule_add_finalize(git_submodule
*sm
)
975 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
976 (error
= git_index_add_bypath(index
, GIT_MODULES_FILE
)) < 0)
979 return git_submodule_add_to_index(sm
, true);
982 int git_submodule_add_to_index(git_submodule
*sm
, int write_index
)
985 git_repository
*sm_repo
= NULL
;
987 git_str path
= GIT_STR_INIT
;
989 git_index_entry entry
;
994 /* force reload of wd OID by git_submodule_open */
995 sm
->flags
= sm
->flags
& ~GIT_SUBMODULE_STATUS__WD_OID_VALID
;
997 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
998 (error
= git_repository_workdir_path(&path
, sm
->repo
, sm
->path
)) < 0 ||
999 (error
= git_submodule_open(&sm_repo
, sm
)) < 0)
1002 /* read stat information for submodule working directory */
1003 if (p_stat(path
.ptr
, &st
) < 0) {
1004 git_error_set(GIT_ERROR_SUBMODULE
,
1005 "cannot add submodule without working directory");
1010 memset(&entry
, 0, sizeof(entry
));
1011 entry
.path
= sm
->path
;
1012 git_index_entry__init_from_stat(
1013 &entry
, &st
, !(git_index_caps(index
) & GIT_INDEX_CAPABILITY_NO_FILEMODE
));
1015 /* calling git_submodule_open will have set sm->wd_oid if possible */
1016 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) == 0) {
1017 git_error_set(GIT_ERROR_SUBMODULE
,
1018 "cannot add submodule without HEAD to index");
1022 git_oid_cpy(&entry
.id
, &sm
->wd_oid
);
1024 if ((error
= git_commit_lookup(&head
, sm_repo
, &sm
->wd_oid
)) < 0)
1027 entry
.ctime
.seconds
= (int32_t)git_commit_time(head
);
1028 entry
.ctime
.nanoseconds
= 0;
1029 entry
.mtime
.seconds
= (int32_t)git_commit_time(head
);
1030 entry
.mtime
.nanoseconds
= 0;
1032 git_commit_free(head
);
1035 error
= git_index_add(index
, &entry
);
1037 /* write it, if requested */
1038 if (!error
&& write_index
) {
1039 error
= git_index_write(index
);
1042 git_oid_cpy(&sm
->index_oid
, &sm
->wd_oid
);
1046 git_repository_free(sm_repo
);
1047 git_str_dispose(&path
);
1051 static const char *submodule_update_to_str(git_submodule_update_t update
)
1054 for (i
= 0; i
< (int)ARRAY_SIZE(_sm_update_map
); ++i
)
1055 if (_sm_update_map
[i
].map_value
== (int)update
)
1056 return _sm_update_map
[i
].str_match
;
1060 git_repository
*git_submodule_owner(git_submodule
*submodule
)
1062 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1063 return submodule
->repo
;
1066 const char *git_submodule_name(git_submodule
*submodule
)
1068 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1069 return submodule
->name
;
1072 const char *git_submodule_path(git_submodule
*submodule
)
1074 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1075 return submodule
->path
;
1078 const char *git_submodule_url(git_submodule
*submodule
)
1080 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1081 return submodule
->url
;
1084 static int write_var(git_repository
*repo
, const char *name
, const char *var
, const char *val
)
1086 git_str key
= GIT_STR_INIT
;
1087 git_config_backend
*mods
;
1090 mods
= open_gitmodules(repo
, GITMODULES_CREATE
);
1094 if ((error
= git_str_printf(&key
, "submodule.%s.%s", name
, var
)) < 0)
1098 error
= git_config_backend_set_string(mods
, key
.ptr
, val
);
1100 error
= git_config_backend_delete(mods
, key
.ptr
);
1102 git_str_dispose(&key
);
1105 git_config_backend_free(mods
);
1109 static int write_mapped_var(git_repository
*repo
, const char *name
, git_configmap
*maps
, size_t nmaps
, const char *var
, int ival
)
1111 git_configmap_t type
;
1114 if (git_config_lookup_map_enum(&type
, &val
, maps
, nmaps
, ival
) < 0) {
1115 git_error_set(GIT_ERROR_SUBMODULE
, "invalid value for %s", var
);
1119 if (type
== GIT_CONFIGMAP_TRUE
)
1122 return write_var(repo
, name
, var
, val
);
1125 const char *git_submodule_branch(git_submodule
*submodule
)
1127 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1128 return submodule
->branch
;
1131 int git_submodule_set_branch(git_repository
*repo
, const char *name
, const char *branch
)
1133 GIT_ASSERT_ARG(repo
);
1134 GIT_ASSERT_ARG(name
);
1136 return write_var(repo
, name
, "branch", branch
);
1139 int git_submodule_set_url(git_repository
*repo
, const char *name
, const char *url
)
1141 GIT_ASSERT_ARG(repo
);
1142 GIT_ASSERT_ARG(name
);
1143 GIT_ASSERT_ARG(url
);
1145 return write_var(repo
, name
, "url", url
);
1148 const git_oid
*git_submodule_index_id(git_submodule
*submodule
)
1150 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1152 if (submodule
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
1153 return &submodule
->index_oid
;
1158 const git_oid
*git_submodule_head_id(git_submodule
*submodule
)
1160 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1162 if (submodule
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
1163 return &submodule
->head_oid
;
1168 const git_oid
*git_submodule_wd_id(git_submodule
*submodule
)
1170 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1172 /* load unless we think we have a valid oid */
1173 if (!(submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)) {
1174 git_repository
*subrepo
;
1176 /* calling submodule open grabs the HEAD OID if possible */
1177 if (!git_submodule_open_bare(&subrepo
, submodule
))
1178 git_repository_free(subrepo
);
1183 if (submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)
1184 return &submodule
->wd_oid
;
1189 git_submodule_ignore_t
git_submodule_ignore(git_submodule
*submodule
)
1191 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
);
1193 return (submodule
->ignore
< GIT_SUBMODULE_IGNORE_NONE
) ?
1194 GIT_SUBMODULE_IGNORE_NONE
: submodule
->ignore
;
1197 int git_submodule_set_ignore(git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1199 GIT_ASSERT_ARG(repo
);
1200 GIT_ASSERT_ARG(name
);
1202 return write_mapped_var(repo
, name
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), "ignore", ignore
);
1205 git_submodule_update_t
git_submodule_update_strategy(git_submodule
*submodule
)
1207 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, GIT_SUBMODULE_UPDATE_NONE
);
1209 return (submodule
->update
< GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1210 GIT_SUBMODULE_UPDATE_CHECKOUT
: submodule
->update
;
1213 int git_submodule_set_update(git_repository
*repo
, const char *name
, git_submodule_update_t update
)
1215 GIT_ASSERT_ARG(repo
);
1216 GIT_ASSERT_ARG(name
);
1218 return write_mapped_var(repo
, name
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), "update", update
);
1221 git_submodule_recurse_t
git_submodule_fetch_recurse_submodules(
1222 git_submodule
*submodule
)
1224 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, GIT_SUBMODULE_RECURSE_NO
);
1225 return submodule
->fetch_recurse
;
1228 int git_submodule_set_fetch_recurse_submodules(git_repository
*repo
, const char *name
, git_submodule_recurse_t recurse
)
1230 GIT_ASSERT_ARG(repo
);
1231 GIT_ASSERT_ARG(name
);
1233 return write_mapped_var(repo
, name
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), "fetchRecurseSubmodules", recurse
);
1236 static int submodule_repo_create(
1237 git_repository
**out
,
1238 git_repository
*parent_repo
,
1242 git_str workdir
= GIT_STR_INIT
, repodir
= GIT_STR_INIT
;
1243 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
1244 git_repository
*subrepo
= NULL
;
1247 GIT_REPOSITORY_INIT_MKPATH
|
1248 GIT_REPOSITORY_INIT_NO_REINIT
|
1249 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
1250 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
1252 /* Workdir: path to sub-repo working directory */
1253 error
= git_repository_workdir_path(&workdir
, parent_repo
, path
);
1257 initopt
.workdir_path
= workdir
.ptr
;
1260 * Repodir: path to the sub-repo. sub-repo goes in:
1261 * <repo-dir>/modules/<name>/ with a gitlink in the
1262 * sub-repo workdir directory to that repository.
1264 error
= git_repository__item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
1267 error
= git_str_joinpath(&repodir
, repodir
.ptr
, path
);
1271 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
1274 git_str_dispose(&workdir
);
1275 git_str_dispose(&repodir
);
1283 * Callback to override sub-repository creation when
1284 * cloning a sub-repository.
1286 static int git_submodule_update_repo_init_cb(
1287 git_repository
**out
,
1298 return submodule_repo_create(out
, sm
->repo
, path
);
1301 int git_submodule_update_options_init(git_submodule_update_options
*opts
, unsigned int version
)
1303 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1304 opts
, version
, git_submodule_update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_INIT
);
1308 #ifndef GIT_DEPRECATE_HARD
1309 int git_submodule_update_init_options(git_submodule_update_options
*opts
, unsigned int version
)
1311 return git_submodule_update_options_init(opts
, version
);
1315 int git_submodule_update(git_submodule
*sm
, int init
, git_submodule_update_options
*_update_options
)
1318 unsigned int submodule_status
;
1319 git_config
*config
= NULL
;
1320 const char *submodule_url
;
1321 git_repository
*sub_repo
= NULL
;
1322 git_remote
*remote
= NULL
;
1323 git_object
*target_commit
= NULL
;
1324 git_str buf
= GIT_STR_INIT
;
1325 git_submodule_update_options update_options
= GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
1326 git_clone_options clone_options
= GIT_CLONE_OPTIONS_INIT
;
1330 if (_update_options
)
1331 memcpy(&update_options
, _update_options
, sizeof(git_submodule_update_options
));
1333 GIT_ERROR_CHECK_VERSION(&update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
1335 /* Copy over the remote callbacks */
1336 memcpy(&clone_options
.fetch_opts
, &update_options
.fetch_opts
, sizeof(git_fetch_options
));
1338 /* Get the status of the submodule to determine if it is already initialized */
1339 if ((error
= git_submodule_status(&submodule_status
, sm
->repo
, sm
->name
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
)) < 0)
1343 * If submodule work dir is not already initialized, check to see
1344 * what we need to do (initialize, clone, return error...)
1346 if (submodule_status
& GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
) {
1348 * Work dir is not initialized, check to see if the submodule
1349 * info has been copied into .git/config
1351 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1352 (error
= git_str_printf(&buf
, "submodule.%s.url", git_submodule_name(sm
))) < 0)
1355 if ((error
= git_config_get_string(&submodule_url
, config
, git_str_cstr(&buf
))) < 0) {
1357 * If the error is not "not found" or if it is "not found" and we are not
1358 * initializing the submodule, then return error.
1360 if (error
!= GIT_ENOTFOUND
)
1364 git_error_set(GIT_ERROR_SUBMODULE
, "submodule is not initialized");
1369 /* The submodule has not been initialized yet - initialize it now.*/
1370 if ((error
= git_submodule_init(sm
, 0)) < 0)
1373 git_config_free(config
);
1376 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1377 (error
= git_config_get_string(&submodule_url
, config
, git_str_cstr(&buf
))) < 0)
1381 /** submodule is initialized - now clone it **/
1382 /* override repo creation */
1383 clone_options
.repository_cb
= git_submodule_update_repo_init_cb
;
1384 clone_options
.repository_cb_payload
= sm
;
1387 * Do not perform checkout as part of clone, instead we
1388 * will checkout the specific commit manually.
1390 clone_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
1392 if ((error
= git_clone(&sub_repo
, submodule_url
, sm
->path
, &clone_options
)) < 0 ||
1393 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0 ||
1394 (error
= git_checkout_head(sub_repo
, &update_options
.checkout_opts
)) != 0)
1400 * Work dir is initialized - look up the commit in the parent repository's index,
1401 * update the workdir contents of the subrepository, and set the subrepository's
1402 * head to the new commit.
1404 if ((error
= git_submodule_open(&sub_repo
, sm
)) < 0)
1407 if ((oid
= git_submodule_index_id(sm
)) == NULL
) {
1408 git_error_set(GIT_ERROR_SUBMODULE
, "could not get ID of submodule in index");
1413 /* Look up the target commit in the submodule. */
1414 if ((error
= git_object_lookup(&target_commit
, sub_repo
, oid
, GIT_OBJECT_COMMIT
)) < 0) {
1415 /* If it isn't found then fetch and try again. */
1416 if (error
!= GIT_ENOTFOUND
|| !update_options
.allow_fetch
||
1417 (error
= lookup_default_remote(&remote
, sub_repo
)) < 0 ||
1418 (error
= git_remote_fetch(remote
, NULL
, &update_options
.fetch_opts
, NULL
)) < 0 ||
1419 (error
= git_object_lookup(&target_commit
, sub_repo
, git_submodule_index_id(sm
), GIT_OBJECT_COMMIT
)) < 0)
1423 if ((error
= git_checkout_tree(sub_repo
, target_commit
, &update_options
.checkout_opts
)) != 0 ||
1424 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0)
1427 /* Invalidate the wd flags as the workdir has been updated. */
1428 sm
->flags
= sm
->flags
&
1429 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1430 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1431 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1435 git_str_dispose(&buf
);
1436 git_config_free(config
);
1437 git_object_free(target_commit
);
1438 git_remote_free(remote
);
1439 git_repository_free(sub_repo
);
1444 int git_submodule_init(git_submodule
*sm
, int overwrite
)
1448 git_str key
= GIT_STR_INIT
, effective_submodule_url
= GIT_STR_INIT
;
1449 git_config
*cfg
= NULL
;
1452 git_error_set(GIT_ERROR_SUBMODULE
,
1453 "no URL configured for submodule '%s'", sm
->name
);
1457 if ((error
= git_repository_config(&cfg
, sm
->repo
)) < 0)
1460 /* write "submodule.NAME.url" */
1462 if ((error
= git_submodule__resolve_url(&effective_submodule_url
, sm
->repo
, sm
->url
)) < 0 ||
1463 (error
= git_str_printf(&key
, "submodule.%s.url", sm
->name
)) < 0 ||
1464 (error
= git_config__update_entry(
1465 cfg
, key
.ptr
, effective_submodule_url
.ptr
, overwrite
!= 0, false)) < 0)
1468 /* write "submodule.NAME.update" if not default */
1470 val
= (sm
->update
== GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1471 NULL
: submodule_update_to_str(sm
->update
);
1473 if ((error
= git_str_printf(&key
, "submodule.%s.update", sm
->name
)) < 0 ||
1474 (error
= git_config__update_entry(
1475 cfg
, key
.ptr
, val
, overwrite
!= 0, false)) < 0)
1481 git_config_free(cfg
);
1482 git_str_dispose(&key
);
1483 git_str_dispose(&effective_submodule_url
);
1488 int git_submodule_sync(git_submodule
*sm
)
1490 git_str key
= GIT_STR_INIT
, url
= GIT_STR_INIT
, remote_name
= GIT_STR_INIT
;
1491 git_repository
*smrepo
= NULL
;
1492 git_config
*cfg
= NULL
;
1496 git_error_set(GIT_ERROR_SUBMODULE
, "no URL configured for submodule '%s'", sm
->name
);
1500 /* copy URL over to config only if it already exists */
1501 if ((error
= git_repository_config__weakptr(&cfg
, sm
->repo
)) < 0 ||
1502 (error
= git_str_printf(&key
, "submodule.%s.url", sm
->name
)) < 0 ||
1503 (error
= git_submodule__resolve_url(&url
, sm
->repo
, sm
->url
)) < 0 ||
1504 (error
= git_config__update_entry(cfg
, key
.ptr
, url
.ptr
, true, true)) < 0)
1507 if (!(sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
))
1510 /* if submodule exists in the working directory, update remote url */
1511 if ((error
= git_submodule_open(&smrepo
, sm
)) < 0 ||
1512 (error
= git_repository_config__weakptr(&cfg
, smrepo
)) < 0)
1515 if (lookup_head_remote_key(&remote_name
, smrepo
) == 0) {
1516 if ((error
= git_str_join3(&key
, '.', "remote", remote_name
.ptr
, "url")) < 0)
1518 } else if ((error
= git_str_sets(&key
, "remote.origin.url")) < 0) {
1522 if ((error
= git_config__update_entry(cfg
, key
.ptr
, url
.ptr
, true, false)) < 0)
1526 git_repository_free(smrepo
);
1527 git_str_dispose(&remote_name
);
1528 git_str_dispose(&key
);
1529 git_str_dispose(&url
);
1533 static int git_submodule__open(
1534 git_repository
**subrepo
, git_submodule
*sm
, bool bare
)
1537 git_str path
= GIT_STR_INIT
;
1538 unsigned int flags
= GIT_REPOSITORY_OPEN_NO_SEARCH
;
1542 GIT_ASSERT_ARG(subrepo
);
1544 if (git_repository__ensure_not_bare(
1545 sm
->repo
, "open submodule repository") < 0)
1546 return GIT_EBAREREPO
;
1548 wd
= git_repository_workdir(sm
->repo
);
1550 if (git_str_join3(&path
, '/', wd
, sm
->path
, DOT_GIT
) < 0)
1553 sm
->flags
= sm
->flags
&
1554 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1555 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1556 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1559 flags
|= GIT_REPOSITORY_OPEN_BARE
;
1561 error
= git_repository_open_ext(subrepo
, path
.ptr
, flags
, wd
);
1563 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1565 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
|
1566 GIT_SUBMODULE_STATUS__WD_SCANNED
;
1568 if (!git_reference_name_to_id(&sm
->wd_oid
, *subrepo
, GIT_HEAD_FILE
))
1569 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_OID_VALID
;
1572 } else if (git_fs_path_exists(path
.ptr
)) {
1573 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
|
1574 GIT_SUBMODULE_STATUS_IN_WD
;
1576 git_str_rtruncate_at_char(&path
, '/'); /* remove "/.git" */
1578 if (git_fs_path_isdir(path
.ptr
))
1579 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1582 git_str_dispose(&path
);
1587 int git_submodule_open_bare(git_repository
**subrepo
, git_submodule
*sm
)
1589 return git_submodule__open(subrepo
, sm
, true);
1592 int git_submodule_open(git_repository
**subrepo
, git_submodule
*sm
)
1594 return git_submodule__open(subrepo
, sm
, false);
1597 static void submodule_update_from_index_entry(
1598 git_submodule
*sm
, const git_index_entry
*ie
)
1600 bool already_found
= (sm
->flags
& GIT_SUBMODULE_STATUS_IN_INDEX
) != 0;
1602 if (!S_ISGITLINK(ie
->mode
)) {
1604 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
1607 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
1609 git_oid_cpy(&sm
->index_oid
, &ie
->id
);
1611 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
1612 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
1616 static int submodule_update_index(git_submodule
*sm
)
1619 const git_index_entry
*ie
;
1621 if (git_repository_index__weakptr(&index
, sm
->repo
) < 0)
1624 sm
->flags
= sm
->flags
&
1625 ~(GIT_SUBMODULE_STATUS_IN_INDEX
|
1626 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
1628 if (!(ie
= git_index_get_bypath(index
, sm
->path
, 0)))
1631 submodule_update_from_index_entry(sm
, ie
);
1636 static void submodule_update_from_head_data(
1637 git_submodule
*sm
, mode_t mode
, const git_oid
*id
)
1639 if (!S_ISGITLINK(mode
))
1640 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
1642 git_oid_cpy(&sm
->head_oid
, id
);
1644 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
1645 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
1649 static int submodule_update_head(git_submodule
*submodule
)
1651 git_tree
*head
= NULL
;
1652 git_tree_entry
*te
= NULL
;
1654 submodule
->flags
= submodule
->flags
&
1655 ~(GIT_SUBMODULE_STATUS_IN_HEAD
|
1656 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
1658 /* if we can't look up file in current head, then done */
1659 if (git_repository_head_tree(&head
, submodule
->repo
) < 0 ||
1660 git_tree_entry_bypath(&te
, head
, submodule
->path
) < 0)
1663 submodule_update_from_head_data(submodule
, te
->attr
, git_tree_entry_id(te
));
1665 git_tree_entry_free(te
);
1666 git_tree_free(head
);
1670 int git_submodule_reload(git_submodule
*sm
, int force
)
1672 git_config
*mods
= NULL
;
1679 if ((error
= git_submodule_name_is_valid(sm
->repo
, sm
->name
, 0)) <= 0)
1680 /* This should come with a warning, but we've no API for that */
1683 if (git_repository_is_bare(sm
->repo
))
1686 /* refresh config data */
1687 if ((error
= gitmodules_snapshot(&mods
, sm
->repo
)) < 0 && error
!= GIT_ENOTFOUND
)
1690 if (mods
!= NULL
&& (error
= submodule_read_config(sm
, mods
)) < 0)
1693 /* refresh wd data */
1695 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1696 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1697 GIT_SUBMODULE_STATUS__WD_FLAGS
);
1699 if ((error
= submodule_load_from_wd_lite(sm
)) < 0 ||
1700 (error
= submodule_update_index(sm
)) < 0 ||
1701 (error
= submodule_update_head(sm
)) < 0)
1705 git_config_free(mods
);
1709 static void submodule_copy_oid_maybe(
1710 git_oid
*tgt
, const git_oid
*src
, bool valid
)
1714 memcpy(tgt
, src
, sizeof(*tgt
));
1716 memset(tgt
, 0, sizeof(*tgt
));
1720 int git_submodule__status(
1721 unsigned int *out_status
,
1722 git_oid
*out_head_id
,
1723 git_oid
*out_index_id
,
1726 git_submodule_ignore_t ign
)
1728 unsigned int status
;
1729 git_repository
*smrepo
= NULL
;
1731 if (ign
== GIT_SUBMODULE_IGNORE_UNSPECIFIED
)
1734 /* only return location info if ignore == all */
1735 if (ign
== GIT_SUBMODULE_IGNORE_ALL
) {
1736 *out_status
= (sm
->flags
& GIT_SUBMODULE_STATUS__IN_FLAGS
);
1740 /* If the user has requested caching submodule state, performing these
1741 * expensive operations (especially `submodule_update_head`, which is
1742 * bottlenecked on `git_repository_head_tree`) eliminates much of the
1743 * advantage. We will, therefore, interpret the request for caching to
1744 * apply here to and skip them.
1747 if (sm
->repo
->submodule_cache
== NULL
) {
1748 /* refresh the index OID */
1749 if (submodule_update_index(sm
) < 0)
1752 /* refresh the HEAD OID */
1753 if (submodule_update_head(sm
) < 0)
1757 /* for ignore == dirty, don't scan the working directory */
1758 if (ign
== GIT_SUBMODULE_IGNORE_DIRTY
) {
1759 /* git_submodule_open_bare will load WD OID data */
1760 if (git_submodule_open_bare(&smrepo
, sm
) < 0)
1763 git_repository_free(smrepo
);
1765 } else if (git_submodule_open(&smrepo
, sm
) < 0) {
1770 status
= GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm
->flags
);
1772 submodule_get_index_status(&status
, sm
);
1773 submodule_get_wd_status(&status
, sm
, smrepo
, ign
);
1775 git_repository_free(smrepo
);
1777 *out_status
= status
;
1779 submodule_copy_oid_maybe(out_head_id
, &sm
->head_oid
,
1780 (sm
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
) != 0);
1781 submodule_copy_oid_maybe(out_index_id
, &sm
->index_oid
,
1782 (sm
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
) != 0);
1783 submodule_copy_oid_maybe(out_wd_id
, &sm
->wd_oid
,
1784 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) != 0);
1789 int git_submodule_status(unsigned int *status
, git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1794 GIT_ASSERT_ARG(status
);
1795 GIT_ASSERT_ARG(repo
);
1796 GIT_ASSERT_ARG(name
);
1798 if ((error
= git_submodule_lookup(&sm
, repo
, name
)) < 0)
1801 error
= git_submodule__status(status
, NULL
, NULL
, NULL
, sm
, ignore
);
1802 git_submodule_free(sm
);
1807 int git_submodule_location(unsigned int *location
, git_submodule
*sm
)
1809 GIT_ASSERT_ARG(location
);
1812 return git_submodule__status(
1813 location
, NULL
, NULL
, NULL
, sm
, GIT_SUBMODULE_IGNORE_ALL
);
1817 * INTERNAL FUNCTIONS
1820 static int submodule_alloc(
1821 git_submodule
**out
, git_repository
*repo
, const char *name
)
1826 if (!name
|| !(namelen
= strlen(name
))) {
1827 git_error_set(GIT_ERROR_SUBMODULE
, "invalid submodule name");
1831 sm
= git__calloc(1, sizeof(git_submodule
));
1832 GIT_ERROR_CHECK_ALLOC(sm
);
1834 sm
->name
= sm
->path
= git__strdup(name
);
1840 GIT_REFCOUNT_INC(sm
);
1841 sm
->ignore
= sm
->ignore_default
= GIT_SUBMODULE_IGNORE_NONE
;
1842 sm
->update
= sm
->update_default
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1843 sm
->fetch_recurse
= sm
->fetch_recurse_default
= GIT_SUBMODULE_RECURSE_NO
;
1851 static void submodule_release(git_submodule
*sm
)
1860 if (sm
->path
!= sm
->name
)
1861 git__free(sm
->path
);
1862 git__free(sm
->name
);
1864 git__free(sm
->branch
);
1865 git__memzero(sm
, sizeof(*sm
));
1869 int git_submodule_dup(git_submodule
**out
, git_submodule
*source
)
1871 GIT_ASSERT_ARG(out
);
1872 GIT_ASSERT_ARG(source
);
1874 GIT_REFCOUNT_INC(source
);
1880 void git_submodule_free(git_submodule
*sm
)
1884 GIT_REFCOUNT_DEC(sm
, submodule_release
);
1887 static int submodule_config_error(const char *property
, const char *value
)
1889 git_error_set(GIT_ERROR_INVALID
,
1890 "invalid value for submodule '%s' property: '%s'", property
, value
);
1894 int git_submodule_parse_ignore(git_submodule_ignore_t
*out
, const char *value
)
1898 if (git_config_lookup_map_value(
1899 &val
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), value
) < 0) {
1900 *out
= GIT_SUBMODULE_IGNORE_NONE
;
1901 return submodule_config_error("ignore", value
);
1904 *out
= (git_submodule_ignore_t
)val
;
1908 int git_submodule_parse_update(git_submodule_update_t
*out
, const char *value
)
1912 if (git_config_lookup_map_value(
1913 &val
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), value
) < 0) {
1914 *out
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1915 return submodule_config_error("update", value
);
1918 *out
= (git_submodule_update_t
)val
;
1922 static int submodule_parse_recurse(git_submodule_recurse_t
*out
, const char *value
)
1926 if (git_config_lookup_map_value(
1927 &val
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), value
) < 0) {
1928 *out
= GIT_SUBMODULE_RECURSE_YES
;
1929 return submodule_config_error("recurse", value
);
1932 *out
= (git_submodule_recurse_t
)val
;
1936 static int get_value(const char **out
, git_config
*cfg
, git_str
*buf
, const char *name
, const char *field
)
1942 if ((error
= git_str_printf(buf
, "submodule.%s.%s", name
, field
)) < 0 ||
1943 (error
= git_config_get_string(out
, cfg
, buf
->ptr
)) < 0)
1949 static bool looks_like_command_line_option(const char *s
)
1951 if (s
&& s
[0] == '-')
1957 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
)
1959 git_str key
= GIT_STR_INIT
;
1961 int error
, in_config
= 0;
1964 * TODO: Look up path in index and if it is present but not a GITLINK
1965 * then this should be deleted (at least to match git's behavior)
1968 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "path")) == 0) {
1970 /* We would warn here if we had that API */
1971 if (!looks_like_command_line_option(value
)) {
1973 * TODO: if case insensitive filesystem, then the following strcmp
1974 * should be strcasecmp
1976 if (strcmp(sm
->name
, value
) != 0) {
1977 if (sm
->path
!= sm
->name
)
1978 git__free(sm
->path
);
1979 sm
->path
= git__strdup(value
);
1980 GIT_ERROR_CHECK_ALLOC(sm
->path
);
1984 } else if (error
!= GIT_ENOTFOUND
) {
1988 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "url")) == 0) {
1989 /* We would warn here if we had that API */
1990 if (!looks_like_command_line_option(value
)) {
1992 sm
->url
= git__strdup(value
);
1993 GIT_ERROR_CHECK_ALLOC(sm
->url
);
1995 } else if (error
!= GIT_ENOTFOUND
) {
1999 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "branch")) == 0) {
2001 sm
->branch
= git__strdup(value
);
2002 GIT_ERROR_CHECK_ALLOC(sm
->branch
);
2003 } else if (error
!= GIT_ENOTFOUND
) {
2007 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "update")) == 0) {
2009 if ((error
= git_submodule_parse_update(&sm
->update
, value
)) < 0)
2011 sm
->update_default
= sm
->update
;
2012 } else if (error
!= GIT_ENOTFOUND
) {
2016 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "fetchRecurseSubmodules")) == 0) {
2018 if ((error
= submodule_parse_recurse(&sm
->fetch_recurse
, value
)) < 0)
2020 sm
->fetch_recurse_default
= sm
->fetch_recurse
;
2021 } else if (error
!= GIT_ENOTFOUND
) {
2025 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "ignore")) == 0) {
2027 if ((error
= git_submodule_parse_ignore(&sm
->ignore
, value
)) < 0)
2029 sm
->ignore_default
= sm
->ignore
;
2030 } else if (error
!= GIT_ENOTFOUND
) {
2035 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
2040 git_str_dispose(&key
);
2044 static int submodule_load_each(const git_config_entry
*entry
, void *payload
)
2046 lfc_data
*data
= payload
;
2047 const char *namestart
, *property
;
2048 git_strmap
*map
= data
->map
;
2049 git_str name
= GIT_STR_INIT
;
2053 if (git__prefixcmp(entry
->name
, "submodule.") != 0)
2056 namestart
= entry
->name
+ strlen("submodule.");
2057 property
= strrchr(namestart
, '.');
2059 if (!property
|| (property
== namestart
))
2064 if ((error
= git_str_set(&name
, namestart
, property
- namestart
-1)) < 0)
2067 isvalid
= git_submodule_name_is_valid(data
->repo
, name
.ptr
, 0);
2074 * Now that we have the submodule's name, we can use that to
2075 * figure out whether it's in the map. If it's not, we create
2076 * a new submodule, load the config and insert it. If it's
2077 * already inserted, we've already loaded it, so we skip.
2079 if (git_strmap_exists(map
, name
.ptr
)) {
2084 if ((error
= submodule_alloc(&sm
, data
->repo
, name
.ptr
)) < 0)
2087 if ((error
= submodule_read_config(sm
, data
->mods
)) < 0) {
2088 git_submodule_free(sm
);
2092 if ((error
= git_strmap_set(map
, sm
->name
, sm
)) < 0)
2098 git_str_dispose(&name
);
2102 static int submodule_load_from_wd_lite(git_submodule
*sm
)
2104 git_str path
= GIT_STR_INIT
;
2106 if (git_repository_workdir_path(&path
, sm
->repo
, sm
->path
) < 0)
2109 if (git_fs_path_isdir(path
.ptr
))
2110 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
2112 if (git_fs_path_contains(&path
, DOT_GIT
))
2113 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
;
2115 git_str_dispose(&path
);
2120 * Requests a snapshot of $WORK_TREE/.gitmodules.
2122 * Returns GIT_ENOTFOUND in case no .gitmodules file exist
2124 static int gitmodules_snapshot(git_config
**snap
, git_repository
*repo
)
2126 git_config
*mods
= NULL
;
2127 git_str path
= GIT_STR_INIT
;
2130 if (git_repository_workdir(repo
) == NULL
)
2131 return GIT_ENOTFOUND
;
2133 if ((error
= git_repository_workdir_path(&path
, repo
, GIT_MODULES_FILE
)) < 0)
2136 if ((error
= git_config_open_ondisk(&mods
, path
.ptr
)) < 0)
2138 git_str_dispose(&path
);
2140 if ((error
= git_config_snapshot(snap
, mods
)) < 0)
2147 git_config_free(mods
);
2148 git_str_dispose(&path
);
2153 static git_config_backend
*open_gitmodules(
2154 git_repository
*repo
,
2157 git_str path
= GIT_STR_INIT
;
2158 git_config_backend
*mods
= NULL
;
2160 if (git_repository_workdir(repo
) != NULL
) {
2161 if (git_repository_workdir_path(&path
, repo
, GIT_MODULES_FILE
) != 0)
2164 if (okay_to_create
|| git_fs_path_isfile(path
.ptr
)) {
2165 /* git_config_backend_from_file should only fail if OOM */
2166 if (git_config_backend_from_file(&mods
, path
.ptr
) < 0)
2168 /* open should only fail here if the file is malformed */
2169 else if (git_config_backend_open(mods
, GIT_CONFIG_LEVEL_LOCAL
, repo
) < 0) {
2170 git_config_backend_free(mods
);
2176 git_str_dispose(&path
);
2181 /* Lookup name of remote of the local tracking branch HEAD points to */
2182 static int lookup_head_remote_key(git_str
*remote_name
, git_repository
*repo
)
2185 git_reference
*head
= NULL
;
2186 git_str upstream_name
= GIT_STR_INIT
;
2188 /* lookup and dereference HEAD */
2189 if ((error
= git_repository_head(&head
, repo
)) < 0)
2193 * If head does not refer to a branch, then return
2194 * GIT_ENOTFOUND to indicate that we could not find
2195 * a remote key for the local tracking branch HEAD points to.
2197 if (!git_reference_is_branch(head
)) {
2198 git_error_set(GIT_ERROR_INVALID
,
2199 "HEAD does not refer to a branch.");
2200 error
= GIT_ENOTFOUND
;
2204 /* lookup remote tracking branch of HEAD */
2205 if ((error
= git_branch__upstream_name(
2208 git_reference_name(head
))) < 0)
2211 /* lookup remote of remote tracking branch */
2212 if ((error
= git_branch__remote_name(remote_name
, repo
, upstream_name
.ptr
)) < 0)
2216 git_str_dispose(&upstream_name
);
2217 git_reference_free(head
);
2222 /* Lookup the remote of the local tracking branch HEAD points to */
2223 static int lookup_head_remote(git_remote
**remote
, git_repository
*repo
)
2226 git_str remote_name
= GIT_STR_INIT
;
2228 /* lookup remote of remote tracking branch name */
2229 if (!(error
= lookup_head_remote_key(&remote_name
, repo
)))
2230 error
= git_remote_lookup(remote
, repo
, remote_name
.ptr
);
2232 git_str_dispose(&remote_name
);
2237 /* Lookup remote, either from HEAD or fall back on origin */
2238 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
)
2240 int error
= lookup_head_remote(remote
, repo
);
2242 /* if that failed, use 'origin' instead */
2243 if (error
== GIT_ENOTFOUND
|| error
== GIT_EUNBORNBRANCH
)
2244 error
= git_remote_lookup(remote
, repo
, "origin");
2246 if (error
== GIT_ENOTFOUND
)
2248 GIT_ERROR_SUBMODULE
,
2249 "cannot get default remote for submodule - no local tracking "
2250 "branch for HEAD and origin does not exist");
2255 static int get_url_base(git_str
*url
, git_repository
*repo
)
2258 git_worktree
*wt
= NULL
;
2259 git_remote
*remote
= NULL
;
2261 if ((error
= lookup_default_remote(&remote
, repo
)) == 0) {
2262 error
= git_str_sets(url
, git_remote_url(remote
));
2264 } else if (error
!= GIT_ENOTFOUND
)
2269 /* if repository does not have a default remote, use workdir instead */
2270 if (git_repository_is_worktree(repo
)) {
2271 if ((error
= git_worktree_open_from_repository(&wt
, repo
)) < 0)
2273 error
= git_str_sets(url
, wt
->parent_path
);
2275 error
= git_str_sets(url
, git_repository_workdir(repo
));
2279 git_remote_free(remote
);
2280 git_worktree_free(wt
);
2285 static void submodule_get_index_status(unsigned int *status
, git_submodule
*sm
)
2287 const git_oid
*head_oid
= git_submodule_head_id(sm
);
2288 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2290 *status
= *status
& ~GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
2294 *status
|= GIT_SUBMODULE_STATUS_INDEX_ADDED
;
2296 else if (!index_oid
)
2297 *status
|= GIT_SUBMODULE_STATUS_INDEX_DELETED
;
2298 else if (!git_oid_equal(head_oid
, index_oid
))
2299 *status
|= GIT_SUBMODULE_STATUS_INDEX_MODIFIED
;
2303 static void submodule_get_wd_status(
2304 unsigned int *status
,
2306 git_repository
*sm_repo
,
2307 git_submodule_ignore_t ign
)
2309 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2310 const git_oid
*wd_oid
=
2311 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) ? &sm
->wd_oid
: NULL
;
2312 git_tree
*sm_head
= NULL
;
2313 git_index
*index
= NULL
;
2314 git_diff_options opt
= GIT_DIFF_OPTIONS_INIT
;
2317 *status
= *status
& ~GIT_SUBMODULE_STATUS__WD_FLAGS
;
2321 *status
|= GIT_SUBMODULE_STATUS_WD_ADDED
;
2324 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_SCANNED
) != 0 &&
2325 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) == 0)
2326 *status
|= GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
;
2328 *status
|= GIT_SUBMODULE_STATUS_WD_DELETED
;
2330 else if (!git_oid_equal(index_oid
, wd_oid
))
2331 *status
|= GIT_SUBMODULE_STATUS_WD_MODIFIED
;
2333 /* if we have no repo, then we're done */
2337 /* the diffs below could be optimized with an early termination
2338 * option to the git_diff functions, but for now this is sufficient
2339 * (and certainly no worse that what core git does).
2342 if (ign
== GIT_SUBMODULE_IGNORE_NONE
)
2343 opt
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
2345 (void)git_repository_index__weakptr(&index
, sm_repo
);
2347 /* if we don't have an unborn head, check diff with index */
2348 if (git_repository_head_tree(&sm_head
, sm_repo
) < 0)
2351 /* perform head to index diff on submodule */
2352 if (git_diff_tree_to_index(&diff
, sm_repo
, sm_head
, index
, &opt
) < 0)
2355 if (git_diff_num_deltas(diff
) > 0)
2356 *status
|= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
2357 git_diff_free(diff
);
2361 git_tree_free(sm_head
);
2364 /* perform index-to-workdir diff on submodule */
2365 if (git_diff_index_to_workdir(&diff
, sm_repo
, index
, &opt
) < 0)
2369 git_diff_num_deltas_of_type(diff
, GIT_DELTA_UNTRACKED
);
2372 *status
|= GIT_SUBMODULE_STATUS_WD_UNTRACKED
;
2374 if (git_diff_num_deltas(diff
) != untracked
)
2375 *status
|= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
;
2377 git_diff_free(diff
);