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.
10 #include "git2/config.h"
11 #include "git2/sys/config.h"
12 #include "git2/types.h"
13 #include "git2/index.h"
17 #include "config_backend.h"
19 #include "repository.h"
27 #define GIT_MODULES_FILE ".gitmodules"
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
},
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
},
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
},
59 GITMODULES_EXISTING
= 0,
60 GITMODULES_CREATE
= 1,
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
);
77 static int submodule_cmp(const void *a
, const void *b
)
79 return strcmp(((git_submodule
*)a
)->name
, ((git_submodule
*)b
)->name
);
82 static int submodule_config_key_trunc_puts(git_buf
*key
, const char *suffix
)
84 ssize_t idx
= git_buf_rfind(key
, '.');
85 git_buf_truncate(key
, (size_t)(idx
+ 1));
86 return git_buf_puts(key
, suffix
);
93 static void submodule_set_lookup_error(int error
, const char *name
)
98 git_error_set(GIT_ERROR_SUBMODULE
, (error
== GIT_ENOTFOUND
) ?
99 "no submodule named '%s'" :
100 "submodule '%s' has not been added yet", name
);
108 static int find_by_path(const git_config_entry
*entry
, void *payload
)
110 fbp_data
*data
= payload
;
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
);
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.
127 static int is_path_occupied(bool *occupied
, git_repository
*repo
, const char *path
)
131 git_buf dir
= GIT_BUF_INIT
;
134 if ((error
= git_repository_index__weakptr(&index
, repo
)) < 0)
137 if ((error
= git_index_find(NULL
, index
, path
)) != GIT_ENOTFOUND
) {
139 git_error_set(GIT_ERROR_SUBMODULE
,
140 "File '%s' already exists in the index", path
);
146 if ((error
= git_buf_sets(&dir
, path
)) < 0)
149 if ((error
= git_path_to_dir(&dir
)) < 0)
152 if ((error
= git_index_find_prefix(NULL
, index
, dir
.ptr
)) != GIT_ENOTFOUND
) {
154 git_error_set(GIT_ERROR_SUBMODULE
,
155 "Directory '%s' already exists in the index", path
);
164 git_buf_dispose(&dir
);
169 * Release the name map returned by 'load_submodule_names'.
171 static void free_submodule_names(git_strmap
*names
)
179 git_strmap_foreach(names
, key
, value
, {
180 git__free((char *) key
);
183 git_strmap_free(names
);
189 * Map submodule paths to names.
190 * TODO: for some use-cases, this might need case-folding on a
191 * case-insensitive filesystem
193 static int load_submodule_names(git_strmap
**out
, git_repository
*repo
, git_config
*cfg
)
195 const char *key
= "submodule\\..*\\.path";
196 git_config_iterator
*iter
= NULL
;
197 git_config_entry
*entry
;
198 git_buf buf
= GIT_BUF_INIT
;
204 if ((error
= git_strmap_new(&names
)) < 0)
207 if ((error
= git_config_iterator_glob_new(&iter
, cfg
, key
)) < 0)
210 while ((error
= git_config_next(&entry
, iter
)) == 0) {
211 const char *fdot
, *ldot
;
212 fdot
= strchr(entry
->name
, '.');
213 ldot
= strrchr(entry
->name
, '.');
215 if (git_strmap_exists(names
, entry
->value
)) {
216 git_error_set(GIT_ERROR_SUBMODULE
,
217 "duplicated submodule path '%s'", entry
->value
);
223 git_buf_put(&buf
, fdot
+ 1, ldot
- fdot
- 1);
224 isvalid
= git_submodule_name_is_valid(repo
, buf
.ptr
, 0);
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");
238 if (error
== GIT_ITEROVER
)
245 free_submodule_names(names
);
246 git_buf_dispose(&buf
);
247 git_config_iterator_free(iter
);
251 int git_submodule_cache_init(git_strmap
**out
, git_repository
*repo
)
254 git_strmap
*cache
= NULL
;
256 GIT_ASSERT_ARG(repo
);
257 if ((error
= git_strmap_new(&cache
)) < 0)
259 if ((error
= git_submodule__map(repo
, cache
)) < 0) {
260 git_submodule_cache_free(cache
);
267 int git_submodule_cache_free(git_strmap
*cache
)
269 git_submodule
*sm
= NULL
;
272 git_strmap_foreach_value(cache
, sm
, {
273 git_submodule_free(sm
);
275 git_strmap_free(cache
);
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 */
284 return git_submodule__lookup_with_cache(out
, repo
, name
, repo
->submodule_cache
);
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 */
294 unsigned int location
;
297 GIT_ASSERT_ARG(repo
);
298 GIT_ASSERT_ARG(name
);
301 git_error_set(GIT_ERROR_SUBMODULE
, "cannot get submodules without a working tree");
306 if ((sm
= git_strmap_get(cache
, name
)) != NULL
) {
309 GIT_REFCOUNT_INC(*out
);
315 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
318 if ((error
= git_submodule_reload(sm
, false)) < 0) {
319 git_submodule_free(sm
);
323 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
324 git_submodule_free(sm
);
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
};
335 git_buf_puts(&path
, name
);
336 while (path
.ptr
[path
.size
-1] == '/') {
337 path
.ptr
[--path
.size
] = '\0';
339 data
.path
= path
.ptr
;
341 mods
= open_gitmodules(repo
, GITMODULES_EXISTING
);
344 error
= git_config_backend_foreach_match(mods
, pattern
, find_by_path
, &data
);
346 git_config_backend_free(mods
);
349 git_submodule_free(sm
);
350 git_buf_dispose(&path
);
356 sm
->name
= data
.name
;
357 sm
->path
= git_buf_detach(&path
);
359 /* Try to load again with the right name */
360 if ((error
= git_submodule_reload(sm
, false)) < 0) {
361 git_submodule_free(sm
);
366 git_buf_dispose(&path
);
369 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
370 git_submodule_free(sm
);
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
;
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)
388 if (git_path_exists(path
.ptr
))
391 git_buf_dispose(&path
);
394 submodule_set_lookup_error(error
, name
);
401 git_submodule_free(sm
);
406 int git_submodule_name_is_valid(git_repository
*repo
, const char *name
, int flags
)
408 git_buf buf
= GIT_BUF_INIT
;
412 flags
= GIT_PATH_REJECT_FILESYSTEM_DEFAULTS
;
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)
419 git_buf_attach_notowned(&buf
, name
, strlen(name
));
422 isvalid
= git_path_validate(repo
, buf
.ptr
, 0, flags
);
423 git_buf_dispose(&buf
);
428 static void submodule_free_dup(void *sm
)
430 git_submodule_free(sm
);
433 static int submodule_get_or_create(git_submodule
**out
, git_repository
*repo
, git_strmap
*map
, const char *name
)
435 git_submodule
*sm
= NULL
;
438 if ((sm
= git_strmap_get(map
, name
)) != NULL
)
441 /* if the submodule doesn't exist yet in the map, create it */
442 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
445 if ((error
= git_strmap_set(map
, sm
->name
, sm
)) < 0) {
446 git_submodule_free(sm
);
451 GIT_REFCOUNT_INC(sm
);
456 static int submodules_from_index(git_strmap
*map
, git_index
*idx
, git_config
*cfg
)
459 git_iterator
*i
= NULL
;
460 const git_index_entry
*entry
;
463 if ((error
= load_submodule_names(&names
, git_index_owner(idx
), cfg
)))
466 if ((error
= git_iterator_for_index(&i
, git_index_owner(idx
), idx
, NULL
)) < 0)
469 while (!(error
= git_iterator_advance(&entry
, i
))) {
472 if ((sm
= git_strmap_get(map
, entry
->path
)) != NULL
) {
473 if (S_ISGITLINK(entry
->mode
))
474 submodule_update_from_index_entry(sm
, entry
);
476 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
477 } else if (S_ISGITLINK(entry
->mode
)) {
480 if ((name
= git_strmap_get(names
, entry
->path
)) == NULL
)
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
);
490 if (error
== GIT_ITEROVER
)
494 git_iterator_free(i
);
495 free_submodule_names(names
);
500 static int submodules_from_head(git_strmap
*map
, git_tree
*head
, git_config
*cfg
)
503 git_iterator
*i
= NULL
;
504 const git_index_entry
*entry
;
507 if ((error
= load_submodule_names(&names
, git_tree_owner(head
), cfg
)))
510 if ((error
= git_iterator_for_tree(&i
, head
, NULL
)) < 0)
513 while (!(error
= git_iterator_advance(&entry
, i
))) {
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
);
520 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
521 } else if (S_ISGITLINK(entry
->mode
)) {
524 if ((name
= git_strmap_get(names
, entry
->path
)) == NULL
)
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
);
535 if (error
== GIT_ITEROVER
)
539 git_iterator_free(i
);
540 free_submodule_names(names
);
545 /* If have_sm is true, sm is populated, otherwise map an repo are. */
549 git_repository
*repo
;
552 int git_submodule__map(git_repository
*repo
, git_strmap
*map
)
555 git_index
*idx
= NULL
;
556 git_tree
*head
= NULL
;
557 git_buf path
= GIT_BUF_INIT
;
559 git_config
*mods
= NULL
;
562 GIT_ASSERT_ARG(repo
);
565 /* get sources that we will need to check */
566 if (git_repository_index(&idx
, repo
) < 0)
568 if (git_repository_head_tree(&head
, repo
) < 0)
571 has_workdir
= git_repository_workdir(repo
) != NULL
;
574 (error
= git_repository_workdir_path(&path
, repo
, GIT_MODULES_FILE
)) < 0)
577 /* add submodule information from .gitmodules */
579 lfc_data data
= { 0 };
583 if ((error
= gitmodules_snapshot(&mods
, repo
)) < 0) {
584 if (error
== GIT_ENOTFOUND
)
590 if ((error
= git_config_foreach(
591 mods
, submodule_load_each
, &data
)) < 0)
594 /* add back submodule information from index */
596 if ((error
= submodules_from_index(map
, idx
, mods
)) < 0)
599 /* add submodule information from HEAD */
601 if ((error
= submodules_from_head(map
, head
, mods
)) < 0)
604 /* shallow scan submodules in work tree as needed */
606 git_strmap_foreach_value(map
, sm
, {
607 submodule_load_from_wd_lite(sm
);
612 git_config_free(mods
);
613 /* TODO: if we got an error, mark submodule config as invalid? */
616 git_buf_dispose(&path
);
620 int git_submodule_foreach(
621 git_repository
*repo
,
622 git_submodule_cb callback
,
625 git_vector snapshot
= GIT_VECTOR_INIT
;
626 git_strmap
*submodules
;
632 git_error_set(GIT_ERROR_SUBMODULE
, "cannot get submodules without a working tree");
636 if ((error
= git_strmap_new(&submodules
)) < 0)
639 if ((error
= git_submodule__map(repo
, submodules
)) < 0)
642 if (!(error
= git_vector_init(
643 &snapshot
, git_strmap_size(submodules
), submodule_cmp
))) {
645 git_strmap_foreach_value(submodules
, sm
, {
646 if ((error
= git_vector_insert(&snapshot
, sm
)) < 0)
648 GIT_REFCOUNT_INC(sm
);
655 git_vector_uniq(&snapshot
, submodule_free_dup
);
657 git_vector_foreach(&snapshot
, i
, sm
) {
658 if ((error
= callback(sm
, sm
->name
, payload
)) != 0) {
659 git_error_set_after_callback(error
);
665 git_vector_foreach(&snapshot
, i
, sm
)
666 git_submodule_free(sm
);
667 git_vector_free(&snapshot
);
669 git_strmap_foreach_value(submodules
, sm
, {
670 git_submodule_free(sm
);
672 git_strmap_free(submodules
);
677 static int submodule_repo_init(
678 git_repository
**out
,
679 git_repository
*parent_repo
,
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
;
689 error
= git_repository_workdir_path(&workdir
, parent_repo
, path
);
693 initopt
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_NO_REINIT
;
694 initopt
.origin_url
= url
;
696 /* init submodule repository and add origin remote as needed */
698 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
699 * gitlink in the sub-repo workdir directory to that repository
701 * Old style: sub-repo goes directly into repo/<name>/.git/
704 error
= git_repository_item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
707 error
= git_buf_joinpath(&repodir
, repodir
.ptr
, path
);
711 initopt
.workdir_path
= workdir
.ptr
;
713 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
714 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
716 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
718 error
= git_repository_init_ext(&subrepo
, workdir
.ptr
, &initopt
);
721 git_buf_dispose(&workdir
);
722 git_buf_dispose(&repodir
);
729 int git_submodule_add_setup(
731 git_repository
*repo
,
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
;
743 GIT_ASSERT_ARG(repo
);
745 GIT_ASSERT_ARG(path
);
747 /* see if there is already an entry for this submodule */
749 if (git_submodule_lookup(NULL
, repo
, path
) < 0)
752 git_error_set(GIT_ERROR_SUBMODULE
,
753 "attempt to add submodule '%s' that already exists", path
);
757 /* validate and normalize path */
759 if (git__prefixcmp(path
, git_repository_workdir(repo
)) == 0)
760 path
+= strlen(git_repository_workdir(repo
));
762 if (git_path_root(path
) >= 0) {
763 git_error_set(GIT_ERROR_SUBMODULE
, "submodule path must be a relative path");
768 if ((error
= is_path_occupied(&path_occupied
, repo
, path
)) < 0)
776 /* update .gitmodules */
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");
784 if ((error
= git_buf_printf(&name
, "submodule.%s.path", path
)) < 0 ||
785 (error
= git_config_backend_set_string(mods
, name
.ptr
, path
)) < 0)
788 if ((error
= submodule_config_key_trunc_puts(&name
, "url")) < 0 ||
789 (error
= git_config_backend_set_string(mods
, name
.ptr
, url
)) < 0)
792 git_buf_clear(&name
);
794 /* init submodule repository and add origin remote as needed */
796 error
= git_repository_workdir_path(&name
, repo
, path
);
800 /* if the repo does not already exist, then init a new repo and add it.
801 * Otherwise, just add the existing repo.
803 if (!(git_path_exists(name
.ptr
) &&
804 git_path_contains(&name
, DOT_GIT
))) {
806 /* resolve the actual URL to use */
807 if ((error
= git_submodule_resolve_url(&real_url
, repo
, url
)) < 0)
810 if ((error
= submodule_repo_init(&subrepo
, repo
, path
, real_url
.ptr
, use_gitlink
)) < 0)
814 if ((error
= git_submodule_lookup(&sm
, repo
, path
)) < 0)
817 error
= git_submodule_init(sm
, false);
821 git_submodule_free(sm
);
827 git_config_backend_free(mods
);
828 git_repository_free(subrepo
);
829 git_buf_dispose(&real_url
);
830 git_buf_dispose(&name
);
835 int git_submodule_repo_init(
836 git_repository
**out
,
837 const git_submodule
*sm
,
841 git_repository
*sub_repo
= NULL
;
842 const char *configured_url
;
843 git_config
*cfg
= NULL
;
844 git_buf buf
= GIT_BUF_INIT
;
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)
859 git_config_free(cfg
);
860 git_buf_dispose(&buf
);
864 static int clone_return_origin(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, void *payload
)
868 return git_remote_lookup(out
, repo
, name
);
871 static int clone_return_repo(git_repository
**out
, const char *path
, int bare
, void *payload
)
873 git_submodule
*sm
= payload
;
877 return git_submodule_open(out
, sm
);
880 int git_submodule_clone(git_repository
**out
, git_submodule
*submodule
, const git_submodule_update_options
*given_opts
)
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
;
888 GIT_ASSERT_ARG(submodule
);
891 memcpy(&sub_opts
, given_opts
, sizeof(sub_opts
));
893 GIT_ERROR_CHECK_VERSION(&sub_opts
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
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
;
902 error
= git_repository_workdir_path(&rel_path
, git_submodule_owner(submodule
), git_submodule_path(submodule
));
906 error
= git_clone__submodule(&clone
, git_submodule_url(submodule
), git_buf_cstr(&rel_path
), &opts
);
911 git_repository_free(clone
);
916 git_buf_dispose(&rel_path
);
921 int git_submodule_add_finalize(git_submodule
*sm
)
928 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
929 (error
= git_index_add_bypath(index
, GIT_MODULES_FILE
)) < 0)
932 return git_submodule_add_to_index(sm
, true);
935 int git_submodule_add_to_index(git_submodule
*sm
, int write_index
)
938 git_repository
*sm_repo
= NULL
;
940 git_buf path
= GIT_BUF_INIT
;
942 git_index_entry entry
;
947 /* force reload of wd OID by git_submodule_open */
948 sm
->flags
= sm
->flags
& ~GIT_SUBMODULE_STATUS__WD_OID_VALID
;
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)
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");
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
));
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");
975 git_oid_cpy(&entry
.id
, &sm
->wd_oid
);
977 if ((error
= git_commit_lookup(&head
, sm_repo
, &sm
->wd_oid
)) < 0)
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;
985 git_commit_free(head
);
988 error
= git_index_add(index
, &entry
);
990 /* write it, if requested */
991 if (!error
&& write_index
) {
992 error
= git_index_write(index
);
995 git_oid_cpy(&sm
->index_oid
, &sm
->wd_oid
);
999 git_repository_free(sm_repo
);
1000 git_buf_dispose(&path
);
1004 static const char *submodule_update_to_str(git_submodule_update_t update
)
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
;
1013 git_repository
*git_submodule_owner(git_submodule
*submodule
)
1015 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1016 return submodule
->repo
;
1019 const char *git_submodule_name(git_submodule
*submodule
)
1021 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1022 return submodule
->name
;
1025 const char *git_submodule_path(git_submodule
*submodule
)
1027 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1028 return submodule
->path
;
1031 const char *git_submodule_url(git_submodule
*submodule
)
1033 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1034 return submodule
->url
;
1037 int git_submodule_resolve_url(git_buf
*out
, git_repository
*repo
, const char *url
)
1040 git_buf normalized
= GIT_BUF_INIT
;
1042 GIT_ASSERT_ARG(out
);
1043 GIT_ASSERT_ARG(repo
);
1044 GIT_ASSERT_ARG(url
);
1046 if ((error
= git_buf_sanitize(out
)) < 0)
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)
1054 url
= normalized
.ptr
;
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
);
1064 git_error_set(GIT_ERROR_SUBMODULE
, "invalid format for submodule URL");
1068 git_buf_dispose(&normalized
);
1072 static int write_var(git_repository
*repo
, const char *name
, const char *var
, const char *val
)
1074 git_buf key
= GIT_BUF_INIT
;
1075 git_config_backend
*mods
;
1078 mods
= open_gitmodules(repo
, GITMODULES_CREATE
);
1082 if ((error
= git_buf_printf(&key
, "submodule.%s.%s", name
, var
)) < 0)
1086 error
= git_config_backend_set_string(mods
, key
.ptr
, val
);
1088 error
= git_config_backend_delete(mods
, key
.ptr
);
1090 git_buf_dispose(&key
);
1093 git_config_backend_free(mods
);
1097 static int write_mapped_var(git_repository
*repo
, const char *name
, git_configmap
*maps
, size_t nmaps
, const char *var
, int ival
)
1099 git_configmap_t type
;
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
);
1107 if (type
== GIT_CONFIGMAP_TRUE
)
1110 return write_var(repo
, name
, var
, val
);
1113 const char *git_submodule_branch(git_submodule
*submodule
)
1115 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1116 return submodule
->branch
;
1119 int git_submodule_set_branch(git_repository
*repo
, const char *name
, const char *branch
)
1121 GIT_ASSERT_ARG(repo
);
1122 GIT_ASSERT_ARG(name
);
1124 return write_var(repo
, name
, "branch", branch
);
1127 int git_submodule_set_url(git_repository
*repo
, const char *name
, const char *url
)
1129 GIT_ASSERT_ARG(repo
);
1130 GIT_ASSERT_ARG(name
);
1131 GIT_ASSERT_ARG(url
);
1133 return write_var(repo
, name
, "url", url
);
1136 const git_oid
*git_submodule_index_id(git_submodule
*submodule
)
1138 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1140 if (submodule
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
1141 return &submodule
->index_oid
;
1146 const git_oid
*git_submodule_head_id(git_submodule
*submodule
)
1148 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1150 if (submodule
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
1151 return &submodule
->head_oid
;
1156 const git_oid
*git_submodule_wd_id(git_submodule
*submodule
)
1158 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, NULL
);
1160 /* load unless we think we have a valid oid */
1161 if (!(submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)) {
1162 git_repository
*subrepo
;
1164 /* calling submodule open grabs the HEAD OID if possible */
1165 if (!git_submodule_open_bare(&subrepo
, submodule
))
1166 git_repository_free(subrepo
);
1171 if (submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)
1172 return &submodule
->wd_oid
;
1177 git_submodule_ignore_t
git_submodule_ignore(git_submodule
*submodule
)
1179 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
);
1181 return (submodule
->ignore
< GIT_SUBMODULE_IGNORE_NONE
) ?
1182 GIT_SUBMODULE_IGNORE_NONE
: submodule
->ignore
;
1185 int git_submodule_set_ignore(git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1187 GIT_ASSERT_ARG(repo
);
1188 GIT_ASSERT_ARG(name
);
1190 return write_mapped_var(repo
, name
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), "ignore", ignore
);
1193 git_submodule_update_t
git_submodule_update_strategy(git_submodule
*submodule
)
1195 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, GIT_SUBMODULE_UPDATE_NONE
);
1197 return (submodule
->update
< GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1198 GIT_SUBMODULE_UPDATE_CHECKOUT
: submodule
->update
;
1201 int git_submodule_set_update(git_repository
*repo
, const char *name
, git_submodule_update_t update
)
1203 GIT_ASSERT_ARG(repo
);
1204 GIT_ASSERT_ARG(name
);
1206 return write_mapped_var(repo
, name
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), "update", update
);
1209 git_submodule_recurse_t
git_submodule_fetch_recurse_submodules(
1210 git_submodule
*submodule
)
1212 GIT_ASSERT_ARG_WITH_RETVAL(submodule
, GIT_SUBMODULE_RECURSE_NO
);
1213 return submodule
->fetch_recurse
;
1216 int git_submodule_set_fetch_recurse_submodules(git_repository
*repo
, const char *name
, git_submodule_recurse_t recurse
)
1218 GIT_ASSERT_ARG(repo
);
1219 GIT_ASSERT_ARG(name
);
1221 return write_mapped_var(repo
, name
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), "fetchRecurseSubmodules", recurse
);
1224 static int submodule_repo_create(
1225 git_repository
**out
,
1226 git_repository
*parent_repo
,
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
;
1235 GIT_REPOSITORY_INIT_MKPATH
|
1236 GIT_REPOSITORY_INIT_NO_REINIT
|
1237 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
1238 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
1240 /* Workdir: path to sub-repo working directory */
1241 error
= git_repository_workdir_path(&workdir
, parent_repo
, path
);
1245 initopt
.workdir_path
= workdir
.ptr
;
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.
1252 error
= git_repository_item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
1255 error
= git_buf_joinpath(&repodir
, repodir
.ptr
, path
);
1259 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
1262 git_buf_dispose(&workdir
);
1263 git_buf_dispose(&repodir
);
1271 * Callback to override sub-repository creation when
1272 * cloning a sub-repository.
1274 static int git_submodule_update_repo_init_cb(
1275 git_repository
**out
,
1286 return submodule_repo_create(out
, sm
->repo
, path
);
1289 int git_submodule_update_options_init(git_submodule_update_options
*opts
, unsigned int version
)
1291 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1292 opts
, version
, git_submodule_update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_INIT
);
1296 #ifndef GIT_DEPRECATE_HARD
1297 int git_submodule_update_init_options(git_submodule_update_options
*opts
, unsigned int version
)
1299 return git_submodule_update_options_init(opts
, version
);
1303 int git_submodule_update(git_submodule
*sm
, int init
, git_submodule_update_options
*_update_options
)
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
;
1318 if (_update_options
)
1319 memcpy(&update_options
, _update_options
, sizeof(git_submodule_update_options
));
1321 GIT_ERROR_CHECK_VERSION(&update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
1323 /* Copy over the remote callbacks */
1324 memcpy(&clone_options
.fetch_opts
, &update_options
.fetch_opts
, sizeof(git_fetch_options
));
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)
1331 * If submodule work dir is not already initialized, check to see
1332 * what we need to do (initialize, clone, return error...)
1334 if (submodule_status
& GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
) {
1336 * Work dir is not initialized, check to see if the submodule
1337 * info has been copied into .git/config
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)
1343 if ((error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0) {
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.
1348 if (error
!= GIT_ENOTFOUND
)
1352 git_error_set(GIT_ERROR_SUBMODULE
, "submodule is not initialized");
1357 /* The submodule has not been initialized yet - initialize it now.*/
1358 if ((error
= git_submodule_init(sm
, 0)) < 0)
1361 git_config_free(config
);
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)
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
;
1375 * Do not perform checkout as part of clone, instead we
1376 * will checkout the specific commit manually.
1378 clone_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
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)
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.
1392 if ((error
= git_submodule_open(&sub_repo
, sm
)) < 0)
1395 if ((oid
= git_submodule_index_id(sm
)) == NULL
) {
1396 git_error_set(GIT_ERROR_SUBMODULE
, "could not get ID of submodule in index");
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)
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)
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
);
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
);
1432 int git_submodule_init(git_submodule
*sm
, int overwrite
)
1436 git_buf key
= GIT_BUF_INIT
, effective_submodule_url
= GIT_BUF_INIT
;
1437 git_config
*cfg
= NULL
;
1440 git_error_set(GIT_ERROR_SUBMODULE
,
1441 "no URL configured for submodule '%s'", sm
->name
);
1445 if ((error
= git_repository_config(&cfg
, sm
->repo
)) < 0)
1448 /* write "submodule.NAME.url" */
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)
1456 /* write "submodule.NAME.update" if not default */
1458 val
= (sm
->update
== GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1459 NULL
: submodule_update_to_str(sm
->update
);
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)
1469 git_config_free(cfg
);
1470 git_buf_dispose(&key
);
1471 git_buf_dispose(&effective_submodule_url
);
1476 int git_submodule_sync(git_submodule
*sm
)
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
;
1484 git_error_set(GIT_ERROR_SUBMODULE
, "no URL configured for submodule '%s'", sm
->name
);
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)
1495 if (!(sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
))
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)
1503 if (lookup_head_remote_key(&remote_name
, smrepo
) == 0) {
1504 if ((error
= git_buf_join3(&key
, '.', "remote", remote_name
.ptr
, "url")) < 0)
1506 } else if ((error
= git_buf_sets(&key
, "remote.origin.url")) < 0) {
1510 if ((error
= git_config__update_entry(cfg
, key
.ptr
, url
.ptr
, true, false)) < 0)
1514 git_repository_free(smrepo
);
1515 git_buf_dispose(&remote_name
);
1516 git_buf_dispose(&key
);
1517 git_buf_dispose(&url
);
1521 static int git_submodule__open(
1522 git_repository
**subrepo
, git_submodule
*sm
, bool bare
)
1525 git_buf path
= GIT_BUF_INIT
;
1526 unsigned int flags
= GIT_REPOSITORY_OPEN_NO_SEARCH
;
1530 GIT_ASSERT_ARG(subrepo
);
1532 if (git_repository__ensure_not_bare(
1533 sm
->repo
, "open submodule repository") < 0)
1534 return GIT_EBAREREPO
;
1536 wd
= git_repository_workdir(sm
->repo
);
1538 if (git_buf_join3(&path
, '/', wd
, sm
->path
, DOT_GIT
) < 0)
1541 sm
->flags
= sm
->flags
&
1542 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1543 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1544 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1547 flags
|= GIT_REPOSITORY_OPEN_BARE
;
1549 error
= git_repository_open_ext(subrepo
, path
.ptr
, flags
, wd
);
1551 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1553 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
|
1554 GIT_SUBMODULE_STATUS__WD_SCANNED
;
1556 if (!git_reference_name_to_id(&sm
->wd_oid
, *subrepo
, GIT_HEAD_FILE
))
1557 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_OID_VALID
;
1560 } else if (git_path_exists(path
.ptr
)) {
1561 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
|
1562 GIT_SUBMODULE_STATUS_IN_WD
;
1564 git_buf_rtruncate_at_char(&path
, '/'); /* remove "/.git" */
1566 if (git_path_isdir(path
.ptr
))
1567 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1570 git_buf_dispose(&path
);
1575 int git_submodule_open_bare(git_repository
**subrepo
, git_submodule
*sm
)
1577 return git_submodule__open(subrepo
, sm
, true);
1580 int git_submodule_open(git_repository
**subrepo
, git_submodule
*sm
)
1582 return git_submodule__open(subrepo
, sm
, false);
1585 static void submodule_update_from_index_entry(
1586 git_submodule
*sm
, const git_index_entry
*ie
)
1588 bool already_found
= (sm
->flags
& GIT_SUBMODULE_STATUS_IN_INDEX
) != 0;
1590 if (!S_ISGITLINK(ie
->mode
)) {
1592 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
1595 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
1597 git_oid_cpy(&sm
->index_oid
, &ie
->id
);
1599 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
1600 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
1604 static int submodule_update_index(git_submodule
*sm
)
1607 const git_index_entry
*ie
;
1609 if (git_repository_index__weakptr(&index
, sm
->repo
) < 0)
1612 sm
->flags
= sm
->flags
&
1613 ~(GIT_SUBMODULE_STATUS_IN_INDEX
|
1614 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
1616 if (!(ie
= git_index_get_bypath(index
, sm
->path
, 0)))
1619 submodule_update_from_index_entry(sm
, ie
);
1624 static void submodule_update_from_head_data(
1625 git_submodule
*sm
, mode_t mode
, const git_oid
*id
)
1627 if (!S_ISGITLINK(mode
))
1628 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
1630 git_oid_cpy(&sm
->head_oid
, id
);
1632 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
1633 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
1637 static int submodule_update_head(git_submodule
*submodule
)
1639 git_tree
*head
= NULL
;
1640 git_tree_entry
*te
= NULL
;
1642 submodule
->flags
= submodule
->flags
&
1643 ~(GIT_SUBMODULE_STATUS_IN_HEAD
|
1644 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
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)
1651 submodule_update_from_head_data(submodule
, te
->attr
, git_tree_entry_id(te
));
1653 git_tree_entry_free(te
);
1654 git_tree_free(head
);
1658 int git_submodule_reload(git_submodule
*sm
, int force
)
1660 git_config
*mods
= NULL
;
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 */
1671 if (git_repository_is_bare(sm
->repo
))
1674 /* refresh config data */
1675 if ((error
= gitmodules_snapshot(&mods
, sm
->repo
)) < 0 && error
!= GIT_ENOTFOUND
)
1678 if (mods
!= NULL
&& (error
= submodule_read_config(sm
, mods
)) < 0)
1681 /* refresh wd data */
1683 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1684 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1685 GIT_SUBMODULE_STATUS__WD_FLAGS
);
1687 if ((error
= submodule_load_from_wd_lite(sm
)) < 0 ||
1688 (error
= submodule_update_index(sm
)) < 0 ||
1689 (error
= submodule_update_head(sm
)) < 0)
1693 git_config_free(mods
);
1697 static void submodule_copy_oid_maybe(
1698 git_oid
*tgt
, const git_oid
*src
, bool valid
)
1702 memcpy(tgt
, src
, sizeof(*tgt
));
1704 memset(tgt
, 0, sizeof(*tgt
));
1708 int git_submodule__status(
1709 unsigned int *out_status
,
1710 git_oid
*out_head_id
,
1711 git_oid
*out_index_id
,
1714 git_submodule_ignore_t ign
)
1716 unsigned int status
;
1717 git_repository
*smrepo
= NULL
;
1719 if (ign
== GIT_SUBMODULE_IGNORE_UNSPECIFIED
)
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
);
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.
1735 if (sm
->repo
->submodule_cache
== NULL
) {
1736 /* refresh the index OID */
1737 if (submodule_update_index(sm
) < 0)
1740 /* refresh the HEAD OID */
1741 if (submodule_update_head(sm
) < 0)
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)
1751 git_repository_free(smrepo
);
1753 } else if (git_submodule_open(&smrepo
, sm
) < 0) {
1758 status
= GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm
->flags
);
1760 submodule_get_index_status(&status
, sm
);
1761 submodule_get_wd_status(&status
, sm
, smrepo
, ign
);
1763 git_repository_free(smrepo
);
1765 *out_status
= status
;
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);
1777 int git_submodule_status(unsigned int *status
, git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1782 GIT_ASSERT_ARG(status
);
1783 GIT_ASSERT_ARG(repo
);
1784 GIT_ASSERT_ARG(name
);
1786 if ((error
= git_submodule_lookup(&sm
, repo
, name
)) < 0)
1789 error
= git_submodule__status(status
, NULL
, NULL
, NULL
, sm
, ignore
);
1790 git_submodule_free(sm
);
1795 int git_submodule_location(unsigned int *location
, git_submodule
*sm
)
1797 GIT_ASSERT_ARG(location
);
1800 return git_submodule__status(
1801 location
, NULL
, NULL
, NULL
, sm
, GIT_SUBMODULE_IGNORE_ALL
);
1805 * INTERNAL FUNCTIONS
1808 static int submodule_alloc(
1809 git_submodule
**out
, git_repository
*repo
, const char *name
)
1814 if (!name
|| !(namelen
= strlen(name
))) {
1815 git_error_set(GIT_ERROR_SUBMODULE
, "invalid submodule name");
1819 sm
= git__calloc(1, sizeof(git_submodule
));
1820 GIT_ERROR_CHECK_ALLOC(sm
);
1822 sm
->name
= sm
->path
= git__strdup(name
);
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
;
1839 static void submodule_release(git_submodule
*sm
)
1848 if (sm
->path
!= sm
->name
)
1849 git__free(sm
->path
);
1850 git__free(sm
->name
);
1852 git__free(sm
->branch
);
1853 git__memzero(sm
, sizeof(*sm
));
1857 int git_submodule_dup(git_submodule
**out
, git_submodule
*source
)
1859 GIT_ASSERT_ARG(out
);
1860 GIT_ASSERT_ARG(source
);
1862 GIT_REFCOUNT_INC(source
);
1868 void git_submodule_free(git_submodule
*sm
)
1872 GIT_REFCOUNT_DEC(sm
, submodule_release
);
1875 static int submodule_config_error(const char *property
, const char *value
)
1877 git_error_set(GIT_ERROR_INVALID
,
1878 "invalid value for submodule '%s' property: '%s'", property
, value
);
1882 int git_submodule_parse_ignore(git_submodule_ignore_t
*out
, const char *value
)
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
);
1892 *out
= (git_submodule_ignore_t
)val
;
1896 int git_submodule_parse_update(git_submodule_update_t
*out
, const char *value
)
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
);
1906 *out
= (git_submodule_update_t
)val
;
1910 static int submodule_parse_recurse(git_submodule_recurse_t
*out
, const char *value
)
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
);
1920 *out
= (git_submodule_recurse_t
)val
;
1924 static int get_value(const char **out
, git_config
*cfg
, git_buf
*buf
, const char *name
, const char *field
)
1930 if ((error
= git_buf_printf(buf
, "submodule.%s.%s", name
, field
)) < 0 ||
1931 (error
= git_config_get_string(out
, cfg
, buf
->ptr
)) < 0)
1937 static bool looks_like_command_line_option(const char *s
)
1939 if (s
&& s
[0] == '-')
1945 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
)
1947 git_buf key
= GIT_BUF_INIT
;
1949 int error
, in_config
= 0;
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)
1956 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "path")) == 0) {
1958 /* We would warn here if we had that API */
1959 if (!looks_like_command_line_option(value
)) {
1961 * TODO: if case insensitive filesystem, then the following strcmp
1962 * should be strcasecmp
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
);
1972 } else if (error
!= GIT_ENOTFOUND
) {
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
)) {
1980 sm
->url
= git__strdup(value
);
1981 GIT_ERROR_CHECK_ALLOC(sm
->url
);
1983 } else if (error
!= GIT_ENOTFOUND
) {
1987 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "branch")) == 0) {
1989 sm
->branch
= git__strdup(value
);
1990 GIT_ERROR_CHECK_ALLOC(sm
->branch
);
1991 } else if (error
!= GIT_ENOTFOUND
) {
1995 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "update")) == 0) {
1997 if ((error
= git_submodule_parse_update(&sm
->update
, value
)) < 0)
1999 sm
->update_default
= sm
->update
;
2000 } else if (error
!= GIT_ENOTFOUND
) {
2004 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "fetchRecurseSubmodules")) == 0) {
2006 if ((error
= submodule_parse_recurse(&sm
->fetch_recurse
, value
)) < 0)
2008 sm
->fetch_recurse_default
= sm
->fetch_recurse
;
2009 } else if (error
!= GIT_ENOTFOUND
) {
2013 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "ignore")) == 0) {
2015 if ((error
= git_submodule_parse_ignore(&sm
->ignore
, value
)) < 0)
2017 sm
->ignore_default
= sm
->ignore
;
2018 } else if (error
!= GIT_ENOTFOUND
) {
2023 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
2028 git_buf_dispose(&key
);
2032 static int submodule_load_each(const git_config_entry
*entry
, void *payload
)
2034 lfc_data
*data
= payload
;
2035 const char *namestart
, *property
;
2036 git_strmap
*map
= data
->map
;
2037 git_buf name
= GIT_BUF_INIT
;
2041 if (git__prefixcmp(entry
->name
, "submodule.") != 0)
2044 namestart
= entry
->name
+ strlen("submodule.");
2045 property
= strrchr(namestart
, '.');
2047 if (!property
|| (property
== namestart
))
2052 if ((error
= git_buf_set(&name
, namestart
, property
- namestart
-1)) < 0)
2055 isvalid
= git_submodule_name_is_valid(data
->repo
, name
.ptr
, 0);
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.
2067 if (git_strmap_exists(map
, name
.ptr
)) {
2072 if ((error
= submodule_alloc(&sm
, data
->repo
, name
.ptr
)) < 0)
2075 if ((error
= submodule_read_config(sm
, data
->mods
)) < 0) {
2076 git_submodule_free(sm
);
2080 if ((error
= git_strmap_set(map
, sm
->name
, sm
)) < 0)
2086 git_buf_dispose(&name
);
2090 static int submodule_load_from_wd_lite(git_submodule
*sm
)
2092 git_buf path
= GIT_BUF_INIT
;
2094 if (git_repository_workdir_path(&path
, sm
->repo
, sm
->path
) < 0)
2097 if (git_path_isdir(path
.ptr
))
2098 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
2100 if (git_path_contains(&path
, DOT_GIT
))
2101 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
;
2103 git_buf_dispose(&path
);
2108 * Requests a snapshot of $WORK_TREE/.gitmodules.
2110 * Returns GIT_ENOTFOUND in case no .gitmodules file exist
2112 static int gitmodules_snapshot(git_config
**snap
, git_repository
*repo
)
2114 git_config
*mods
= NULL
;
2115 git_buf path
= GIT_BUF_INIT
;
2118 if (git_repository_workdir(repo
) == NULL
)
2119 return GIT_ENOTFOUND
;
2121 if ((error
= git_repository_workdir_path(&path
, repo
, GIT_MODULES_FILE
)) < 0)
2124 if ((error
= git_config_open_ondisk(&mods
, path
.ptr
)) < 0)
2126 git_buf_dispose(&path
);
2128 if ((error
= git_config_snapshot(snap
, mods
)) < 0)
2135 git_config_free(mods
);
2136 git_buf_dispose(&path
);
2141 static git_config_backend
*open_gitmodules(
2142 git_repository
*repo
,
2145 git_buf path
= GIT_BUF_INIT
;
2146 git_config_backend
*mods
= NULL
;
2148 if (git_repository_workdir(repo
) != NULL
) {
2149 if (git_repository_workdir_path(&path
, repo
, GIT_MODULES_FILE
) != 0)
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)
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
);
2164 git_buf_dispose(&path
);
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
)
2173 git_reference
*head
= NULL
;
2174 git_buf upstream_name
= GIT_BUF_INIT
;
2176 /* lookup and dereference HEAD */
2177 if ((error
= git_repository_head(&head
, repo
)) < 0)
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.
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
;
2192 /* lookup remote tracking branch of HEAD */
2193 if ((error
= git_branch_upstream_name(
2196 git_reference_name(head
))) < 0)
2199 /* lookup remote of remote tracking branch */
2200 if ((error
= git_branch_remote_name(remote_name
, repo
, upstream_name
.ptr
)) < 0)
2204 git_buf_dispose(&upstream_name
);
2205 git_reference_free(head
);
2210 /* Lookup the remote of the local tracking branch HEAD points to */
2211 static int lookup_head_remote(git_remote
**remote
, git_repository
*repo
)
2214 git_buf remote_name
= GIT_BUF_INIT
;
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
);
2220 git_buf_dispose(&remote_name
);
2225 /* Lookup remote, either from HEAD or fall back on origin */
2226 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
)
2228 int error
= lookup_head_remote(remote
, repo
);
2230 /* if that failed, use 'origin' instead */
2231 if (error
== GIT_ENOTFOUND
|| error
== GIT_EUNBORNBRANCH
)
2232 error
= git_remote_lookup(remote
, repo
, "origin");
2234 if (error
== GIT_ENOTFOUND
)
2236 GIT_ERROR_SUBMODULE
,
2237 "cannot get default remote for submodule - no local tracking "
2238 "branch for HEAD and origin does not exist");
2243 static int get_url_base(git_buf
*url
, git_repository
*repo
)
2246 git_worktree
*wt
= NULL
;
2247 git_remote
*remote
= NULL
;
2249 if ((error
= lookup_default_remote(&remote
, repo
)) == 0) {
2250 error
= git_buf_sets(url
, git_remote_url(remote
));
2252 } else if (error
!= GIT_ENOTFOUND
)
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)
2261 error
= git_buf_sets(url
, wt
->parent_path
);
2263 error
= git_buf_sets(url
, git_repository_workdir(repo
));
2267 git_remote_free(remote
);
2268 git_worktree_free(wt
);
2273 static void submodule_get_index_status(unsigned int *status
, git_submodule
*sm
)
2275 const git_oid
*head_oid
= git_submodule_head_id(sm
);
2276 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2278 *status
= *status
& ~GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
2282 *status
|= GIT_SUBMODULE_STATUS_INDEX_ADDED
;
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
;
2291 static void submodule_get_wd_status(
2292 unsigned int *status
,
2294 git_repository
*sm_repo
,
2295 git_submodule_ignore_t ign
)
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
;
2305 *status
= *status
& ~GIT_SUBMODULE_STATUS__WD_FLAGS
;
2309 *status
|= GIT_SUBMODULE_STATUS_WD_ADDED
;
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
;
2316 *status
|= GIT_SUBMODULE_STATUS_WD_DELETED
;
2318 else if (!git_oid_equal(index_oid
, wd_oid
))
2319 *status
|= GIT_SUBMODULE_STATUS_WD_MODIFIED
;
2321 /* if we have no repo, then we're done */
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).
2330 if (ign
== GIT_SUBMODULE_IGNORE_NONE
)
2331 opt
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
2333 (void)git_repository_index__weakptr(&index
, sm_repo
);
2335 /* if we don't have an unborn head, check diff with index */
2336 if (git_repository_head_tree(&sm_head
, sm_repo
) < 0)
2339 /* perform head to index diff on submodule */
2340 if (git_diff_tree_to_index(&diff
, sm_repo
, sm_head
, index
, &opt
) < 0)
2343 if (git_diff_num_deltas(diff
) > 0)
2344 *status
|= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
2345 git_diff_free(diff
);
2349 git_tree_free(sm_head
);
2352 /* perform index-to-workdir diff on submodule */
2353 if (git_diff_index_to_workdir(&diff
, sm_repo
, index
, &opt
) < 0)
2357 git_diff_num_deltas_of_type(diff
, GIT_DELTA_UNTRACKED
);
2360 *status
|= GIT_SUBMODULE_STATUS_WD_UNTRACKED
;
2362 if (git_diff_num_deltas(diff
) != untracked
)
2363 *status
|= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
;
2365 git_diff_free(diff
);