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.
9 #include "git2/config.h"
10 #include "git2/sys/config.h"
11 #include "git2/types.h"
12 #include "git2/index.h"
17 #include "config_file.h"
19 #include "repository.h"
20 #include "submodule.h"
27 #define GIT_MODULES_FILE ".gitmodules"
29 static git_cvar_map _sm_update_map
[] = {
30 {GIT_CVAR_STRING
, "checkout", GIT_SUBMODULE_UPDATE_CHECKOUT
},
31 {GIT_CVAR_STRING
, "rebase", GIT_SUBMODULE_UPDATE_REBASE
},
32 {GIT_CVAR_STRING
, "merge", GIT_SUBMODULE_UPDATE_MERGE
},
33 {GIT_CVAR_STRING
, "none", GIT_SUBMODULE_UPDATE_NONE
},
34 {GIT_CVAR_FALSE
, NULL
, GIT_SUBMODULE_UPDATE_NONE
},
35 {GIT_CVAR_TRUE
, NULL
, GIT_SUBMODULE_UPDATE_CHECKOUT
},
38 static git_cvar_map _sm_ignore_map
[] = {
39 {GIT_CVAR_STRING
, "none", GIT_SUBMODULE_IGNORE_NONE
},
40 {GIT_CVAR_STRING
, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED
},
41 {GIT_CVAR_STRING
, "dirty", GIT_SUBMODULE_IGNORE_DIRTY
},
42 {GIT_CVAR_STRING
, "all", GIT_SUBMODULE_IGNORE_ALL
},
43 {GIT_CVAR_FALSE
, NULL
, GIT_SUBMODULE_IGNORE_NONE
},
44 {GIT_CVAR_TRUE
, NULL
, GIT_SUBMODULE_IGNORE_ALL
},
47 static git_cvar_map _sm_recurse_map
[] = {
48 {GIT_CVAR_STRING
, "on-demand", GIT_SUBMODULE_RECURSE_ONDEMAND
},
49 {GIT_CVAR_FALSE
, NULL
, GIT_SUBMODULE_RECURSE_NO
},
50 {GIT_CVAR_TRUE
, NULL
, GIT_SUBMODULE_RECURSE_YES
},
59 GITMODULES_EXISTING
= 0,
60 GITMODULES_CREATE
= 1,
63 static kh_inline khint_t
str_hash_no_trailing_slash(const char *s
)
68 if (s
[1] != '\0' || *s
!= '/')
69 h
= (h
<< 5) - h
+ *s
;
74 static kh_inline
int str_equal_no_trailing_slash(const char *a
, const char *b
)
76 size_t alen
= a
? strlen(a
) : 0;
77 size_t blen
= b
? strlen(b
) : 0;
79 if (alen
> 0 && a
[alen
- 1] == '/')
81 if (blen
> 0 && b
[blen
- 1] == '/')
84 return (alen
== 0 && blen
== 0) ||
85 (alen
== blen
&& strncmp(a
, b
, alen
) == 0);
89 str
, static kh_inline
, const char *, void *, 1,
90 str_hash_no_trailing_slash
, str_equal_no_trailing_slash
)
92 static int submodule_alloc(git_submodule
**out
, git_repository
*repo
, const char *name
);
93 static git_config_backend
*open_gitmodules(git_repository
*repo
, int gitmod
);
94 static git_config
*gitmodules_snapshot(git_repository
*repo
);
95 static int get_url_base(git_buf
*url
, git_repository
*repo
);
96 static int lookup_head_remote_key(git_buf
*remote_key
, git_repository
*repo
);
97 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
);
98 static int submodule_load_each(const git_config_entry
*entry
, void *payload
);
99 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
);
100 static int submodule_load_from_wd_lite(git_submodule
*);
101 static void submodule_get_index_status(unsigned int *, git_submodule
*);
102 static void submodule_get_wd_status(unsigned int *, git_submodule
*, git_repository
*, git_submodule_ignore_t
);
103 static void submodule_update_from_index_entry(git_submodule
*sm
, const git_index_entry
*ie
);
104 static void submodule_update_from_head_data(git_submodule
*sm
, mode_t mode
, const git_oid
*id
);
106 static int submodule_cmp(const void *a
, const void *b
)
108 return strcmp(((git_submodule
*)a
)->name
, ((git_submodule
*)b
)->name
);
111 static int submodule_config_key_trunc_puts(git_buf
*key
, const char *suffix
)
113 ssize_t idx
= git_buf_rfind(key
, '.');
114 git_buf_truncate(key
, (size_t)(idx
+ 1));
115 return git_buf_puts(key
, suffix
);
122 static void submodule_set_lookup_error(int error
, const char *name
)
127 giterr_set(GITERR_SUBMODULE
, (error
== GIT_ENOTFOUND
) ?
128 "no submodule named '%s'" :
129 "submodule '%s' has not been added yet", name
);
137 static int find_by_path(const git_config_entry
*entry
, void *payload
)
139 fbp_data
*data
= payload
;
141 if (!strcmp(entry
->value
, data
->path
)) {
142 const char *fdot
, *ldot
;
143 fdot
= strchr(entry
->name
, '.');
144 ldot
= strrchr(entry
->name
, '.');
145 data
->name
= git__strndup(fdot
+ 1, ldot
- fdot
- 1);
146 GITERR_CHECK_ALLOC(data
->name
);
153 * Release the name map returned by 'load_submodule_names'.
155 static void free_submodule_names(git_strmap
*names
)
160 git_strmap_foreach_value(names
, name
, {
163 git_strmap_free(names
);
168 * Map submodule paths to names.
169 * TODO: for some use-cases, this might need case-folding on a
170 * case-insensitive filesystem
172 static int load_submodule_names(git_strmap
*out
, git_config
*cfg
)
174 const char *key
= "submodule\\..*\\.path";
175 git_config_iterator
*iter
;
176 git_config_entry
*entry
;
177 git_buf buf
= GIT_BUF_INIT
;
181 if ((error
= git_config_iterator_glob_new(&iter
, cfg
, key
)) < 0)
184 while (git_config_next(&entry
, iter
) == 0) {
185 const char *fdot
, *ldot
;
186 fdot
= strchr(entry
->name
, '.');
187 ldot
= strrchr(entry
->name
, '.');
189 git_buf_put(&buf
, fdot
+ 1, ldot
- fdot
- 1);
190 git_strmap_insert(out
, entry
->value
, git_buf_detach(&buf
), &rval
);
192 giterr_set(GITERR_NOMEMORY
, "error inserting submodule into hash table");
197 git_config_iterator_free(iter
);
201 int git_submodule_lookup(
202 git_submodule
**out
, /* NULL if user only wants to test existence */
203 git_repository
*repo
,
204 const char *name
) /* trailing slash is allowed */
207 unsigned int location
;
210 assert(repo
&& name
);
212 if (repo
->submodule_cache
!= NULL
) {
213 khiter_t pos
= git_strmap_lookup_index(repo
->submodule_cache
, name
);
214 if (git_strmap_valid_index(repo
->submodule_cache
, pos
)) {
216 *out
= git_strmap_value_at(repo
->submodule_cache
, pos
);
217 GIT_REFCOUNT_INC(*out
);
223 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
226 if ((error
= git_submodule_reload(sm
, false)) < 0) {
227 git_submodule_free(sm
);
231 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
232 git_submodule_free(sm
);
236 /* If it's not configured or we're looking by path */
237 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
238 git_config_backend
*mods
;
239 const char *pattern
= "submodule\\..*\\.path";
240 git_buf path
= GIT_BUF_INIT
;
241 fbp_data data
= { NULL
, NULL
};
243 git_buf_puts(&path
, name
);
244 while (path
.ptr
[path
.size
-1] == '/') {
245 path
.ptr
[--path
.size
] = '\0';
247 data
.path
= path
.ptr
;
249 mods
= open_gitmodules(repo
, GITMODULES_EXISTING
);
252 error
= git_config_file_foreach_match(mods
, pattern
, find_by_path
, &data
);
254 git_config_file_free(mods
);
257 git_submodule_free(sm
);
264 sm
->name
= data
.name
;
265 sm
->path
= git_buf_detach(&path
);
267 /* Try to load again with the right name */
268 if ((error
= git_submodule_reload(sm
, false)) < 0) {
269 git_submodule_free(sm
);
277 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
278 git_submodule_free(sm
);
282 /* If we still haven't found it, do the WD check */
283 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
284 git_submodule_free(sm
);
285 error
= GIT_ENOTFOUND
;
287 /* If it's not configured, we still check if there's a repo at the path */
288 if (git_repository_workdir(repo
)) {
289 git_buf path
= GIT_BUF_INIT
;
290 if (git_buf_join3(&path
,
291 '/', git_repository_workdir(repo
), name
, DOT_GIT
) < 0)
294 if (git_path_exists(path
.ptr
))
300 submodule_set_lookup_error(error
, name
);
307 git_submodule_free(sm
);
312 static void submodule_free_dup(void *sm
)
314 git_submodule_free(sm
);
317 static int submodule_get_or_create(git_submodule
**out
, git_repository
*repo
, git_strmap
*map
, const char *name
)
321 git_submodule
*sm
= NULL
;
323 pos
= git_strmap_lookup_index(map
, name
);
324 if (git_strmap_valid_index(map
, pos
)) {
325 sm
= git_strmap_value_at(map
, pos
);
329 /* if the submodule doesn't exist yet in the map, create it */
330 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
333 pos
= git_strmap_put(map
, sm
->name
, &error
);
334 /* nobody can beat us to adding it */
337 git_submodule_free(sm
);
341 git_strmap_set_value_at(map
, pos
, sm
);
344 GIT_REFCOUNT_INC(sm
);
349 static int submodules_from_index(git_strmap
*map
, git_index
*idx
, git_config
*cfg
)
352 git_iterator
*i
= NULL
;
353 const git_index_entry
*entry
;
354 git_strmap
*names
= 0;
356 git_strmap_alloc(&names
);
357 if ((error
= load_submodule_names(names
, cfg
)))
360 if ((error
= git_iterator_for_index(&i
, git_index_owner(idx
), idx
, NULL
)) < 0)
363 while (!(error
= git_iterator_advance(&entry
, i
))) {
364 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
367 if (git_strmap_valid_index(map
, pos
)) {
368 sm
= git_strmap_value_at(map
, pos
);
370 if (S_ISGITLINK(entry
->mode
))
371 submodule_update_from_index_entry(sm
, entry
);
373 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
374 } else if (S_ISGITLINK(entry
->mode
)) {
378 name_pos
= git_strmap_lookup_index(names
, entry
->path
);
379 if (git_strmap_valid_index(names
, name_pos
)) {
380 name
= git_strmap_value_at(names
, name_pos
);
385 if (!submodule_get_or_create(&sm
, git_index_owner(idx
), map
, name
)) {
386 submodule_update_from_index_entry(sm
, entry
);
387 git_submodule_free(sm
);
392 if (error
== GIT_ITEROVER
)
396 git_iterator_free(i
);
397 free_submodule_names(names
);
402 static int submodules_from_head(git_strmap
*map
, git_tree
*head
, git_config
*cfg
)
405 git_iterator
*i
= NULL
;
406 const git_index_entry
*entry
;
407 git_strmap
*names
= 0;
408 git_strmap_alloc(&names
);
409 if ((error
= load_submodule_names(names
, cfg
)))
412 if ((error
= git_iterator_for_tree(&i
, head
, NULL
)) < 0)
415 while (!(error
= git_iterator_advance(&entry
, i
))) {
416 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
419 if (git_strmap_valid_index(map
, pos
)) {
420 sm
= git_strmap_value_at(map
, pos
);
422 if (S_ISGITLINK(entry
->mode
))
423 submodule_update_from_head_data(sm
, entry
->mode
, &entry
->id
);
425 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
426 } else if (S_ISGITLINK(entry
->mode
)) {
430 name_pos
= git_strmap_lookup_index(names
, entry
->path
);
431 if (git_strmap_valid_index(names
, name_pos
)) {
432 name
= git_strmap_value_at(names
, name_pos
);
437 if (!submodule_get_or_create(&sm
, git_tree_owner(head
), map
, name
)) {
438 submodule_update_from_head_data(
439 sm
, entry
->mode
, &entry
->id
);
440 git_submodule_free(sm
);
445 if (error
== GIT_ITEROVER
)
449 git_iterator_free(i
);
450 free_submodule_names(names
);
455 /* If have_sm is true, sm is populated, otherwise map an repo are. */
459 git_repository
*repo
;
462 int git_submodule__map(git_repository
*repo
, git_strmap
*map
)
465 git_index
*idx
= NULL
;
466 git_tree
*head
= NULL
;
467 const char *wd
= NULL
;
468 git_buf path
= GIT_BUF_INIT
;
470 git_config
*mods
= NULL
;
475 /* get sources that we will need to check */
476 if (git_repository_index(&idx
, repo
) < 0)
478 if (git_repository_head_tree(&head
, repo
) < 0)
481 wd
= git_repository_workdir(repo
);
482 if (wd
&& (error
= git_buf_joinpath(&path
, wd
, GIT_MODULES_FILE
)) < 0)
485 /* clear submodule flags that are to be refreshed */
487 mask
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
488 GIT_SUBMODULE_STATUS__INDEX_FLAGS
|
489 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
|
490 GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
492 mask
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
493 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
494 mask
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
496 mask
|= GIT_SUBMODULE_STATUS_IN_WD
|
497 GIT_SUBMODULE_STATUS__WD_SCANNED
|
498 GIT_SUBMODULE_STATUS__WD_FLAGS
|
499 GIT_SUBMODULE_STATUS__WD_OID_VALID
;
501 /* add submodule information from .gitmodules */
503 lfc_data data
= { 0 };
507 if ((mods
= gitmodules_snapshot(repo
)) == NULL
)
511 if ((error
= git_config_foreach(
512 mods
, submodule_load_each
, &data
)) < 0)
515 /* add back submodule information from index */
517 if ((error
= submodules_from_index(map
, idx
, mods
)) < 0)
520 /* add submodule information from HEAD */
522 if ((error
= submodules_from_head(map
, head
, mods
)) < 0)
525 /* shallow scan submodules in work tree as needed */
526 if (wd
&& mask
!= 0) {
527 git_strmap_foreach_value(map
, sm
, {
528 submodule_load_from_wd_lite(sm
);
533 git_config_free(mods
);
534 /* TODO: if we got an error, mark submodule config as invalid? */
541 int git_submodule_foreach(
542 git_repository
*repo
,
543 git_submodule_cb callback
,
546 git_vector snapshot
= GIT_VECTOR_INIT
;
547 git_strmap
*submodules
;
552 if ((error
= git_strmap_alloc(&submodules
)) < 0)
555 if ((error
= git_submodule__map(repo
, submodules
)) < 0)
558 if (!(error
= git_vector_init(
559 &snapshot
, git_strmap_num_entries(submodules
), submodule_cmp
))) {
561 git_strmap_foreach_value(submodules
, sm
, {
562 if ((error
= git_vector_insert(&snapshot
, sm
)) < 0)
564 GIT_REFCOUNT_INC(sm
);
571 git_vector_uniq(&snapshot
, submodule_free_dup
);
573 git_vector_foreach(&snapshot
, i
, sm
) {
574 if ((error
= callback(sm
, sm
->name
, payload
)) != 0) {
575 giterr_set_after_callback(error
);
581 git_vector_foreach(&snapshot
, i
, sm
)
582 git_submodule_free(sm
);
583 git_vector_free(&snapshot
);
585 git_strmap_foreach_value(submodules
, sm
, {
586 git_submodule_free(sm
);
588 git_strmap_free(submodules
);
593 static int submodule_repo_init(
594 git_repository
**out
,
595 git_repository
*parent_repo
,
601 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
602 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
603 git_repository
*subrepo
= NULL
;
605 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
609 initopt
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_NO_REINIT
;
610 initopt
.origin_url
= url
;
612 /* init submodule repository and add origin remote as needed */
614 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
615 * gitlink in the sub-repo workdir directory to that repository
617 * Old style: sub-repo goes directly into repo/<name>/.git/
620 error
= git_repository_item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
623 error
= git_buf_joinpath(&repodir
, repodir
.ptr
, path
);
627 initopt
.workdir_path
= workdir
.ptr
;
629 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
630 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
632 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
634 error
= git_repository_init_ext(&subrepo
, workdir
.ptr
, &initopt
);
637 git_buf_free(&workdir
);
638 git_buf_free(&repodir
);
645 int git_submodule_add_setup(
647 git_repository
*repo
,
653 git_config_backend
*mods
= NULL
;
654 git_submodule
*sm
= NULL
;
655 git_buf name
= GIT_BUF_INIT
, real_url
= GIT_BUF_INIT
;
656 git_repository
*subrepo
= NULL
;
658 assert(repo
&& url
&& path
);
660 /* see if there is already an entry for this submodule */
662 if (git_submodule_lookup(NULL
, repo
, path
) < 0)
665 giterr_set(GITERR_SUBMODULE
,
666 "attempt to add submodule '%s' that already exists", path
);
670 /* validate and normalize path */
672 if (git__prefixcmp(path
, git_repository_workdir(repo
)) == 0)
673 path
+= strlen(git_repository_workdir(repo
));
675 if (git_path_root(path
) >= 0) {
676 giterr_set(GITERR_SUBMODULE
, "submodule path must be a relative path");
681 /* update .gitmodules */
683 if (!(mods
= open_gitmodules(repo
, GITMODULES_CREATE
))) {
684 giterr_set(GITERR_SUBMODULE
,
685 "adding submodules to a bare repository is not supported");
689 if ((error
= git_buf_printf(&name
, "submodule.%s.path", path
)) < 0 ||
690 (error
= git_config_file_set_string(mods
, name
.ptr
, path
)) < 0)
693 if ((error
= submodule_config_key_trunc_puts(&name
, "url")) < 0 ||
694 (error
= git_config_file_set_string(mods
, name
.ptr
, url
)) < 0)
697 git_buf_clear(&name
);
699 /* init submodule repository and add origin remote as needed */
701 error
= git_buf_joinpath(&name
, git_repository_workdir(repo
), path
);
705 /* if the repo does not already exist, then init a new repo and add it.
706 * Otherwise, just add the existing repo.
708 if (!(git_path_exists(name
.ptr
) &&
709 git_path_contains(&name
, DOT_GIT
))) {
711 /* resolve the actual URL to use */
712 if ((error
= git_submodule_resolve_url(&real_url
, repo
, url
)) < 0)
715 if ((error
= submodule_repo_init(&subrepo
, repo
, path
, real_url
.ptr
, use_gitlink
)) < 0)
719 if ((error
= git_submodule_lookup(&sm
, repo
, path
)) < 0)
722 error
= git_submodule_init(sm
, false);
726 git_submodule_free(sm
);
732 git_config_file_free(mods
);
733 git_repository_free(subrepo
);
734 git_buf_free(&real_url
);
740 int git_submodule_repo_init(
741 git_repository
**out
,
742 const git_submodule
*sm
,
746 git_repository
*sub_repo
= NULL
;
747 const char *configured_url
;
748 git_config
*cfg
= NULL
;
749 git_buf buf
= GIT_BUF_INIT
;
753 /* get the configured remote url of the submodule */
754 if ((error
= git_buf_printf(&buf
, "submodule.%s.url", sm
->name
)) < 0 ||
755 (error
= git_repository_config_snapshot(&cfg
, sm
->repo
)) < 0 ||
756 (error
= git_config_get_string(&configured_url
, cfg
, buf
.ptr
)) < 0 ||
757 (error
= submodule_repo_init(&sub_repo
, sm
->repo
, sm
->path
, configured_url
, use_gitlink
)) < 0)
763 git_config_free(cfg
);
768 int git_submodule_add_finalize(git_submodule
*sm
)
775 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
776 (error
= git_index_add_bypath(index
, GIT_MODULES_FILE
)) < 0)
779 return git_submodule_add_to_index(sm
, true);
782 int git_submodule_add_to_index(git_submodule
*sm
, int write_index
)
785 git_repository
*sm_repo
= NULL
;
787 git_buf path
= GIT_BUF_INIT
;
789 git_index_entry entry
;
794 /* force reload of wd OID by git_submodule_open */
795 sm
->flags
= sm
->flags
& ~GIT_SUBMODULE_STATUS__WD_OID_VALID
;
797 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
798 (error
= git_buf_joinpath(
799 &path
, git_repository_workdir(sm
->repo
), sm
->path
)) < 0 ||
800 (error
= git_submodule_open(&sm_repo
, sm
)) < 0)
803 /* read stat information for submodule working directory */
804 if (p_stat(path
.ptr
, &st
) < 0) {
805 giterr_set(GITERR_SUBMODULE
,
806 "cannot add submodule without working directory");
811 memset(&entry
, 0, sizeof(entry
));
812 entry
.path
= sm
->path
;
813 git_index_entry__init_from_stat(
814 &entry
, &st
, !(git_index_caps(index
) & GIT_INDEXCAP_NO_FILEMODE
));
816 /* calling git_submodule_open will have set sm->wd_oid if possible */
817 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) == 0) {
818 giterr_set(GITERR_SUBMODULE
,
819 "cannot add submodule without HEAD to index");
823 git_oid_cpy(&entry
.id
, &sm
->wd_oid
);
825 if ((error
= git_commit_lookup(&head
, sm_repo
, &sm
->wd_oid
)) < 0)
828 entry
.ctime
.seconds
= (int32_t)git_commit_time(head
);
829 entry
.ctime
.nanoseconds
= 0;
830 entry
.mtime
.seconds
= (int32_t)git_commit_time(head
);
831 entry
.mtime
.nanoseconds
= 0;
833 git_commit_free(head
);
836 error
= git_index_add(index
, &entry
);
838 /* write it, if requested */
839 if (!error
&& write_index
) {
840 error
= git_index_write(index
);
843 git_oid_cpy(&sm
->index_oid
, &sm
->wd_oid
);
847 git_repository_free(sm_repo
);
852 const char *git_submodule_update_to_str(git_submodule_update_t update
)
855 for (i
= 0; i
< (int)ARRAY_SIZE(_sm_update_map
); ++i
)
856 if (_sm_update_map
[i
].map_value
== (int)update
)
857 return _sm_update_map
[i
].str_match
;
861 git_repository
*git_submodule_owner(git_submodule
*submodule
)
864 return submodule
->repo
;
867 const char *git_submodule_name(git_submodule
*submodule
)
870 return submodule
->name
;
873 const char *git_submodule_path(git_submodule
*submodule
)
876 return submodule
->path
;
879 const char *git_submodule_url(git_submodule
*submodule
)
882 return submodule
->url
;
885 int git_submodule_resolve_url(git_buf
*out
, git_repository
*repo
, const char *url
)
888 git_buf normalized
= GIT_BUF_INIT
;
890 assert(out
&& repo
&& url
);
892 git_buf_sanitize(out
);
894 /* We do this in all platforms in case someone on Windows created the .gitmodules */
895 if (strchr(url
, '\\')) {
896 if ((error
= git_path_normalize_slashes(&normalized
, url
)) < 0)
899 url
= normalized
.ptr
;
903 if (git_path_is_relative(url
)) {
904 if (!(error
= get_url_base(out
, repo
)))
905 error
= git_path_apply_relative(out
, url
);
906 } else if (strchr(url
, ':') != NULL
|| url
[0] == '/') {
907 error
= git_buf_sets(out
, url
);
909 giterr_set(GITERR_SUBMODULE
, "invalid format for submodule URL");
913 git_buf_free(&normalized
);
917 static int write_var(git_repository
*repo
, const char *name
, const char *var
, const char *val
)
919 git_buf key
= GIT_BUF_INIT
;
920 git_config_backend
*mods
;
923 mods
= open_gitmodules(repo
, GITMODULES_CREATE
);
927 if ((error
= git_buf_printf(&key
, "submodule.%s.%s", name
, var
)) < 0)
931 error
= git_config_file_set_string(mods
, key
.ptr
, val
);
933 error
= git_config_file_delete(mods
, key
.ptr
);
938 git_config_file_free(mods
);
942 static int write_mapped_var(git_repository
*repo
, const char *name
, git_cvar_map
*maps
, size_t nmaps
, const char *var
, int ival
)
947 if (git_config_lookup_map_enum(&type
, &val
, maps
, nmaps
, ival
) < 0) {
948 giterr_set(GITERR_SUBMODULE
, "invalid value for %s", var
);
952 if (type
== GIT_CVAR_TRUE
)
955 return write_var(repo
, name
, var
, val
);
958 const char *git_submodule_branch(git_submodule
*submodule
)
961 return submodule
->branch
;
964 int git_submodule_set_branch(git_repository
*repo
, const char *name
, const char *branch
)
967 assert(repo
&& name
);
969 return write_var(repo
, name
, "branch", branch
);
972 int git_submodule_set_url(git_repository
*repo
, const char *name
, const char *url
)
974 assert(repo
&& name
&& url
);
976 return write_var(repo
, name
, "url", url
);
979 const git_oid
*git_submodule_index_id(git_submodule
*submodule
)
983 if (submodule
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
984 return &submodule
->index_oid
;
989 const git_oid
*git_submodule_head_id(git_submodule
*submodule
)
993 if (submodule
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
994 return &submodule
->head_oid
;
999 const git_oid
*git_submodule_wd_id(git_submodule
*submodule
)
1003 /* load unless we think we have a valid oid */
1004 if (!(submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)) {
1005 git_repository
*subrepo
;
1007 /* calling submodule open grabs the HEAD OID if possible */
1008 if (!git_submodule_open_bare(&subrepo
, submodule
))
1009 git_repository_free(subrepo
);
1014 if (submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)
1015 return &submodule
->wd_oid
;
1020 git_submodule_ignore_t
git_submodule_ignore(git_submodule
*submodule
)
1023 return (submodule
->ignore
< GIT_SUBMODULE_IGNORE_NONE
) ?
1024 GIT_SUBMODULE_IGNORE_NONE
: submodule
->ignore
;
1027 int git_submodule_set_ignore(git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1029 assert(repo
&& name
);
1031 return write_mapped_var(repo
, name
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), "ignore", ignore
);
1034 git_submodule_update_t
git_submodule_update_strategy(git_submodule
*submodule
)
1037 return (submodule
->update
< GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1038 GIT_SUBMODULE_UPDATE_CHECKOUT
: submodule
->update
;
1041 int git_submodule_set_update(git_repository
*repo
, const char *name
, git_submodule_update_t update
)
1043 assert(repo
&& name
);
1045 return write_mapped_var(repo
, name
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), "update", update
);
1048 git_submodule_recurse_t
git_submodule_fetch_recurse_submodules(
1049 git_submodule
*submodule
)
1052 return submodule
->fetch_recurse
;
1055 int git_submodule_set_fetch_recurse_submodules(git_repository
*repo
, const char *name
, git_submodule_recurse_t recurse
)
1057 assert(repo
&& name
);
1059 return write_mapped_var(repo
, name
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), "fetchRecurseSubmodules", recurse
);
1062 static int submodule_repo_create(
1063 git_repository
**out
,
1064 git_repository
*parent_repo
,
1068 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
1069 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
1070 git_repository
*subrepo
= NULL
;
1073 GIT_REPOSITORY_INIT_MKPATH
|
1074 GIT_REPOSITORY_INIT_NO_REINIT
|
1075 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
1076 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
1078 /* Workdir: path to sub-repo working directory */
1079 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
1083 initopt
.workdir_path
= workdir
.ptr
;
1086 * Repodir: path to the sub-repo. sub-repo goes in:
1087 * <repo-dir>/modules/<name>/ with a gitlink in the
1088 * sub-repo workdir directory to that repository.
1090 error
= git_repository_item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
1093 error
= git_buf_joinpath(&repodir
, repodir
.ptr
, path
);
1097 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
1100 git_buf_free(&workdir
);
1101 git_buf_free(&repodir
);
1109 * Callback to override sub-repository creation when
1110 * cloning a sub-repository.
1112 static int git_submodule_update_repo_init_cb(
1113 git_repository
**out
,
1124 return submodule_repo_create(out
, sm
->repo
, path
);
1127 int git_submodule_update_init_options(git_submodule_update_options
*opts
, unsigned int version
)
1129 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1130 opts
, version
, git_submodule_update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_INIT
);
1134 int git_submodule_update(git_submodule
*sm
, int init
, git_submodule_update_options
*_update_options
)
1137 unsigned int submodule_status
;
1138 git_config
*config
= NULL
;
1139 const char *submodule_url
;
1140 git_repository
*sub_repo
= NULL
;
1141 git_remote
*remote
= NULL
;
1142 git_object
*target_commit
= NULL
;
1143 git_buf buf
= GIT_BUF_INIT
;
1144 git_submodule_update_options update_options
= GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
1145 git_clone_options clone_options
= GIT_CLONE_OPTIONS_INIT
;
1149 if (_update_options
)
1150 memcpy(&update_options
, _update_options
, sizeof(git_submodule_update_options
));
1152 GITERR_CHECK_VERSION(&update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
1154 /* Copy over the remote callbacks */
1155 memcpy(&clone_options
.fetch_opts
, &update_options
.fetch_opts
, sizeof(git_fetch_options
));
1157 /* Get the status of the submodule to determine if it is already initialized */
1158 if ((error
= git_submodule_status(&submodule_status
, sm
->repo
, sm
->name
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
)) < 0)
1162 * If submodule work dir is not already initialized, check to see
1163 * what we need to do (initialize, clone, return error...)
1165 if (submodule_status
& GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
) {
1167 * Work dir is not initialized, check to see if the submodule
1168 * info has been copied into .git/config
1170 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1171 (error
= git_buf_printf(&buf
, "submodule.%s.url", git_submodule_name(sm
))) < 0)
1174 if ((error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0) {
1176 * If the error is not "not found" or if it is "not found" and we are not
1177 * initializing the submodule, then return error.
1179 if (error
!= GIT_ENOTFOUND
)
1183 giterr_set(GITERR_SUBMODULE
, "submodule is not initialized");
1188 /* The submodule has not been initialized yet - initialize it now.*/
1189 if ((error
= git_submodule_init(sm
, 0)) < 0)
1192 git_config_free(config
);
1195 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1196 (error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0)
1200 /** submodule is initialized - now clone it **/
1201 /* override repo creation */
1202 clone_options
.repository_cb
= git_submodule_update_repo_init_cb
;
1203 clone_options
.repository_cb_payload
= sm
;
1206 * Do not perform checkout as part of clone, instead we
1207 * will checkout the specific commit manually.
1209 clone_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
1211 if ((error
= git_clone(&sub_repo
, submodule_url
, sm
->path
, &clone_options
)) < 0 ||
1212 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0 ||
1213 (error
= git_checkout_head(sub_repo
, &update_options
.checkout_opts
)) != 0)
1219 * Work dir is initialized - look up the commit in the parent repository's index,
1220 * update the workdir contents of the subrepository, and set the subrepository's
1221 * head to the new commit.
1223 if ((error
= git_submodule_open(&sub_repo
, sm
)) < 0)
1226 if ((oid
= git_submodule_index_id(sm
)) == NULL
) {
1227 giterr_set(GITERR_SUBMODULE
, "could not get ID of submodule in index");
1232 /* Look up the target commit in the submodule. */
1233 if ((error
= git_object_lookup(&target_commit
, sub_repo
, oid
, GIT_OBJ_COMMIT
)) < 0) {
1234 /* If it isn't found then fetch and try again. */
1235 if (error
!= GIT_ENOTFOUND
|| !update_options
.allow_fetch
||
1236 (error
= lookup_default_remote(&remote
, sub_repo
)) < 0 ||
1237 (error
= git_remote_fetch(remote
, NULL
, &update_options
.fetch_opts
, NULL
)) < 0 ||
1238 (error
= git_object_lookup(&target_commit
, sub_repo
, git_submodule_index_id(sm
), GIT_OBJ_COMMIT
)) < 0)
1242 if ((error
= git_checkout_tree(sub_repo
, target_commit
, &update_options
.checkout_opts
)) != 0 ||
1243 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0)
1246 /* Invalidate the wd flags as the workdir has been updated. */
1247 sm
->flags
= sm
->flags
&
1248 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1249 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1250 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1255 git_config_free(config
);
1256 git_object_free(target_commit
);
1257 git_remote_free(remote
);
1258 git_repository_free(sub_repo
);
1263 int git_submodule_init(git_submodule
*sm
, int overwrite
)
1267 git_buf key
= GIT_BUF_INIT
, effective_submodule_url
= GIT_BUF_INIT
;
1268 git_config
*cfg
= NULL
;
1271 giterr_set(GITERR_SUBMODULE
,
1272 "no URL configured for submodule '%s'", sm
->name
);
1276 if ((error
= git_repository_config(&cfg
, sm
->repo
)) < 0)
1279 /* write "submodule.NAME.url" */
1281 if ((error
= git_submodule_resolve_url(&effective_submodule_url
, sm
->repo
, sm
->url
)) < 0 ||
1282 (error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)) < 0 ||
1283 (error
= git_config__update_entry(
1284 cfg
, key
.ptr
, effective_submodule_url
.ptr
, overwrite
!= 0, false)) < 0)
1287 /* write "submodule.NAME.update" if not default */
1289 val
= (sm
->update
== GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1290 NULL
: git_submodule_update_to_str(sm
->update
);
1292 if ((error
= git_buf_printf(&key
, "submodule.%s.update", sm
->name
)) < 0 ||
1293 (error
= git_config__update_entry(
1294 cfg
, key
.ptr
, val
, overwrite
!= 0, false)) < 0)
1300 git_config_free(cfg
);
1302 git_buf_free(&effective_submodule_url
);
1307 int git_submodule_sync(git_submodule
*sm
)
1310 git_config
*cfg
= NULL
;
1311 git_buf key
= GIT_BUF_INIT
;
1312 git_repository
*smrepo
= NULL
;
1315 giterr_set(GITERR_SUBMODULE
,
1316 "no URL configured for submodule '%s'", sm
->name
);
1320 /* copy URL over to config only if it already exists */
1322 if (!(error
= git_repository_config__weakptr(&cfg
, sm
->repo
)) &&
1323 !(error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)))
1324 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, true);
1326 /* if submodule exists in the working directory, update remote url */
1329 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) != 0 &&
1330 !(error
= git_submodule_open(&smrepo
, sm
)))
1332 git_buf remote_name
= GIT_BUF_INIT
;
1334 if ((error
= git_repository_config__weakptr(&cfg
, smrepo
)) < 0)
1335 /* return error from reading submodule config */;
1336 else if ((error
= lookup_head_remote_key(&remote_name
, smrepo
)) < 0) {
1338 error
= git_buf_sets(&key
, "remote.origin.url");
1340 error
= git_buf_join3(
1341 &key
, '.', "remote", remote_name
.ptr
, "url");
1342 git_buf_free(&remote_name
);
1346 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, false);
1348 git_repository_free(smrepo
);
1356 static int git_submodule__open(
1357 git_repository
**subrepo
, git_submodule
*sm
, bool bare
)
1360 git_buf path
= GIT_BUF_INIT
;
1361 unsigned int flags
= GIT_REPOSITORY_OPEN_NO_SEARCH
;
1364 assert(sm
&& subrepo
);
1366 if (git_repository__ensure_not_bare(
1367 sm
->repo
, "open submodule repository") < 0)
1368 return GIT_EBAREREPO
;
1370 wd
= git_repository_workdir(sm
->repo
);
1372 if (git_buf_joinpath(&path
, wd
, sm
->path
) < 0 ||
1373 git_buf_joinpath(&path
, path
.ptr
, DOT_GIT
) < 0)
1376 sm
->flags
= sm
->flags
&
1377 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1378 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1379 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1382 flags
|= GIT_REPOSITORY_OPEN_BARE
;
1384 error
= git_repository_open_ext(subrepo
, path
.ptr
, flags
, wd
);
1386 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1388 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
|
1389 GIT_SUBMODULE_STATUS__WD_SCANNED
;
1391 if (!git_reference_name_to_id(&sm
->wd_oid
, *subrepo
, GIT_HEAD_FILE
))
1392 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_OID_VALID
;
1395 } else if (git_path_exists(path
.ptr
)) {
1396 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
|
1397 GIT_SUBMODULE_STATUS_IN_WD
;
1399 git_buf_rtruncate_at_char(&path
, '/'); /* remove "/.git" */
1401 if (git_path_isdir(path
.ptr
))
1402 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1405 git_buf_free(&path
);
1410 int git_submodule_open_bare(git_repository
**subrepo
, git_submodule
*sm
)
1412 return git_submodule__open(subrepo
, sm
, true);
1415 int git_submodule_open(git_repository
**subrepo
, git_submodule
*sm
)
1417 return git_submodule__open(subrepo
, sm
, false);
1420 static void submodule_update_from_index_entry(
1421 git_submodule
*sm
, const git_index_entry
*ie
)
1423 bool already_found
= (sm
->flags
& GIT_SUBMODULE_STATUS_IN_INDEX
) != 0;
1425 if (!S_ISGITLINK(ie
->mode
)) {
1427 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
1430 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
1432 git_oid_cpy(&sm
->index_oid
, &ie
->id
);
1434 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
1435 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
1439 static int submodule_update_index(git_submodule
*sm
)
1442 const git_index_entry
*ie
;
1444 if (git_repository_index__weakptr(&index
, sm
->repo
) < 0)
1447 sm
->flags
= sm
->flags
&
1448 ~(GIT_SUBMODULE_STATUS_IN_INDEX
|
1449 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
1451 if (!(ie
= git_index_get_bypath(index
, sm
->path
, 0)))
1454 submodule_update_from_index_entry(sm
, ie
);
1459 static void submodule_update_from_head_data(
1460 git_submodule
*sm
, mode_t mode
, const git_oid
*id
)
1462 if (!S_ISGITLINK(mode
))
1463 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
1465 git_oid_cpy(&sm
->head_oid
, id
);
1467 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
1468 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
1472 static int submodule_update_head(git_submodule
*submodule
)
1474 git_tree
*head
= NULL
;
1475 git_tree_entry
*te
= NULL
;
1477 submodule
->flags
= submodule
->flags
&
1478 ~(GIT_SUBMODULE_STATUS_IN_HEAD
|
1479 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
1481 /* if we can't look up file in current head, then done */
1482 if (git_repository_head_tree(&head
, submodule
->repo
) < 0 ||
1483 git_tree_entry_bypath(&te
, head
, submodule
->path
) < 0)
1486 submodule_update_from_head_data(submodule
, te
->attr
, git_tree_entry_id(te
));
1488 git_tree_entry_free(te
);
1489 git_tree_free(head
);
1493 int git_submodule_reload(git_submodule
*sm
, int force
)
1502 if (!git_repository_is_bare(sm
->repo
)) {
1503 /* refresh config data */
1504 mods
= gitmodules_snapshot(sm
->repo
);
1506 error
= submodule_read_config(sm
, mods
);
1507 git_config_free(mods
);
1513 /* refresh wd data */
1515 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1516 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1517 GIT_SUBMODULE_STATUS__WD_FLAGS
);
1519 error
= submodule_load_from_wd_lite(sm
);
1522 if (error
== 0 && (error
= submodule_update_index(sm
)) == 0)
1523 error
= submodule_update_head(sm
);
1528 static void submodule_copy_oid_maybe(
1529 git_oid
*tgt
, const git_oid
*src
, bool valid
)
1533 memcpy(tgt
, src
, sizeof(*tgt
));
1535 memset(tgt
, 0, sizeof(*tgt
));
1539 int git_submodule__status(
1540 unsigned int *out_status
,
1541 git_oid
*out_head_id
,
1542 git_oid
*out_index_id
,
1545 git_submodule_ignore_t ign
)
1547 unsigned int status
;
1548 git_repository
*smrepo
= NULL
;
1550 if (ign
== GIT_SUBMODULE_IGNORE_UNSPECIFIED
)
1553 /* only return location info if ignore == all */
1554 if (ign
== GIT_SUBMODULE_IGNORE_ALL
) {
1555 *out_status
= (sm
->flags
& GIT_SUBMODULE_STATUS__IN_FLAGS
);
1559 /* If the user has requested caching submodule state, performing these
1560 * expensive operations (especially `submodule_update_head`, which is
1561 * bottlenecked on `git_repository_head_tree`) eliminates much of the
1562 * advantage. We will, therefore, interpret the request for caching to
1563 * apply here to and skip them.
1566 if (sm
->repo
->submodule_cache
== NULL
) {
1567 /* refresh the index OID */
1568 if (submodule_update_index(sm
) < 0)
1571 /* refresh the HEAD OID */
1572 if (submodule_update_head(sm
) < 0)
1576 /* for ignore == dirty, don't scan the working directory */
1577 if (ign
== GIT_SUBMODULE_IGNORE_DIRTY
) {
1578 /* git_submodule_open_bare will load WD OID data */
1579 if (git_submodule_open_bare(&smrepo
, sm
) < 0)
1582 git_repository_free(smrepo
);
1584 } else if (git_submodule_open(&smrepo
, sm
) < 0) {
1589 status
= GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm
->flags
);
1591 submodule_get_index_status(&status
, sm
);
1592 submodule_get_wd_status(&status
, sm
, smrepo
, ign
);
1594 git_repository_free(smrepo
);
1596 *out_status
= status
;
1598 submodule_copy_oid_maybe(out_head_id
, &sm
->head_oid
,
1599 (sm
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
) != 0);
1600 submodule_copy_oid_maybe(out_index_id
, &sm
->index_oid
,
1601 (sm
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
) != 0);
1602 submodule_copy_oid_maybe(out_wd_id
, &sm
->wd_oid
,
1603 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) != 0);
1608 int git_submodule_status(unsigned int *status
, git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1613 assert(status
&& repo
&& name
);
1615 if ((error
= git_submodule_lookup(&sm
, repo
, name
)) < 0)
1618 error
= git_submodule__status(status
, NULL
, NULL
, NULL
, sm
, ignore
);
1619 git_submodule_free(sm
);
1624 int git_submodule_location(unsigned int *location
, git_submodule
*sm
)
1626 assert(location
&& sm
);
1628 return git_submodule__status(
1629 location
, NULL
, NULL
, NULL
, sm
, GIT_SUBMODULE_IGNORE_ALL
);
1633 * INTERNAL FUNCTIONS
1636 static int submodule_alloc(
1637 git_submodule
**out
, git_repository
*repo
, const char *name
)
1642 if (!name
|| !(namelen
= strlen(name
))) {
1643 giterr_set(GITERR_SUBMODULE
, "invalid submodule name");
1647 sm
= git__calloc(1, sizeof(git_submodule
));
1648 GITERR_CHECK_ALLOC(sm
);
1650 sm
->name
= sm
->path
= git__strdup(name
);
1656 GIT_REFCOUNT_INC(sm
);
1657 sm
->ignore
= sm
->ignore_default
= GIT_SUBMODULE_IGNORE_NONE
;
1658 sm
->update
= sm
->update_default
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1659 sm
->fetch_recurse
= sm
->fetch_recurse_default
= GIT_SUBMODULE_RECURSE_NO
;
1667 static void submodule_release(git_submodule
*sm
)
1676 if (sm
->path
!= sm
->name
)
1677 git__free(sm
->path
);
1678 git__free(sm
->name
);
1680 git__free(sm
->branch
);
1681 git__memzero(sm
, sizeof(*sm
));
1685 void git_submodule_free(git_submodule
*sm
)
1689 GIT_REFCOUNT_DEC(sm
, submodule_release
);
1692 static int submodule_config_error(const char *property
, const char *value
)
1694 giterr_set(GITERR_INVALID
,
1695 "invalid value for submodule '%s' property: '%s'", property
, value
);
1699 int git_submodule_parse_ignore(git_submodule_ignore_t
*out
, const char *value
)
1703 if (git_config_lookup_map_value(
1704 &val
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), value
) < 0) {
1705 *out
= GIT_SUBMODULE_IGNORE_NONE
;
1706 return submodule_config_error("ignore", value
);
1709 *out
= (git_submodule_ignore_t
)val
;
1713 int git_submodule_parse_update(git_submodule_update_t
*out
, const char *value
)
1717 if (git_config_lookup_map_value(
1718 &val
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), value
) < 0) {
1719 *out
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1720 return submodule_config_error("update", value
);
1723 *out
= (git_submodule_update_t
)val
;
1727 int git_submodule_parse_recurse(git_submodule_recurse_t
*out
, const char *value
)
1731 if (git_config_lookup_map_value(
1732 &val
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), value
) < 0) {
1733 *out
= GIT_SUBMODULE_RECURSE_YES
;
1734 return submodule_config_error("recurse", value
);
1737 *out
= (git_submodule_recurse_t
)val
;
1741 static int get_value(const char **out
, git_config
*cfg
, git_buf
*buf
, const char *name
, const char *field
)
1747 if ((error
= git_buf_printf(buf
, "submodule.%s.%s", name
, field
)) < 0 ||
1748 (error
= git_config_get_string(out
, cfg
, buf
->ptr
)) < 0)
1754 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
)
1756 git_buf key
= GIT_BUF_INIT
;
1758 int error
, in_config
= 0;
1761 * TODO: Look up path in index and if it is present but not a GITLINK
1762 * then this should be deleted (at least to match git's behavior)
1765 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "path")) == 0) {
1768 * TODO: if case insensitive filesystem, then the following strcmp
1769 * should be strcasecmp
1771 if (strcmp(sm
->name
, value
) != 0) {
1772 if (sm
->path
!= sm
->name
)
1773 git__free(sm
->path
);
1774 sm
->path
= git__strdup(value
);
1775 GITERR_CHECK_ALLOC(sm
->path
);
1777 } else if (error
!= GIT_ENOTFOUND
) {
1781 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "url")) == 0) {
1783 sm
->url
= git__strdup(value
);
1784 GITERR_CHECK_ALLOC(sm
->url
);
1785 } else if (error
!= GIT_ENOTFOUND
) {
1789 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "branch")) == 0) {
1791 sm
->branch
= git__strdup(value
);
1792 GITERR_CHECK_ALLOC(sm
->branch
);
1793 } else if (error
!= GIT_ENOTFOUND
) {
1797 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "update")) == 0) {
1799 if ((error
= git_submodule_parse_update(&sm
->update
, value
)) < 0)
1801 sm
->update_default
= sm
->update
;
1802 } else if (error
!= GIT_ENOTFOUND
) {
1806 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "fetchRecurseSubmodules")) == 0) {
1808 if ((error
= git_submodule_parse_recurse(&sm
->fetch_recurse
, value
)) < 0)
1810 sm
->fetch_recurse_default
= sm
->fetch_recurse
;
1811 } else if (error
!= GIT_ENOTFOUND
) {
1815 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "ignore")) == 0) {
1817 if ((error
= git_submodule_parse_ignore(&sm
->ignore
, value
)) < 0)
1819 sm
->ignore_default
= sm
->ignore
;
1820 } else if (error
!= GIT_ENOTFOUND
) {
1825 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
1834 static int submodule_load_each(const git_config_entry
*entry
, void *payload
)
1836 lfc_data
*data
= payload
;
1837 const char *namestart
, *property
;
1838 git_strmap_iter pos
;
1839 git_strmap
*map
= data
->map
;
1840 git_buf name
= GIT_BUF_INIT
;
1844 if (git__prefixcmp(entry
->name
, "submodule.") != 0)
1847 namestart
= entry
->name
+ strlen("submodule.");
1848 property
= strrchr(namestart
, '.');
1850 if (!property
|| (property
== namestart
))
1855 if ((error
= git_buf_set(&name
, namestart
, property
- namestart
-1)) < 0)
1859 * Now that we have the submodule's name, we can use that to
1860 * figure out whether it's in the map. If it's not, we create
1861 * a new submodule, load the config and insert it. If it's
1862 * already inserted, we've already loaded it, so we skip.
1864 pos
= git_strmap_lookup_index(map
, name
.ptr
);
1865 if (git_strmap_valid_index(map
, pos
)) {
1870 if ((error
= submodule_alloc(&sm
, data
->repo
, name
.ptr
)) < 0)
1873 if ((error
= submodule_read_config(sm
, data
->mods
)) < 0) {
1874 git_submodule_free(sm
);
1878 git_strmap_insert(map
, sm
->name
, sm
, &error
);
1886 git_buf_free(&name
);
1890 static int submodule_load_from_wd_lite(git_submodule
*sm
)
1892 git_buf path
= GIT_BUF_INIT
;
1894 if (git_buf_joinpath(&path
, git_repository_workdir(sm
->repo
), sm
->path
) < 0)
1897 if (git_path_isdir(path
.ptr
))
1898 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1900 if (git_path_contains(&path
, DOT_GIT
))
1901 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
;
1903 git_buf_free(&path
);
1908 * Returns a snapshot of $WORK_TREE/.gitmodules.
1910 * We ignore any errors and just pretend the file isn't there.
1912 static git_config
*gitmodules_snapshot(git_repository
*repo
)
1914 const char *workdir
= git_repository_workdir(repo
);
1915 git_config
*mods
= NULL
, *snap
= NULL
;
1916 git_buf path
= GIT_BUF_INIT
;
1918 if (workdir
!= NULL
) {
1919 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1922 if (git_config_open_ondisk(&mods
, path
.ptr
) < 0)
1926 git_buf_free(&path
);
1929 git_config_snapshot(&snap
, mods
);
1930 git_config_free(mods
);
1936 static git_config_backend
*open_gitmodules(
1937 git_repository
*repo
,
1940 const char *workdir
= git_repository_workdir(repo
);
1941 git_buf path
= GIT_BUF_INIT
;
1942 git_config_backend
*mods
= NULL
;
1944 if (workdir
!= NULL
) {
1945 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1948 if (okay_to_create
|| git_path_isfile(path
.ptr
)) {
1949 /* git_config_file__ondisk should only fail if OOM */
1950 if (git_config_file__ondisk(&mods
, path
.ptr
) < 0)
1952 /* open should only fail here if the file is malformed */
1953 else if (git_config_file_open(mods
, GIT_CONFIG_LEVEL_LOCAL
) < 0) {
1954 git_config_file_free(mods
);
1960 git_buf_free(&path
);
1965 /* Lookup name of remote of the local tracking branch HEAD points to */
1966 static int lookup_head_remote_key(git_buf
*remote_name
, git_repository
*repo
)
1969 git_reference
*head
= NULL
;
1970 git_buf upstream_name
= GIT_BUF_INIT
;
1972 /* lookup and dereference HEAD */
1973 if ((error
= git_repository_head(&head
, repo
)) < 0)
1977 * If head does not refer to a branch, then return
1978 * GIT_ENOTFOUND to indicate that we could not find
1979 * a remote key for the local tracking branch HEAD points to.
1981 if (!git_reference_is_branch(head
)) {
1982 giterr_set(GITERR_INVALID
,
1983 "HEAD does not refer to a branch.");
1984 error
= GIT_ENOTFOUND
;
1988 /* lookup remote tracking branch of HEAD */
1989 if ((error
= git_branch_upstream_name(
1992 git_reference_name(head
))) < 0)
1995 /* lookup remote of remote tracking branch */
1996 if ((error
= git_branch_remote_name(remote_name
, repo
, upstream_name
.ptr
)) < 0)
2000 git_buf_free(&upstream_name
);
2001 git_reference_free(head
);
2006 /* Lookup the remote of the local tracking branch HEAD points to */
2007 static int lookup_head_remote(git_remote
**remote
, git_repository
*repo
)
2010 git_buf remote_name
= GIT_BUF_INIT
;
2012 /* lookup remote of remote tracking branch name */
2013 if (!(error
= lookup_head_remote_key(&remote_name
, repo
)))
2014 error
= git_remote_lookup(remote
, repo
, remote_name
.ptr
);
2016 git_buf_free(&remote_name
);
2021 /* Lookup remote, either from HEAD or fall back on origin */
2022 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
)
2024 int error
= lookup_head_remote(remote
, repo
);
2026 /* if that failed, use 'origin' instead */
2027 if (error
== GIT_ENOTFOUND
)
2028 error
= git_remote_lookup(remote
, repo
, "origin");
2030 if (error
== GIT_ENOTFOUND
)
2033 "cannot get default remote for submodule - no local tracking "
2034 "branch for HEAD and origin does not exist");
2039 static int get_url_base(git_buf
*url
, git_repository
*repo
)
2042 git_worktree
*wt
= NULL
;
2043 git_remote
*remote
= NULL
;
2045 if ((error
= lookup_default_remote(&remote
, repo
)) == 0) {
2046 error
= git_buf_sets(url
, git_remote_url(remote
));
2048 } else if (error
!= GIT_ENOTFOUND
)
2053 /* if repository does not have a default remote, use workdir instead */
2054 if (git_repository_is_worktree(repo
)) {
2055 if ((error
= git_worktree_open_from_repository(&wt
, repo
)) < 0)
2057 error
= git_buf_sets(url
, wt
->parent_path
);
2059 error
= git_buf_sets(url
, git_repository_workdir(repo
));
2062 git_remote_free(remote
);
2063 git_worktree_free(wt
);
2068 static void submodule_get_index_status(unsigned int *status
, git_submodule
*sm
)
2070 const git_oid
*head_oid
= git_submodule_head_id(sm
);
2071 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2073 *status
= *status
& ~GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
2077 *status
|= GIT_SUBMODULE_STATUS_INDEX_ADDED
;
2079 else if (!index_oid
)
2080 *status
|= GIT_SUBMODULE_STATUS_INDEX_DELETED
;
2081 else if (!git_oid_equal(head_oid
, index_oid
))
2082 *status
|= GIT_SUBMODULE_STATUS_INDEX_MODIFIED
;
2086 static void submodule_get_wd_status(
2087 unsigned int *status
,
2089 git_repository
*sm_repo
,
2090 git_submodule_ignore_t ign
)
2092 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2093 const git_oid
*wd_oid
=
2094 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) ? &sm
->wd_oid
: NULL
;
2095 git_tree
*sm_head
= NULL
;
2096 git_index
*index
= NULL
;
2097 git_diff_options opt
= GIT_DIFF_OPTIONS_INIT
;
2100 *status
= *status
& ~GIT_SUBMODULE_STATUS__WD_FLAGS
;
2104 *status
|= GIT_SUBMODULE_STATUS_WD_ADDED
;
2107 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_SCANNED
) != 0 &&
2108 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) == 0)
2109 *status
|= GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
;
2111 *status
|= GIT_SUBMODULE_STATUS_WD_DELETED
;
2113 else if (!git_oid_equal(index_oid
, wd_oid
))
2114 *status
|= GIT_SUBMODULE_STATUS_WD_MODIFIED
;
2116 /* if we have no repo, then we're done */
2120 /* the diffs below could be optimized with an early termination
2121 * option to the git_diff functions, but for now this is sufficient
2122 * (and certainly no worse that what core git does).
2125 if (ign
== GIT_SUBMODULE_IGNORE_NONE
)
2126 opt
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
2128 (void)git_repository_index__weakptr(&index
, sm_repo
);
2130 /* if we don't have an unborn head, check diff with index */
2131 if (git_repository_head_tree(&sm_head
, sm_repo
) < 0)
2134 /* perform head to index diff on submodule */
2135 if (git_diff_tree_to_index(&diff
, sm_repo
, sm_head
, index
, &opt
) < 0)
2138 if (git_diff_num_deltas(diff
) > 0)
2139 *status
|= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
2140 git_diff_free(diff
);
2144 git_tree_free(sm_head
);
2147 /* perform index-to-workdir diff on submodule */
2148 if (git_diff_index_to_workdir(&diff
, sm_repo
, index
, &opt
) < 0)
2152 git_diff_num_deltas_of_type(diff
, GIT_DELTA_UNTRACKED
);
2155 *status
|= GIT_SUBMODULE_STATUS_WD_UNTRACKED
;
2157 if (git_diff_num_deltas(diff
) != untracked
)
2158 *status
|= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
;
2160 git_diff_free(diff
);