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"
26 #define GIT_MODULES_FILE ".gitmodules"
28 static git_cvar_map _sm_update_map
[] = {
29 {GIT_CVAR_STRING
, "checkout", GIT_SUBMODULE_UPDATE_CHECKOUT
},
30 {GIT_CVAR_STRING
, "rebase", GIT_SUBMODULE_UPDATE_REBASE
},
31 {GIT_CVAR_STRING
, "merge", GIT_SUBMODULE_UPDATE_MERGE
},
32 {GIT_CVAR_STRING
, "none", GIT_SUBMODULE_UPDATE_NONE
},
33 {GIT_CVAR_FALSE
, NULL
, GIT_SUBMODULE_UPDATE_NONE
},
34 {GIT_CVAR_TRUE
, NULL
, GIT_SUBMODULE_UPDATE_CHECKOUT
},
37 static git_cvar_map _sm_ignore_map
[] = {
38 {GIT_CVAR_STRING
, "none", GIT_SUBMODULE_IGNORE_NONE
},
39 {GIT_CVAR_STRING
, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED
},
40 {GIT_CVAR_STRING
, "dirty", GIT_SUBMODULE_IGNORE_DIRTY
},
41 {GIT_CVAR_STRING
, "all", GIT_SUBMODULE_IGNORE_ALL
},
42 {GIT_CVAR_FALSE
, NULL
, GIT_SUBMODULE_IGNORE_NONE
},
43 {GIT_CVAR_TRUE
, NULL
, GIT_SUBMODULE_IGNORE_ALL
},
46 static git_cvar_map _sm_recurse_map
[] = {
47 {GIT_CVAR_STRING
, "on-demand", GIT_SUBMODULE_RECURSE_ONDEMAND
},
48 {GIT_CVAR_FALSE
, NULL
, GIT_SUBMODULE_RECURSE_NO
},
49 {GIT_CVAR_TRUE
, NULL
, GIT_SUBMODULE_RECURSE_YES
},
58 GITMODULES_EXISTING
= 0,
59 GITMODULES_CREATE
= 1,
62 static kh_inline khint_t
str_hash_no_trailing_slash(const char *s
)
67 if (s
[1] != '\0' || *s
!= '/')
68 h
= (h
<< 5) - h
+ *s
;
73 static kh_inline
int str_equal_no_trailing_slash(const char *a
, const char *b
)
75 size_t alen
= a
? strlen(a
) : 0;
76 size_t blen
= b
? strlen(b
) : 0;
78 if (alen
> 0 && a
[alen
- 1] == '/')
80 if (blen
> 0 && b
[blen
- 1] == '/')
83 return (alen
== 0 && blen
== 0) ||
84 (alen
== blen
&& strncmp(a
, b
, alen
) == 0);
88 str
, static kh_inline
, const char *, void *, 1,
89 str_hash_no_trailing_slash
, str_equal_no_trailing_slash
)
91 static int submodule_alloc(git_submodule
**out
, git_repository
*repo
, const char *name
);
92 static git_config_backend
*open_gitmodules(git_repository
*repo
, int gitmod
);
93 static git_config
*gitmodules_snapshot(git_repository
*repo
);
94 static int get_url_base(git_buf
*url
, git_repository
*repo
);
95 static int lookup_head_remote_key(git_buf
*remote_key
, git_repository
*repo
);
96 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
);
97 static int submodule_load_each(const git_config_entry
*entry
, void *payload
);
98 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
);
99 static int submodule_load_from_wd_lite(git_submodule
*);
100 static void submodule_get_index_status(unsigned int *, git_submodule
*);
101 static void submodule_get_wd_status(unsigned int *, git_submodule
*, git_repository
*, git_submodule_ignore_t
);
102 static void submodule_update_from_index_entry(git_submodule
*sm
, const git_index_entry
*ie
);
103 static void submodule_update_from_head_data(git_submodule
*sm
, mode_t mode
, const git_oid
*id
);
105 static int submodule_cmp(const void *a
, const void *b
)
107 return strcmp(((git_submodule
*)a
)->name
, ((git_submodule
*)b
)->name
);
110 static int submodule_config_key_trunc_puts(git_buf
*key
, const char *suffix
)
112 ssize_t idx
= git_buf_rfind(key
, '.');
113 git_buf_truncate(key
, (size_t)(idx
+ 1));
114 return git_buf_puts(key
, suffix
);
121 static void submodule_set_lookup_error(int error
, const char *name
)
126 giterr_set(GITERR_SUBMODULE
, (error
== GIT_ENOTFOUND
) ?
127 "no submodule named '%s'" :
128 "submodule '%s' has not been added yet", name
);
136 static int find_by_path(const git_config_entry
*entry
, void *payload
)
138 fbp_data
*data
= payload
;
140 if (!strcmp(entry
->value
, data
->path
)) {
141 const char *fdot
, *ldot
;
142 fdot
= strchr(entry
->name
, '.');
143 ldot
= strrchr(entry
->name
, '.');
144 data
->name
= git__strndup(fdot
+ 1, ldot
- fdot
- 1);
145 GITERR_CHECK_ALLOC(data
->name
);
152 * Release the name map returned by 'load_submodule_names'.
154 static void free_submodule_names(git_strmap
*names
)
159 git_strmap_foreach_value(names
, name
, {
162 git_strmap_free(names
);
167 * Map submodule paths to names.
168 * TODO: for some use-cases, this might need case-folding on a
169 * case-insensitive filesystem
171 static int load_submodule_names(git_strmap
*out
, git_config
*cfg
)
173 const char *key
= "submodule\\..*\\.path";
174 git_config_iterator
*iter
;
175 git_config_entry
*entry
;
176 git_buf buf
= GIT_BUF_INIT
;
180 if ((error
= git_config_iterator_glob_new(&iter
, cfg
, key
)) < 0)
183 while (git_config_next(&entry
, iter
) == 0) {
184 const char *fdot
, *ldot
;
185 fdot
= strchr(entry
->name
, '.');
186 ldot
= strrchr(entry
->name
, '.');
188 git_buf_put(&buf
, fdot
+ 1, ldot
- fdot
- 1);
189 git_strmap_insert(out
, entry
->value
, git_buf_detach(&buf
), &rval
);
191 giterr_set(GITERR_NOMEMORY
, "error inserting submodule into hash table");
196 git_config_iterator_free(iter
);
200 int git_submodule_lookup(
201 git_submodule
**out
, /* NULL if user only wants to test existence */
202 git_repository
*repo
,
203 const char *name
) /* trailing slash is allowed */
206 unsigned int location
;
209 assert(repo
&& name
);
211 if (repo
->submodule_cache
!= NULL
) {
212 khiter_t pos
= git_strmap_lookup_index(repo
->submodule_cache
, name
);
213 if (git_strmap_valid_index(repo
->submodule_cache
, pos
)) {
215 *out
= git_strmap_value_at(repo
->submodule_cache
, pos
);
216 GIT_REFCOUNT_INC(*out
);
222 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
225 if ((error
= git_submodule_reload(sm
, false)) < 0) {
226 git_submodule_free(sm
);
230 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
231 git_submodule_free(sm
);
235 /* If it's not configured or we're looking by path */
236 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
237 git_config_backend
*mods
;
238 const char *pattern
= "submodule\\..*\\.path";
239 git_buf path
= GIT_BUF_INIT
;
240 fbp_data data
= { NULL
, NULL
};
242 git_buf_puts(&path
, name
);
243 while (path
.ptr
[path
.size
-1] == '/') {
244 path
.ptr
[--path
.size
] = '\0';
246 data
.path
= path
.ptr
;
248 mods
= open_gitmodules(repo
, GITMODULES_EXISTING
);
251 error
= git_config_file_foreach_match(mods
, pattern
, find_by_path
, &data
);
253 git_config_file_free(mods
);
256 git_submodule_free(sm
);
263 sm
->name
= data
.name
;
264 sm
->path
= git_buf_detach(&path
);
266 /* Try to load again with the right name */
267 if ((error
= git_submodule_reload(sm
, false)) < 0) {
268 git_submodule_free(sm
);
276 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
277 git_submodule_free(sm
);
281 /* If we still haven't found it, do the WD check */
282 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
283 git_submodule_free(sm
);
284 error
= GIT_ENOTFOUND
;
286 /* If it's not configured, we still check if there's a repo at the path */
287 if (git_repository_workdir(repo
)) {
288 git_buf path
= GIT_BUF_INIT
;
289 if (git_buf_join3(&path
,
290 '/', git_repository_workdir(repo
), name
, DOT_GIT
) < 0)
293 if (git_path_exists(path
.ptr
))
299 submodule_set_lookup_error(error
, name
);
306 git_submodule_free(sm
);
311 static void submodule_free_dup(void *sm
)
313 git_submodule_free(sm
);
316 static int submodule_get_or_create(git_submodule
**out
, git_repository
*repo
, git_strmap
*map
, const char *name
)
320 git_submodule
*sm
= NULL
;
322 pos
= git_strmap_lookup_index(map
, name
);
323 if (git_strmap_valid_index(map
, pos
)) {
324 sm
= git_strmap_value_at(map
, pos
);
328 /* if the submodule doesn't exist yet in the map, create it */
329 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
332 pos
= git_strmap_put(map
, sm
->name
, &error
);
333 /* nobody can beat us to adding it */
336 git_submodule_free(sm
);
340 git_strmap_set_value_at(map
, pos
, sm
);
343 GIT_REFCOUNT_INC(sm
);
348 static int submodules_from_index(git_strmap
*map
, git_index
*idx
, git_config
*cfg
)
351 git_iterator
*i
= NULL
;
352 const git_index_entry
*entry
;
353 git_strmap
*names
= 0;
355 git_strmap_alloc(&names
);
356 if ((error
= load_submodule_names(names
, cfg
)))
359 if ((error
= git_iterator_for_index(&i
, git_index_owner(idx
), idx
, NULL
)) < 0)
362 while (!(error
= git_iterator_advance(&entry
, i
))) {
363 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
366 if (git_strmap_valid_index(map
, pos
)) {
367 sm
= git_strmap_value_at(map
, pos
);
369 if (S_ISGITLINK(entry
->mode
))
370 submodule_update_from_index_entry(sm
, entry
);
372 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
373 } else if (S_ISGITLINK(entry
->mode
)) {
377 name_pos
= git_strmap_lookup_index(names
, entry
->path
);
378 if (git_strmap_valid_index(names
, name_pos
)) {
379 name
= git_strmap_value_at(names
, name_pos
);
384 if (!submodule_get_or_create(&sm
, git_index_owner(idx
), map
, name
)) {
385 submodule_update_from_index_entry(sm
, entry
);
386 git_submodule_free(sm
);
391 if (error
== GIT_ITEROVER
)
395 git_iterator_free(i
);
396 free_submodule_names(names
);
401 static int submodules_from_head(git_strmap
*map
, git_tree
*head
, git_config
*cfg
)
404 git_iterator
*i
= NULL
;
405 const git_index_entry
*entry
;
406 git_strmap
*names
= 0;
407 git_strmap_alloc(&names
);
408 if ((error
= load_submodule_names(names
, cfg
)))
411 if ((error
= git_iterator_for_tree(&i
, head
, NULL
)) < 0)
414 while (!(error
= git_iterator_advance(&entry
, i
))) {
415 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
418 if (git_strmap_valid_index(map
, pos
)) {
419 sm
= git_strmap_value_at(map
, pos
);
421 if (S_ISGITLINK(entry
->mode
))
422 submodule_update_from_head_data(sm
, entry
->mode
, &entry
->id
);
424 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
425 } else if (S_ISGITLINK(entry
->mode
)) {
429 name_pos
= git_strmap_lookup_index(names
, entry
->path
);
430 if (git_strmap_valid_index(names
, name_pos
)) {
431 name
= git_strmap_value_at(names
, name_pos
);
436 if (!submodule_get_or_create(&sm
, git_tree_owner(head
), map
, name
)) {
437 submodule_update_from_head_data(
438 sm
, entry
->mode
, &entry
->id
);
439 git_submodule_free(sm
);
444 if (error
== GIT_ITEROVER
)
448 git_iterator_free(i
);
449 free_submodule_names(names
);
454 /* If have_sm is true, sm is populated, otherwise map an repo are. */
458 git_repository
*repo
;
461 int git_submodule__map(git_repository
*repo
, git_strmap
*map
)
464 git_index
*idx
= NULL
;
465 git_tree
*head
= NULL
;
466 const char *wd
= NULL
;
467 git_buf path
= GIT_BUF_INIT
;
469 git_config
*mods
= NULL
;
474 /* get sources that we will need to check */
475 if (git_repository_index(&idx
, repo
) < 0)
477 if (git_repository_head_tree(&head
, repo
) < 0)
480 wd
= git_repository_workdir(repo
);
481 if (wd
&& (error
= git_buf_joinpath(&path
, wd
, GIT_MODULES_FILE
)) < 0)
484 /* clear submodule flags that are to be refreshed */
486 mask
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
487 GIT_SUBMODULE_STATUS__INDEX_FLAGS
|
488 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
|
489 GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
491 mask
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
492 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
493 mask
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
495 mask
|= GIT_SUBMODULE_STATUS_IN_WD
|
496 GIT_SUBMODULE_STATUS__WD_SCANNED
|
497 GIT_SUBMODULE_STATUS__WD_FLAGS
|
498 GIT_SUBMODULE_STATUS__WD_OID_VALID
;
500 /* add submodule information from .gitmodules */
502 lfc_data data
= { 0 };
506 if ((mods
= gitmodules_snapshot(repo
)) == NULL
)
510 if ((error
= git_config_foreach(
511 mods
, submodule_load_each
, &data
)) < 0)
514 /* add back submodule information from index */
516 if ((error
= submodules_from_index(map
, idx
, mods
)) < 0)
519 /* add submodule information from HEAD */
521 if ((error
= submodules_from_head(map
, head
, mods
)) < 0)
524 /* shallow scan submodules in work tree as needed */
525 if (wd
&& mask
!= 0) {
526 git_strmap_foreach_value(map
, sm
, {
527 submodule_load_from_wd_lite(sm
);
532 git_config_free(mods
);
533 /* TODO: if we got an error, mark submodule config as invalid? */
540 int git_submodule_foreach(
541 git_repository
*repo
,
542 git_submodule_cb callback
,
545 git_vector snapshot
= GIT_VECTOR_INIT
;
546 git_strmap
*submodules
;
551 if ((error
= git_strmap_alloc(&submodules
)) < 0)
554 if ((error
= git_submodule__map(repo
, submodules
)) < 0)
557 if (!(error
= git_vector_init(
558 &snapshot
, git_strmap_num_entries(submodules
), submodule_cmp
))) {
560 git_strmap_foreach_value(submodules
, sm
, {
561 if ((error
= git_vector_insert(&snapshot
, sm
)) < 0)
563 GIT_REFCOUNT_INC(sm
);
570 git_vector_uniq(&snapshot
, submodule_free_dup
);
572 git_vector_foreach(&snapshot
, i
, sm
) {
573 if ((error
= callback(sm
, sm
->name
, payload
)) != 0) {
574 giterr_set_after_callback(error
);
580 git_vector_foreach(&snapshot
, i
, sm
)
581 git_submodule_free(sm
);
582 git_vector_free(&snapshot
);
584 git_strmap_foreach_value(submodules
, sm
, {
585 git_submodule_free(sm
);
587 git_strmap_free(submodules
);
592 static int submodule_repo_init(
593 git_repository
**out
,
594 git_repository
*parent_repo
,
600 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
601 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
602 git_repository
*subrepo
= NULL
;
604 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
608 initopt
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_NO_REINIT
;
609 initopt
.origin_url
= url
;
611 /* init submodule repository and add origin remote as needed */
613 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
614 * gitlink in the sub-repo workdir directory to that repository
616 * Old style: sub-repo goes directly into repo/<name>/.git/
619 error
= git_repository_item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
622 error
= git_buf_joinpath(&repodir
, repodir
.ptr
, path
);
626 initopt
.workdir_path
= workdir
.ptr
;
628 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
629 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
631 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
633 error
= git_repository_init_ext(&subrepo
, workdir
.ptr
, &initopt
);
636 git_buf_free(&workdir
);
637 git_buf_free(&repodir
);
644 int git_submodule_add_setup(
646 git_repository
*repo
,
652 git_config_backend
*mods
= NULL
;
653 git_submodule
*sm
= NULL
;
654 git_buf name
= GIT_BUF_INIT
, real_url
= GIT_BUF_INIT
;
655 git_repository
*subrepo
= NULL
;
657 assert(repo
&& url
&& path
);
659 /* see if there is already an entry for this submodule */
661 if (git_submodule_lookup(NULL
, repo
, path
) < 0)
664 giterr_set(GITERR_SUBMODULE
,
665 "attempt to add submodule '%s' that already exists", path
);
669 /* validate and normalize path */
671 if (git__prefixcmp(path
, git_repository_workdir(repo
)) == 0)
672 path
+= strlen(git_repository_workdir(repo
));
674 if (git_path_root(path
) >= 0) {
675 giterr_set(GITERR_SUBMODULE
, "submodule path must be a relative path");
680 /* update .gitmodules */
682 if (!(mods
= open_gitmodules(repo
, GITMODULES_CREATE
))) {
683 giterr_set(GITERR_SUBMODULE
,
684 "adding submodules to a bare repository is not supported");
688 if ((error
= git_buf_printf(&name
, "submodule.%s.path", path
)) < 0 ||
689 (error
= git_config_file_set_string(mods
, name
.ptr
, path
)) < 0)
692 if ((error
= submodule_config_key_trunc_puts(&name
, "url")) < 0 ||
693 (error
= git_config_file_set_string(mods
, name
.ptr
, url
)) < 0)
696 git_buf_clear(&name
);
698 /* init submodule repository and add origin remote as needed */
700 error
= git_buf_joinpath(&name
, git_repository_workdir(repo
), path
);
704 /* if the repo does not already exist, then init a new repo and add it.
705 * Otherwise, just add the existing repo.
707 if (!(git_path_exists(name
.ptr
) &&
708 git_path_contains(&name
, DOT_GIT
))) {
710 /* resolve the actual URL to use */
711 if ((error
= git_submodule_resolve_url(&real_url
, repo
, url
)) < 0)
714 if ((error
= submodule_repo_init(&subrepo
, repo
, path
, real_url
.ptr
, use_gitlink
)) < 0)
718 if ((error
= git_submodule_lookup(&sm
, repo
, path
)) < 0)
721 error
= git_submodule_init(sm
, false);
725 git_submodule_free(sm
);
731 git_config_file_free(mods
);
732 git_repository_free(subrepo
);
733 git_buf_free(&real_url
);
739 int git_submodule_repo_init(
740 git_repository
**out
,
741 const git_submodule
*sm
,
745 git_repository
*sub_repo
= NULL
;
746 const char *configured_url
;
747 git_config
*cfg
= NULL
;
748 git_buf buf
= GIT_BUF_INIT
;
752 /* get the configured remote url of the submodule */
753 if ((error
= git_buf_printf(&buf
, "submodule.%s.url", sm
->name
)) < 0 ||
754 (error
= git_repository_config_snapshot(&cfg
, sm
->repo
)) < 0 ||
755 (error
= git_config_get_string(&configured_url
, cfg
, buf
.ptr
)) < 0 ||
756 (error
= submodule_repo_init(&sub_repo
, sm
->repo
, sm
->path
, configured_url
, use_gitlink
)) < 0)
762 git_config_free(cfg
);
767 int git_submodule_add_finalize(git_submodule
*sm
)
774 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
775 (error
= git_index_add_bypath(index
, GIT_MODULES_FILE
)) < 0)
778 return git_submodule_add_to_index(sm
, true);
781 int git_submodule_add_to_index(git_submodule
*sm
, int write_index
)
784 git_repository
*sm_repo
= NULL
;
786 git_buf path
= GIT_BUF_INIT
;
788 git_index_entry entry
;
793 /* force reload of wd OID by git_submodule_open */
794 sm
->flags
= sm
->flags
& ~GIT_SUBMODULE_STATUS__WD_OID_VALID
;
796 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
797 (error
= git_buf_joinpath(
798 &path
, git_repository_workdir(sm
->repo
), sm
->path
)) < 0 ||
799 (error
= git_submodule_open(&sm_repo
, sm
)) < 0)
802 /* read stat information for submodule working directory */
803 if (p_stat(path
.ptr
, &st
) < 0) {
804 giterr_set(GITERR_SUBMODULE
,
805 "cannot add submodule without working directory");
810 memset(&entry
, 0, sizeof(entry
));
811 entry
.path
= sm
->path
;
812 git_index_entry__init_from_stat(
813 &entry
, &st
, !(git_index_caps(index
) & GIT_INDEXCAP_NO_FILEMODE
));
815 /* calling git_submodule_open will have set sm->wd_oid if possible */
816 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) == 0) {
817 giterr_set(GITERR_SUBMODULE
,
818 "cannot add submodule without HEAD to index");
822 git_oid_cpy(&entry
.id
, &sm
->wd_oid
);
824 if ((error
= git_commit_lookup(&head
, sm_repo
, &sm
->wd_oid
)) < 0)
827 entry
.ctime
.seconds
= (int32_t)git_commit_time(head
);
828 entry
.ctime
.nanoseconds
= 0;
829 entry
.mtime
.seconds
= (int32_t)git_commit_time(head
);
830 entry
.mtime
.nanoseconds
= 0;
832 git_commit_free(head
);
835 error
= git_index_add(index
, &entry
);
837 /* write it, if requested */
838 if (!error
&& write_index
) {
839 error
= git_index_write(index
);
842 git_oid_cpy(&sm
->index_oid
, &sm
->wd_oid
);
846 git_repository_free(sm_repo
);
851 const char *git_submodule_update_to_str(git_submodule_update_t update
)
854 for (i
= 0; i
< (int)ARRAY_SIZE(_sm_update_map
); ++i
)
855 if (_sm_update_map
[i
].map_value
== (int)update
)
856 return _sm_update_map
[i
].str_match
;
860 git_repository
*git_submodule_owner(git_submodule
*submodule
)
863 return submodule
->repo
;
866 const char *git_submodule_name(git_submodule
*submodule
)
869 return submodule
->name
;
872 const char *git_submodule_path(git_submodule
*submodule
)
875 return submodule
->path
;
878 const char *git_submodule_url(git_submodule
*submodule
)
881 return submodule
->url
;
884 int git_submodule_resolve_url(git_buf
*out
, git_repository
*repo
, const char *url
)
887 git_buf normalized
= GIT_BUF_INIT
;
889 assert(out
&& repo
&& url
);
891 git_buf_sanitize(out
);
893 /* We do this in all platforms in case someone on Windows created the .gitmodules */
894 if (strchr(url
, '\\')) {
895 if ((error
= git_path_normalize_slashes(&normalized
, url
)) < 0)
898 url
= normalized
.ptr
;
902 if (git_path_is_relative(url
)) {
903 if (!(error
= get_url_base(out
, repo
)))
904 error
= git_path_apply_relative(out
, url
);
905 } else if (strchr(url
, ':') != NULL
|| url
[0] == '/') {
906 error
= git_buf_sets(out
, url
);
908 giterr_set(GITERR_SUBMODULE
, "invalid format for submodule URL");
912 git_buf_free(&normalized
);
916 static int write_var(git_repository
*repo
, const char *name
, const char *var
, const char *val
)
918 git_buf key
= GIT_BUF_INIT
;
919 git_config_backend
*mods
;
922 mods
= open_gitmodules(repo
, GITMODULES_CREATE
);
926 if ((error
= git_buf_printf(&key
, "submodule.%s.%s", name
, var
)) < 0)
930 error
= git_config_file_set_string(mods
, key
.ptr
, val
);
932 error
= git_config_file_delete(mods
, key
.ptr
);
937 git_config_file_free(mods
);
941 static int write_mapped_var(git_repository
*repo
, const char *name
, git_cvar_map
*maps
, size_t nmaps
, const char *var
, int ival
)
946 if (git_config_lookup_map_enum(&type
, &val
, maps
, nmaps
, ival
) < 0) {
947 giterr_set(GITERR_SUBMODULE
, "invalid value for %s", var
);
951 if (type
== GIT_CVAR_TRUE
)
954 return write_var(repo
, name
, var
, val
);
957 const char *git_submodule_branch(git_submodule
*submodule
)
960 return submodule
->branch
;
963 int git_submodule_set_branch(git_repository
*repo
, const char *name
, const char *branch
)
966 assert(repo
&& name
);
968 return write_var(repo
, name
, "branch", branch
);
971 int git_submodule_set_url(git_repository
*repo
, const char *name
, const char *url
)
973 assert(repo
&& name
&& url
);
975 return write_var(repo
, name
, "url", url
);
978 const git_oid
*git_submodule_index_id(git_submodule
*submodule
)
982 if (submodule
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
983 return &submodule
->index_oid
;
988 const git_oid
*git_submodule_head_id(git_submodule
*submodule
)
992 if (submodule
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
993 return &submodule
->head_oid
;
998 const git_oid
*git_submodule_wd_id(git_submodule
*submodule
)
1002 /* load unless we think we have a valid oid */
1003 if (!(submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)) {
1004 git_repository
*subrepo
;
1006 /* calling submodule open grabs the HEAD OID if possible */
1007 if (!git_submodule_open_bare(&subrepo
, submodule
))
1008 git_repository_free(subrepo
);
1013 if (submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)
1014 return &submodule
->wd_oid
;
1019 git_submodule_ignore_t
git_submodule_ignore(git_submodule
*submodule
)
1022 return (submodule
->ignore
< GIT_SUBMODULE_IGNORE_NONE
) ?
1023 GIT_SUBMODULE_IGNORE_NONE
: submodule
->ignore
;
1026 int git_submodule_set_ignore(git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1028 assert(repo
&& name
);
1030 return write_mapped_var(repo
, name
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), "ignore", ignore
);
1033 git_submodule_update_t
git_submodule_update_strategy(git_submodule
*submodule
)
1036 return (submodule
->update
< GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1037 GIT_SUBMODULE_UPDATE_CHECKOUT
: submodule
->update
;
1040 int git_submodule_set_update(git_repository
*repo
, const char *name
, git_submodule_update_t update
)
1042 assert(repo
&& name
);
1044 return write_mapped_var(repo
, name
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), "update", update
);
1047 git_submodule_recurse_t
git_submodule_fetch_recurse_submodules(
1048 git_submodule
*submodule
)
1051 return submodule
->fetch_recurse
;
1054 int git_submodule_set_fetch_recurse_submodules(git_repository
*repo
, const char *name
, git_submodule_recurse_t recurse
)
1056 assert(repo
&& name
);
1058 return write_mapped_var(repo
, name
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), "fetchRecurseSubmodules", recurse
);
1061 static int submodule_repo_create(
1062 git_repository
**out
,
1063 git_repository
*parent_repo
,
1067 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
1068 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
1069 git_repository
*subrepo
= NULL
;
1072 GIT_REPOSITORY_INIT_MKPATH
|
1073 GIT_REPOSITORY_INIT_NO_REINIT
|
1074 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
1075 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
1077 /* Workdir: path to sub-repo working directory */
1078 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
1082 initopt
.workdir_path
= workdir
.ptr
;
1085 * Repodir: path to the sub-repo. sub-repo goes in:
1086 * <repo-dir>/modules/<name>/ with a gitlink in the
1087 * sub-repo workdir directory to that repository.
1089 error
= git_repository_item_path(&repodir
, parent_repo
, GIT_REPOSITORY_ITEM_MODULES
);
1092 error
= git_buf_joinpath(&repodir
, repodir
.ptr
, path
);
1096 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
1099 git_buf_free(&workdir
);
1100 git_buf_free(&repodir
);
1108 * Callback to override sub-repository creation when
1109 * cloning a sub-repository.
1111 static int git_submodule_update_repo_init_cb(
1112 git_repository
**out
,
1123 return submodule_repo_create(out
, sm
->repo
, path
);
1126 int git_submodule_update_init_options(git_submodule_update_options
*opts
, unsigned int version
)
1128 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1129 opts
, version
, git_submodule_update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_INIT
);
1133 int git_submodule_update(git_submodule
*sm
, int init
, git_submodule_update_options
*_update_options
)
1136 unsigned int submodule_status
;
1137 git_config
*config
= NULL
;
1138 const char *submodule_url
;
1139 git_repository
*sub_repo
= NULL
;
1140 git_remote
*remote
= NULL
;
1141 git_object
*target_commit
= NULL
;
1142 git_buf buf
= GIT_BUF_INIT
;
1143 git_submodule_update_options update_options
= GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
1144 git_clone_options clone_options
= GIT_CLONE_OPTIONS_INIT
;
1148 if (_update_options
)
1149 memcpy(&update_options
, _update_options
, sizeof(git_submodule_update_options
));
1151 GITERR_CHECK_VERSION(&update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
1153 /* Copy over the remote callbacks */
1154 memcpy(&clone_options
.fetch_opts
, &update_options
.fetch_opts
, sizeof(git_fetch_options
));
1156 /* Get the status of the submodule to determine if it is already initialized */
1157 if ((error
= git_submodule_status(&submodule_status
, sm
->repo
, sm
->name
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
)) < 0)
1161 * If submodule work dir is not already initialized, check to see
1162 * what we need to do (initialize, clone, return error...)
1164 if (submodule_status
& GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
) {
1166 * Work dir is not initialized, check to see if the submodule
1167 * info has been copied into .git/config
1169 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1170 (error
= git_buf_printf(&buf
, "submodule.%s.url", git_submodule_name(sm
))) < 0)
1173 if ((error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0) {
1175 * If the error is not "not found" or if it is "not found" and we are not
1176 * initializing the submodule, then return error.
1178 if (error
!= GIT_ENOTFOUND
)
1182 giterr_set(GITERR_SUBMODULE
, "submodule is not initialized");
1187 /* The submodule has not been initialized yet - initialize it now.*/
1188 if ((error
= git_submodule_init(sm
, 0)) < 0)
1191 git_config_free(config
);
1194 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1195 (error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0)
1199 /** submodule is initialized - now clone it **/
1200 /* override repo creation */
1201 clone_options
.repository_cb
= git_submodule_update_repo_init_cb
;
1202 clone_options
.repository_cb_payload
= sm
;
1205 * Do not perform checkout as part of clone, instead we
1206 * will checkout the specific commit manually.
1208 clone_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
1210 if ((error
= git_clone(&sub_repo
, submodule_url
, sm
->path
, &clone_options
)) < 0 ||
1211 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0 ||
1212 (error
= git_checkout_head(sub_repo
, &update_options
.checkout_opts
)) != 0)
1216 * Work dir is initialized - look up the commit in the parent repository's index,
1217 * update the workdir contents of the subrepository, and set the subrepository's
1218 * head to the new commit.
1220 if ((error
= git_submodule_open(&sub_repo
, sm
)) < 0)
1223 /* Look up the target commit in the submodule. */
1224 if ((error
= git_object_lookup(&target_commit
, sub_repo
, git_submodule_index_id(sm
), GIT_OBJ_COMMIT
)) < 0) {
1225 /* If it isn't found then fetch and try again. */
1226 if (error
!= GIT_ENOTFOUND
|| !update_options
.allow_fetch
||
1227 (error
= lookup_default_remote(&remote
, sub_repo
)) < 0 ||
1228 (error
= git_remote_fetch(remote
, NULL
, &update_options
.fetch_opts
, NULL
)) < 0 ||
1229 (error
= git_object_lookup(&target_commit
, sub_repo
, git_submodule_index_id(sm
), GIT_OBJ_COMMIT
)) < 0)
1233 if ((error
= git_checkout_tree(sub_repo
, target_commit
, &update_options
.checkout_opts
)) != 0 ||
1234 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0)
1237 /* Invalidate the wd flags as the workdir has been updated. */
1238 sm
->flags
= sm
->flags
&
1239 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1240 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1241 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1246 git_config_free(config
);
1247 git_object_free(target_commit
);
1248 git_remote_free(remote
);
1249 git_repository_free(sub_repo
);
1254 int git_submodule_init(git_submodule
*sm
, int overwrite
)
1258 git_buf key
= GIT_BUF_INIT
, effective_submodule_url
= GIT_BUF_INIT
;
1259 git_config
*cfg
= NULL
;
1262 giterr_set(GITERR_SUBMODULE
,
1263 "no URL configured for submodule '%s'", sm
->name
);
1267 if ((error
= git_repository_config(&cfg
, sm
->repo
)) < 0)
1270 /* write "submodule.NAME.url" */
1272 if ((error
= git_submodule_resolve_url(&effective_submodule_url
, sm
->repo
, sm
->url
)) < 0 ||
1273 (error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)) < 0 ||
1274 (error
= git_config__update_entry(
1275 cfg
, key
.ptr
, effective_submodule_url
.ptr
, overwrite
!= 0, false)) < 0)
1278 /* write "submodule.NAME.update" if not default */
1280 val
= (sm
->update
== GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1281 NULL
: git_submodule_update_to_str(sm
->update
);
1283 if ((error
= git_buf_printf(&key
, "submodule.%s.update", sm
->name
)) < 0 ||
1284 (error
= git_config__update_entry(
1285 cfg
, key
.ptr
, val
, overwrite
!= 0, false)) < 0)
1291 git_config_free(cfg
);
1293 git_buf_free(&effective_submodule_url
);
1298 int git_submodule_sync(git_submodule
*sm
)
1301 git_config
*cfg
= NULL
;
1302 git_buf key
= GIT_BUF_INIT
;
1303 git_repository
*smrepo
= NULL
;
1306 giterr_set(GITERR_SUBMODULE
,
1307 "no URL configured for submodule '%s'", sm
->name
);
1311 /* copy URL over to config only if it already exists */
1313 if (!(error
= git_repository_config__weakptr(&cfg
, sm
->repo
)) &&
1314 !(error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)))
1315 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, true);
1317 /* if submodule exists in the working directory, update remote url */
1320 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) != 0 &&
1321 !(error
= git_submodule_open(&smrepo
, sm
)))
1323 git_buf remote_name
= GIT_BUF_INIT
;
1325 if ((error
= git_repository_config__weakptr(&cfg
, smrepo
)) < 0)
1326 /* return error from reading submodule config */;
1327 else if ((error
= lookup_head_remote_key(&remote_name
, smrepo
)) < 0) {
1329 error
= git_buf_sets(&key
, "remote.origin.url");
1331 error
= git_buf_join3(
1332 &key
, '.', "remote", remote_name
.ptr
, "url");
1333 git_buf_free(&remote_name
);
1337 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, false);
1339 git_repository_free(smrepo
);
1347 static int git_submodule__open(
1348 git_repository
**subrepo
, git_submodule
*sm
, bool bare
)
1351 git_buf path
= GIT_BUF_INIT
;
1352 unsigned int flags
= GIT_REPOSITORY_OPEN_NO_SEARCH
;
1355 assert(sm
&& subrepo
);
1357 if (git_repository__ensure_not_bare(
1358 sm
->repo
, "open submodule repository") < 0)
1359 return GIT_EBAREREPO
;
1361 wd
= git_repository_workdir(sm
->repo
);
1363 if (git_buf_joinpath(&path
, wd
, sm
->path
) < 0 ||
1364 git_buf_joinpath(&path
, path
.ptr
, DOT_GIT
) < 0)
1367 sm
->flags
= sm
->flags
&
1368 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1369 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1370 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1373 flags
|= GIT_REPOSITORY_OPEN_BARE
;
1375 error
= git_repository_open_ext(subrepo
, path
.ptr
, flags
, wd
);
1377 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1379 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
|
1380 GIT_SUBMODULE_STATUS__WD_SCANNED
;
1382 if (!git_reference_name_to_id(&sm
->wd_oid
, *subrepo
, GIT_HEAD_FILE
))
1383 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_OID_VALID
;
1386 } else if (git_path_exists(path
.ptr
)) {
1387 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
|
1388 GIT_SUBMODULE_STATUS_IN_WD
;
1390 git_buf_rtruncate_at_char(&path
, '/'); /* remove "/.git" */
1392 if (git_path_isdir(path
.ptr
))
1393 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1396 git_buf_free(&path
);
1401 int git_submodule_open_bare(git_repository
**subrepo
, git_submodule
*sm
)
1403 return git_submodule__open(subrepo
, sm
, true);
1406 int git_submodule_open(git_repository
**subrepo
, git_submodule
*sm
)
1408 return git_submodule__open(subrepo
, sm
, false);
1411 static void submodule_update_from_index_entry(
1412 git_submodule
*sm
, const git_index_entry
*ie
)
1414 bool already_found
= (sm
->flags
& GIT_SUBMODULE_STATUS_IN_INDEX
) != 0;
1416 if (!S_ISGITLINK(ie
->mode
)) {
1418 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
1421 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
1423 git_oid_cpy(&sm
->index_oid
, &ie
->id
);
1425 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
1426 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
1430 static int submodule_update_index(git_submodule
*sm
)
1433 const git_index_entry
*ie
;
1435 if (git_repository_index__weakptr(&index
, sm
->repo
) < 0)
1438 sm
->flags
= sm
->flags
&
1439 ~(GIT_SUBMODULE_STATUS_IN_INDEX
|
1440 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
1442 if (!(ie
= git_index_get_bypath(index
, sm
->path
, 0)))
1445 submodule_update_from_index_entry(sm
, ie
);
1450 static void submodule_update_from_head_data(
1451 git_submodule
*sm
, mode_t mode
, const git_oid
*id
)
1453 if (!S_ISGITLINK(mode
))
1454 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
1456 git_oid_cpy(&sm
->head_oid
, id
);
1458 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
1459 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
1463 static int submodule_update_head(git_submodule
*submodule
)
1465 git_tree
*head
= NULL
;
1466 git_tree_entry
*te
= NULL
;
1468 submodule
->flags
= submodule
->flags
&
1469 ~(GIT_SUBMODULE_STATUS_IN_HEAD
|
1470 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
1472 /* if we can't look up file in current head, then done */
1473 if (git_repository_head_tree(&head
, submodule
->repo
) < 0 ||
1474 git_tree_entry_bypath(&te
, head
, submodule
->path
) < 0)
1477 submodule_update_from_head_data(submodule
, te
->attr
, git_tree_entry_id(te
));
1479 git_tree_entry_free(te
);
1480 git_tree_free(head
);
1484 int git_submodule_reload(git_submodule
*sm
, int force
)
1493 if (!git_repository_is_bare(sm
->repo
)) {
1494 /* refresh config data */
1495 mods
= gitmodules_snapshot(sm
->repo
);
1497 error
= submodule_read_config(sm
, mods
);
1498 git_config_free(mods
);
1504 /* refresh wd data */
1506 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1507 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1508 GIT_SUBMODULE_STATUS__WD_FLAGS
);
1510 error
= submodule_load_from_wd_lite(sm
);
1513 if (error
== 0 && (error
= submodule_update_index(sm
)) == 0)
1514 error
= submodule_update_head(sm
);
1519 static void submodule_copy_oid_maybe(
1520 git_oid
*tgt
, const git_oid
*src
, bool valid
)
1524 memcpy(tgt
, src
, sizeof(*tgt
));
1526 memset(tgt
, 0, sizeof(*tgt
));
1530 int git_submodule__status(
1531 unsigned int *out_status
,
1532 git_oid
*out_head_id
,
1533 git_oid
*out_index_id
,
1536 git_submodule_ignore_t ign
)
1538 unsigned int status
;
1539 git_repository
*smrepo
= NULL
;
1541 if (ign
== GIT_SUBMODULE_IGNORE_UNSPECIFIED
)
1544 /* only return location info if ignore == all */
1545 if (ign
== GIT_SUBMODULE_IGNORE_ALL
) {
1546 *out_status
= (sm
->flags
& GIT_SUBMODULE_STATUS__IN_FLAGS
);
1550 /* If the user has requested caching submodule state, performing these
1551 * expensive operations (especially `submodule_update_head`, which is
1552 * bottlenecked on `git_repository_head_tree`) eliminates much of the
1553 * advantage. We will, therefore, interpret the request for caching to
1554 * apply here to and skip them.
1557 if (sm
->repo
->submodule_cache
== NULL
) {
1558 /* refresh the index OID */
1559 if (submodule_update_index(sm
) < 0)
1562 /* refresh the HEAD OID */
1563 if (submodule_update_head(sm
) < 0)
1567 /* for ignore == dirty, don't scan the working directory */
1568 if (ign
== GIT_SUBMODULE_IGNORE_DIRTY
) {
1569 /* git_submodule_open_bare will load WD OID data */
1570 if (git_submodule_open_bare(&smrepo
, sm
) < 0)
1573 git_repository_free(smrepo
);
1575 } else if (git_submodule_open(&smrepo
, sm
) < 0) {
1580 status
= GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm
->flags
);
1582 submodule_get_index_status(&status
, sm
);
1583 submodule_get_wd_status(&status
, sm
, smrepo
, ign
);
1585 git_repository_free(smrepo
);
1587 *out_status
= status
;
1589 submodule_copy_oid_maybe(out_head_id
, &sm
->head_oid
,
1590 (sm
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
) != 0);
1591 submodule_copy_oid_maybe(out_index_id
, &sm
->index_oid
,
1592 (sm
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
) != 0);
1593 submodule_copy_oid_maybe(out_wd_id
, &sm
->wd_oid
,
1594 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) != 0);
1599 int git_submodule_status(unsigned int *status
, git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1604 assert(status
&& repo
&& name
);
1606 if ((error
= git_submodule_lookup(&sm
, repo
, name
)) < 0)
1609 error
= git_submodule__status(status
, NULL
, NULL
, NULL
, sm
, ignore
);
1610 git_submodule_free(sm
);
1615 int git_submodule_location(unsigned int *location
, git_submodule
*sm
)
1617 assert(location
&& sm
);
1619 return git_submodule__status(
1620 location
, NULL
, NULL
, NULL
, sm
, GIT_SUBMODULE_IGNORE_ALL
);
1624 * INTERNAL FUNCTIONS
1627 static int submodule_alloc(
1628 git_submodule
**out
, git_repository
*repo
, const char *name
)
1633 if (!name
|| !(namelen
= strlen(name
))) {
1634 giterr_set(GITERR_SUBMODULE
, "invalid submodule name");
1638 sm
= git__calloc(1, sizeof(git_submodule
));
1639 GITERR_CHECK_ALLOC(sm
);
1641 sm
->name
= sm
->path
= git__strdup(name
);
1647 GIT_REFCOUNT_INC(sm
);
1648 sm
->ignore
= sm
->ignore_default
= GIT_SUBMODULE_IGNORE_NONE
;
1649 sm
->update
= sm
->update_default
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1650 sm
->fetch_recurse
= sm
->fetch_recurse_default
= GIT_SUBMODULE_RECURSE_NO
;
1658 static void submodule_release(git_submodule
*sm
)
1667 if (sm
->path
!= sm
->name
)
1668 git__free(sm
->path
);
1669 git__free(sm
->name
);
1671 git__free(sm
->branch
);
1672 git__memzero(sm
, sizeof(*sm
));
1676 void git_submodule_free(git_submodule
*sm
)
1680 GIT_REFCOUNT_DEC(sm
, submodule_release
);
1683 static int submodule_config_error(const char *property
, const char *value
)
1685 giterr_set(GITERR_INVALID
,
1686 "invalid value for submodule '%s' property: '%s'", property
, value
);
1690 int git_submodule_parse_ignore(git_submodule_ignore_t
*out
, const char *value
)
1694 if (git_config_lookup_map_value(
1695 &val
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), value
) < 0) {
1696 *out
= GIT_SUBMODULE_IGNORE_NONE
;
1697 return submodule_config_error("ignore", value
);
1700 *out
= (git_submodule_ignore_t
)val
;
1704 int git_submodule_parse_update(git_submodule_update_t
*out
, const char *value
)
1708 if (git_config_lookup_map_value(
1709 &val
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), value
) < 0) {
1710 *out
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1711 return submodule_config_error("update", value
);
1714 *out
= (git_submodule_update_t
)val
;
1718 int git_submodule_parse_recurse(git_submodule_recurse_t
*out
, const char *value
)
1722 if (git_config_lookup_map_value(
1723 &val
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), value
) < 0) {
1724 *out
= GIT_SUBMODULE_RECURSE_YES
;
1725 return submodule_config_error("recurse", value
);
1728 *out
= (git_submodule_recurse_t
)val
;
1732 static int get_value(const char **out
, git_config
*cfg
, git_buf
*buf
, const char *name
, const char *field
)
1738 if ((error
= git_buf_printf(buf
, "submodule.%s.%s", name
, field
)) < 0 ||
1739 (error
= git_config_get_string(out
, cfg
, buf
->ptr
)) < 0)
1745 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
)
1747 git_buf key
= GIT_BUF_INIT
;
1749 int error
, in_config
= 0;
1752 * TODO: Look up path in index and if it is present but not a GITLINK
1753 * then this should be deleted (at least to match git's behavior)
1756 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "path")) == 0) {
1759 * TODO: if case insensitive filesystem, then the following strcmp
1760 * should be strcasecmp
1762 if (strcmp(sm
->name
, value
) != 0) {
1763 if (sm
->path
!= sm
->name
)
1764 git__free(sm
->path
);
1765 sm
->path
= git__strdup(value
);
1766 GITERR_CHECK_ALLOC(sm
->path
);
1768 } else if (error
!= GIT_ENOTFOUND
) {
1772 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "url")) == 0) {
1774 sm
->url
= git__strdup(value
);
1775 GITERR_CHECK_ALLOC(sm
->url
);
1776 } else if (error
!= GIT_ENOTFOUND
) {
1780 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "branch")) == 0) {
1782 sm
->branch
= git__strdup(value
);
1783 GITERR_CHECK_ALLOC(sm
->branch
);
1784 } else if (error
!= GIT_ENOTFOUND
) {
1788 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "update")) == 0) {
1790 if ((error
= git_submodule_parse_update(&sm
->update
, value
)) < 0)
1792 sm
->update_default
= sm
->update
;
1793 } else if (error
!= GIT_ENOTFOUND
) {
1797 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "fetchRecurseSubmodules")) == 0) {
1799 if ((error
= git_submodule_parse_recurse(&sm
->fetch_recurse
, value
)) < 0)
1801 sm
->fetch_recurse_default
= sm
->fetch_recurse
;
1802 } else if (error
!= GIT_ENOTFOUND
) {
1806 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "ignore")) == 0) {
1808 if ((error
= git_submodule_parse_ignore(&sm
->ignore
, value
)) < 0)
1810 sm
->ignore_default
= sm
->ignore
;
1811 } else if (error
!= GIT_ENOTFOUND
) {
1816 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
1825 static int submodule_load_each(const git_config_entry
*entry
, void *payload
)
1827 lfc_data
*data
= payload
;
1828 const char *namestart
, *property
;
1829 git_strmap_iter pos
;
1830 git_strmap
*map
= data
->map
;
1831 git_buf name
= GIT_BUF_INIT
;
1835 if (git__prefixcmp(entry
->name
, "submodule.") != 0)
1838 namestart
= entry
->name
+ strlen("submodule.");
1839 property
= strrchr(namestart
, '.');
1841 if (!property
|| (property
== namestart
))
1846 if ((error
= git_buf_set(&name
, namestart
, property
- namestart
-1)) < 0)
1850 * Now that we have the submodule's name, we can use that to
1851 * figure out whether it's in the map. If it's not, we create
1852 * a new submodule, load the config and insert it. If it's
1853 * already inserted, we've already loaded it, so we skip.
1855 pos
= git_strmap_lookup_index(map
, name
.ptr
);
1856 if (git_strmap_valid_index(map
, pos
)) {
1861 if ((error
= submodule_alloc(&sm
, data
->repo
, name
.ptr
)) < 0)
1864 if ((error
= submodule_read_config(sm
, data
->mods
)) < 0) {
1865 git_submodule_free(sm
);
1869 git_strmap_insert(map
, sm
->name
, sm
, &error
);
1877 git_buf_free(&name
);
1881 static int submodule_load_from_wd_lite(git_submodule
*sm
)
1883 git_buf path
= GIT_BUF_INIT
;
1885 if (git_buf_joinpath(&path
, git_repository_workdir(sm
->repo
), sm
->path
) < 0)
1888 if (git_path_isdir(path
.ptr
))
1889 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1891 if (git_path_contains(&path
, DOT_GIT
))
1892 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
;
1894 git_buf_free(&path
);
1899 * Returns a snapshot of $WORK_TREE/.gitmodules.
1901 * We ignore any errors and just pretend the file isn't there.
1903 static git_config
*gitmodules_snapshot(git_repository
*repo
)
1905 const char *workdir
= git_repository_workdir(repo
);
1906 git_config
*mods
= NULL
, *snap
= NULL
;
1907 git_buf path
= GIT_BUF_INIT
;
1909 if (workdir
!= NULL
) {
1910 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1913 if (git_config_open_ondisk(&mods
, path
.ptr
) < 0)
1917 git_buf_free(&path
);
1920 git_config_snapshot(&snap
, mods
);
1921 git_config_free(mods
);
1927 static git_config_backend
*open_gitmodules(
1928 git_repository
*repo
,
1931 const char *workdir
= git_repository_workdir(repo
);
1932 git_buf path
= GIT_BUF_INIT
;
1933 git_config_backend
*mods
= NULL
;
1935 if (workdir
!= NULL
) {
1936 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1939 if (okay_to_create
|| git_path_isfile(path
.ptr
)) {
1940 /* git_config_file__ondisk should only fail if OOM */
1941 if (git_config_file__ondisk(&mods
, path
.ptr
) < 0)
1943 /* open should only fail here if the file is malformed */
1944 else if (git_config_file_open(mods
, GIT_CONFIG_LEVEL_LOCAL
) < 0) {
1945 git_config_file_free(mods
);
1951 git_buf_free(&path
);
1956 /* Lookup name of remote of the local tracking branch HEAD points to */
1957 static int lookup_head_remote_key(git_buf
*remote_name
, git_repository
*repo
)
1960 git_reference
*head
= NULL
;
1961 git_buf upstream_name
= GIT_BUF_INIT
;
1963 /* lookup and dereference HEAD */
1964 if ((error
= git_repository_head(&head
, repo
)) < 0)
1968 * If head does not refer to a branch, then return
1969 * GIT_ENOTFOUND to indicate that we could not find
1970 * a remote key for the local tracking branch HEAD points to.
1972 if (!git_reference_is_branch(head
)) {
1973 giterr_set(GITERR_INVALID
,
1974 "HEAD does not refer to a branch.");
1975 error
= GIT_ENOTFOUND
;
1979 /* lookup remote tracking branch of HEAD */
1980 if ((error
= git_branch_upstream_name(
1983 git_reference_name(head
))) < 0)
1986 /* lookup remote of remote tracking branch */
1987 if ((error
= git_branch_remote_name(remote_name
, repo
, upstream_name
.ptr
)) < 0)
1991 git_buf_free(&upstream_name
);
1992 git_reference_free(head
);
1997 /* Lookup the remote of the local tracking branch HEAD points to */
1998 static int lookup_head_remote(git_remote
**remote
, git_repository
*repo
)
2001 git_buf remote_name
= GIT_BUF_INIT
;
2003 /* lookup remote of remote tracking branch name */
2004 if (!(error
= lookup_head_remote_key(&remote_name
, repo
)))
2005 error
= git_remote_lookup(remote
, repo
, remote_name
.ptr
);
2007 git_buf_free(&remote_name
);
2012 /* Lookup remote, either from HEAD or fall back on origin */
2013 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
)
2015 int error
= lookup_head_remote(remote
, repo
);
2017 /* if that failed, use 'origin' instead */
2018 if (error
== GIT_ENOTFOUND
)
2019 error
= git_remote_lookup(remote
, repo
, "origin");
2021 if (error
== GIT_ENOTFOUND
)
2024 "cannot get default remote for submodule - no local tracking "
2025 "branch for HEAD and origin does not exist");
2030 static int get_url_base(git_buf
*url
, git_repository
*repo
)
2033 git_remote
*remote
= NULL
;
2035 if (!(error
= lookup_default_remote(&remote
, repo
))) {
2036 error
= git_buf_sets(url
, git_remote_url(remote
));
2037 git_remote_free(remote
);
2039 else if (error
== GIT_ENOTFOUND
) {
2040 /* if repository does not have a default remote, use workdir instead */
2042 error
= git_buf_sets(url
, git_repository_workdir(repo
));
2048 static void submodule_get_index_status(unsigned int *status
, git_submodule
*sm
)
2050 const git_oid
*head_oid
= git_submodule_head_id(sm
);
2051 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2053 *status
= *status
& ~GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
2057 *status
|= GIT_SUBMODULE_STATUS_INDEX_ADDED
;
2059 else if (!index_oid
)
2060 *status
|= GIT_SUBMODULE_STATUS_INDEX_DELETED
;
2061 else if (!git_oid_equal(head_oid
, index_oid
))
2062 *status
|= GIT_SUBMODULE_STATUS_INDEX_MODIFIED
;
2066 static void submodule_get_wd_status(
2067 unsigned int *status
,
2069 git_repository
*sm_repo
,
2070 git_submodule_ignore_t ign
)
2072 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2073 const git_oid
*wd_oid
=
2074 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) ? &sm
->wd_oid
: NULL
;
2075 git_tree
*sm_head
= NULL
;
2076 git_index
*index
= NULL
;
2077 git_diff_options opt
= GIT_DIFF_OPTIONS_INIT
;
2080 *status
= *status
& ~GIT_SUBMODULE_STATUS__WD_FLAGS
;
2084 *status
|= GIT_SUBMODULE_STATUS_WD_ADDED
;
2087 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_SCANNED
) != 0 &&
2088 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) == 0)
2089 *status
|= GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
;
2091 *status
|= GIT_SUBMODULE_STATUS_WD_DELETED
;
2093 else if (!git_oid_equal(index_oid
, wd_oid
))
2094 *status
|= GIT_SUBMODULE_STATUS_WD_MODIFIED
;
2096 /* if we have no repo, then we're done */
2100 /* the diffs below could be optimized with an early termination
2101 * option to the git_diff functions, but for now this is sufficient
2102 * (and certainly no worse that what core git does).
2105 if (ign
== GIT_SUBMODULE_IGNORE_NONE
)
2106 opt
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
2108 (void)git_repository_index__weakptr(&index
, sm_repo
);
2110 /* if we don't have an unborn head, check diff with index */
2111 if (git_repository_head_tree(&sm_head
, sm_repo
) < 0)
2114 /* perform head to index diff on submodule */
2115 if (git_diff_tree_to_index(&diff
, sm_repo
, sm_head
, index
, &opt
) < 0)
2118 if (git_diff_num_deltas(diff
) > 0)
2119 *status
|= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
2120 git_diff_free(diff
);
2124 git_tree_free(sm_head
);
2127 /* perform index-to-workdir diff on submodule */
2128 if (git_diff_index_to_workdir(&diff
, sm_repo
, index
, &opt
) < 0)
2132 git_diff_num_deltas_of_type(diff
, GIT_DELTA_UNTRACKED
);
2135 *status
|= GIT_SUBMODULE_STATUS_WD_UNTRACKED
;
2137 if (git_diff_num_deltas(diff
) != untracked
)
2138 *status
|= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
;
2140 git_diff_free(diff
);