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 submodule_load_each(const git_config_entry
*entry
, void *payload
);
97 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
);
98 static int submodule_load_from_wd_lite(git_submodule
*);
99 static void submodule_get_index_status(unsigned int *, git_submodule
*);
100 static void submodule_get_wd_status(unsigned int *, git_submodule
*, git_repository
*, git_submodule_ignore_t
);
101 static void submodule_update_from_index_entry(git_submodule
*sm
, const git_index_entry
*ie
);
102 static void submodule_update_from_head_data(git_submodule
*sm
, mode_t mode
, const git_oid
*id
);
104 static int submodule_cmp(const void *a
, const void *b
)
106 return strcmp(((git_submodule
*)a
)->name
, ((git_submodule
*)b
)->name
);
109 static int submodule_config_key_trunc_puts(git_buf
*key
, const char *suffix
)
111 ssize_t idx
= git_buf_rfind(key
, '.');
112 git_buf_truncate(key
, (size_t)(idx
+ 1));
113 return git_buf_puts(key
, suffix
);
120 static void submodule_set_lookup_error(int error
, const char *name
)
125 giterr_set(GITERR_SUBMODULE
, (error
== GIT_ENOTFOUND
) ?
126 "No submodule named '%s'" :
127 "Submodule '%s' has not been added yet", name
);
135 static int find_by_path(const git_config_entry
*entry
, void *payload
)
137 fbp_data
*data
= payload
;
139 if (!strcmp(entry
->value
, data
->path
)) {
140 const char *fdot
, *ldot
;
141 fdot
= strchr(entry
->name
, '.');
142 ldot
= strrchr(entry
->name
, '.');
143 data
->name
= git__strndup(fdot
+ 1, ldot
- fdot
- 1);
144 GITERR_CHECK_ALLOC(data
->name
);
151 * Find out the name of a submodule from its path
153 static int name_from_path(git_buf
*out
, git_config
*cfg
, const char *path
)
155 const char *key
= "submodule\\..*\\.path";
156 git_config_iterator
*iter
;
157 git_config_entry
*entry
;
160 if ((error
= git_config_iterator_glob_new(&iter
, cfg
, key
)) < 0)
163 while ((error
= git_config_next(&entry
, iter
)) == 0) {
164 const char *fdot
, *ldot
;
165 /* TODO: this should maybe be strcasecmp on a case-insensitive fs */
166 if (strcmp(path
, entry
->value
) != 0)
169 fdot
= strchr(entry
->name
, '.');
170 ldot
= strrchr(entry
->name
, '.');
173 git_buf_put(out
, fdot
+ 1, ldot
- fdot
- 1);
177 if (error
== GIT_ITEROVER
) {
178 giterr_set(GITERR_SUBMODULE
, "could not find a submodule name for '%s'", path
);
179 error
= GIT_ENOTFOUND
;
183 git_config_iterator_free(iter
);
187 int git_submodule_lookup(
188 git_submodule
**out
, /* NULL if user only wants to test existence */
189 git_repository
*repo
,
190 const char *name
) /* trailing slash is allowed */
193 unsigned int location
;
196 assert(repo
&& name
);
198 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
201 if ((error
= git_submodule_reload(sm
, false)) < 0) {
202 git_submodule_free(sm
);
206 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
207 git_submodule_free(sm
);
211 /* If it's not configured or we're looking by path */
212 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
213 git_config_backend
*mods
;
214 const char *pattern
= "submodule\\..*\\.path";
215 git_buf path
= GIT_BUF_INIT
;
216 fbp_data data
= { NULL
, NULL
};
218 git_buf_puts(&path
, name
);
219 while (path
.ptr
[path
.size
-1] == '/') {
220 path
.ptr
[--path
.size
] = '\0';
222 data
.path
= path
.ptr
;
224 mods
= open_gitmodules(repo
, GITMODULES_EXISTING
);
227 error
= git_config_file_foreach_match(mods
, pattern
, find_by_path
, &data
);
229 git_config_file_free(mods
);
232 git_submodule_free(sm
);
239 sm
->name
= data
.name
;
240 sm
->path
= git_buf_detach(&path
);
242 /* Try to load again with the right name */
243 if ((error
= git_submodule_reload(sm
, false)) < 0) {
244 git_submodule_free(sm
);
252 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
253 git_submodule_free(sm
);
257 /* If we still haven't found it, do the WD check */
258 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
259 git_submodule_free(sm
);
260 error
= GIT_ENOTFOUND
;
262 /* If it's not configured, we still check if there's a repo at the path */
263 if (git_repository_workdir(repo
)) {
264 git_buf path
= GIT_BUF_INIT
;
265 if (git_buf_join3(&path
,
266 '/', git_repository_workdir(repo
), name
, DOT_GIT
) < 0)
269 if (git_path_exists(path
.ptr
))
275 submodule_set_lookup_error(error
, name
);
282 git_submodule_free(sm
);
287 static void submodule_free_dup(void *sm
)
289 git_submodule_free(sm
);
292 static int submodule_get_or_create(git_submodule
**out
, git_repository
*repo
, git_strmap
*map
, const char *name
)
296 git_submodule
*sm
= NULL
;
298 pos
= git_strmap_lookup_index(map
, name
);
299 if (git_strmap_valid_index(map
, pos
)) {
300 sm
= git_strmap_value_at(map
, pos
);
304 /* if the submodule doesn't exist yet in the map, create it */
305 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
308 pos
= kh_put(str
, map
, sm
->name
, &error
);
309 /* nobody can beat us to adding it */
312 git_submodule_free(sm
);
316 git_strmap_set_value_at(map
, pos
, sm
);
319 GIT_REFCOUNT_INC(sm
);
324 static int submodules_from_index(git_strmap
*map
, git_index
*idx
, git_config
*cfg
)
328 const git_index_entry
*entry
;
329 git_buf name
= GIT_BUF_INIT
;
331 if ((error
= git_iterator_for_index(&i
, git_index_owner(idx
), idx
, NULL
)) < 0)
334 while (!(error
= git_iterator_advance(&entry
, i
))) {
335 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
338 git_buf_clear(&name
);
339 if (!name_from_path(&name
, cfg
, entry
->path
)) {
340 git_strmap_lookup_index(map
, name
.ptr
);
343 if (git_strmap_valid_index(map
, pos
)) {
344 sm
= git_strmap_value_at(map
, pos
);
346 if (S_ISGITLINK(entry
->mode
))
347 submodule_update_from_index_entry(sm
, entry
);
349 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
350 } else if (S_ISGITLINK(entry
->mode
)) {
351 if (!submodule_get_or_create(&sm
, git_index_owner(idx
), map
, name
.ptr
? name
.ptr
: entry
->path
)) {
352 submodule_update_from_index_entry(sm
, entry
);
353 git_submodule_free(sm
);
358 if (error
== GIT_ITEROVER
)
362 git_iterator_free(i
);
367 static int submodules_from_head(git_strmap
*map
, git_tree
*head
, git_config
*cfg
)
371 const git_index_entry
*entry
;
372 git_buf name
= GIT_BUF_INIT
;
374 if ((error
= git_iterator_for_tree(&i
, head
, NULL
)) < 0)
377 while (!(error
= git_iterator_advance(&entry
, i
))) {
378 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
381 git_buf_clear(&name
);
382 if (!name_from_path(&name
, cfg
, entry
->path
)) {
383 git_strmap_lookup_index(map
, name
.ptr
);
386 if (git_strmap_valid_index(map
, pos
)) {
387 sm
= git_strmap_value_at(map
, pos
);
389 if (S_ISGITLINK(entry
->mode
))
390 submodule_update_from_head_data(sm
, entry
->mode
, &entry
->id
);
392 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
393 } else if (S_ISGITLINK(entry
->mode
)) {
394 if (!submodule_get_or_create(&sm
, git_tree_owner(head
), map
, name
.ptr
? name
.ptr
: entry
->path
)) {
395 submodule_update_from_head_data(
396 sm
, entry
->mode
, &entry
->id
);
397 git_submodule_free(sm
);
402 if (error
== GIT_ITEROVER
)
406 git_iterator_free(i
);
411 /* If have_sm is true, sm is populated, otherwise map an repo are. */
415 git_repository
*repo
;
418 static int all_submodules(git_repository
*repo
, git_strmap
*map
)
421 git_index
*idx
= NULL
;
422 git_tree
*head
= NULL
;
423 const char *wd
= NULL
;
424 git_buf path
= GIT_BUF_INIT
;
426 git_config
*mods
= NULL
;
431 /* get sources that we will need to check */
432 if (git_repository_index(&idx
, repo
) < 0)
434 if (git_repository_head_tree(&head
, repo
) < 0)
437 wd
= git_repository_workdir(repo
);
438 if (wd
&& (error
= git_buf_joinpath(&path
, wd
, GIT_MODULES_FILE
)) < 0)
441 /* clear submodule flags that are to be refreshed */
443 mask
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
444 GIT_SUBMODULE_STATUS__INDEX_FLAGS
|
445 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
|
446 GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
448 mask
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
449 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
450 mask
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
452 mask
|= GIT_SUBMODULE_STATUS_IN_WD
|
453 GIT_SUBMODULE_STATUS__WD_SCANNED
|
454 GIT_SUBMODULE_STATUS__WD_FLAGS
|
455 GIT_SUBMODULE_STATUS__WD_OID_VALID
;
457 /* add submodule information from .gitmodules */
459 lfc_data data
= { 0 };
463 if ((mods
= gitmodules_snapshot(repo
)) == NULL
)
467 if ((error
= git_config_foreach(
468 mods
, submodule_load_each
, &data
)) < 0)
471 /* add back submodule information from index */
473 if ((error
= submodules_from_index(map
, idx
, mods
)) < 0)
476 /* add submodule information from HEAD */
478 if ((error
= submodules_from_head(map
, head
, mods
)) < 0)
481 /* shallow scan submodules in work tree as needed */
482 if (wd
&& mask
!= 0) {
483 git_strmap_foreach_value(map
, sm
, {
484 submodule_load_from_wd_lite(sm
);
489 git_config_free(mods
);
490 /* TODO: if we got an error, mark submodule config as invalid? */
497 int git_submodule_foreach(
498 git_repository
*repo
,
499 git_submodule_cb callback
,
502 git_vector snapshot
= GIT_VECTOR_INIT
;
503 git_strmap
*submodules
;
508 if ((error
= git_strmap_alloc(&submodules
)) < 0)
511 if ((error
= all_submodules(repo
, submodules
)) < 0)
514 if (!(error
= git_vector_init(
515 &snapshot
, kh_size(submodules
), submodule_cmp
))) {
517 git_strmap_foreach_value(submodules
, sm
, {
518 if ((error
= git_vector_insert(&snapshot
, sm
)) < 0)
520 GIT_REFCOUNT_INC(sm
);
527 git_vector_uniq(&snapshot
, submodule_free_dup
);
529 git_vector_foreach(&snapshot
, i
, sm
) {
530 if ((error
= callback(sm
, sm
->name
, payload
)) != 0) {
531 giterr_set_after_callback(error
);
537 git_vector_foreach(&snapshot
, i
, sm
)
538 git_submodule_free(sm
);
539 git_vector_free(&snapshot
);
541 git_strmap_foreach_value(submodules
, sm
, {
542 git_submodule_free(sm
);
544 git_strmap_free(submodules
);
549 static int submodule_repo_init(
550 git_repository
**out
,
551 git_repository
*parent_repo
,
557 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
558 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
559 git_repository
*subrepo
= NULL
;
561 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
565 initopt
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_NO_REINIT
;
566 initopt
.origin_url
= url
;
568 /* init submodule repository and add origin remote as needed */
570 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
571 * gitlink in the sub-repo workdir directory to that repository
573 * Old style: sub-repo goes directly into repo/<name>/.git/
576 error
= git_buf_join3(
577 &repodir
, '/', git_repository_path(parent_repo
), "modules", path
);
581 initopt
.workdir_path
= workdir
.ptr
;
583 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
584 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
586 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
588 error
= git_repository_init_ext(&subrepo
, workdir
.ptr
, &initopt
);
591 git_buf_free(&workdir
);
592 git_buf_free(&repodir
);
599 int git_submodule_add_setup(
601 git_repository
*repo
,
607 git_config_backend
*mods
= NULL
;
608 git_submodule
*sm
= NULL
;
609 git_buf name
= GIT_BUF_INIT
, real_url
= GIT_BUF_INIT
;
610 git_repository
*subrepo
= NULL
;
612 assert(repo
&& url
&& path
);
614 /* see if there is already an entry for this submodule */
616 if (git_submodule_lookup(NULL
, repo
, path
) < 0)
619 giterr_set(GITERR_SUBMODULE
,
620 "Attempt to add submodule '%s' that already exists", path
);
624 /* validate and normalize path */
626 if (git__prefixcmp(path
, git_repository_workdir(repo
)) == 0)
627 path
+= strlen(git_repository_workdir(repo
));
629 if (git_path_root(path
) >= 0) {
630 giterr_set(GITERR_SUBMODULE
, "Submodule path must be a relative path");
635 /* update .gitmodules */
637 if (!(mods
= open_gitmodules(repo
, GITMODULES_CREATE
))) {
638 giterr_set(GITERR_SUBMODULE
,
639 "Adding submodules to a bare repository is not supported");
643 if ((error
= git_buf_printf(&name
, "submodule.%s.path", path
)) < 0 ||
644 (error
= git_config_file_set_string(mods
, name
.ptr
, path
)) < 0)
647 if ((error
= submodule_config_key_trunc_puts(&name
, "url")) < 0 ||
648 (error
= git_config_file_set_string(mods
, name
.ptr
, url
)) < 0)
651 git_buf_clear(&name
);
653 /* init submodule repository and add origin remote as needed */
655 error
= git_buf_joinpath(&name
, git_repository_workdir(repo
), path
);
659 /* if the repo does not already exist, then init a new repo and add it.
660 * Otherwise, just add the existing repo.
662 if (!(git_path_exists(name
.ptr
) &&
663 git_path_contains(&name
, DOT_GIT
))) {
665 /* resolve the actual URL to use */
666 if ((error
= git_submodule_resolve_url(&real_url
, repo
, url
)) < 0)
669 if ((error
= submodule_repo_init(&subrepo
, repo
, path
, real_url
.ptr
, use_gitlink
)) < 0)
673 if ((error
= git_submodule_lookup(&sm
, repo
, path
)) < 0)
676 error
= git_submodule_init(sm
, false);
680 git_submodule_free(sm
);
686 git_config_file_free(mods
);
687 git_repository_free(subrepo
);
688 git_buf_free(&real_url
);
694 int git_submodule_repo_init(
695 git_repository
**out
,
696 const git_submodule
*sm
,
700 git_repository
*sub_repo
= NULL
;
701 const char *configured_url
;
702 git_config
*cfg
= NULL
;
703 git_buf buf
= GIT_BUF_INIT
;
707 /* get the configured remote url of the submodule */
708 if ((error
= git_buf_printf(&buf
, "submodule.%s.url", sm
->name
)) < 0 ||
709 (error
= git_repository_config_snapshot(&cfg
, sm
->repo
)) < 0 ||
710 (error
= git_config_get_string(&configured_url
, cfg
, buf
.ptr
)) < 0 ||
711 (error
= submodule_repo_init(&sub_repo
, sm
->repo
, sm
->path
, configured_url
, use_gitlink
)) < 0)
717 git_config_free(cfg
);
722 int git_submodule_add_finalize(git_submodule
*sm
)
729 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
730 (error
= git_index_add_bypath(index
, GIT_MODULES_FILE
)) < 0)
733 return git_submodule_add_to_index(sm
, true);
736 int git_submodule_add_to_index(git_submodule
*sm
, int write_index
)
739 git_repository
*sm_repo
= NULL
;
741 git_buf path
= GIT_BUF_INIT
;
743 git_index_entry entry
;
748 /* force reload of wd OID by git_submodule_open */
749 sm
->flags
= sm
->flags
& ~GIT_SUBMODULE_STATUS__WD_OID_VALID
;
751 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
752 (error
= git_buf_joinpath(
753 &path
, git_repository_workdir(sm
->repo
), sm
->path
)) < 0 ||
754 (error
= git_submodule_open(&sm_repo
, sm
)) < 0)
757 /* read stat information for submodule working directory */
758 if (p_stat(path
.ptr
, &st
) < 0) {
759 giterr_set(GITERR_SUBMODULE
,
760 "Cannot add submodule without working directory");
765 memset(&entry
, 0, sizeof(entry
));
766 entry
.path
= sm
->path
;
767 git_index_entry__init_from_stat(
768 &entry
, &st
, !(git_index_caps(index
) & GIT_INDEXCAP_NO_FILEMODE
));
770 /* calling git_submodule_open will have set sm->wd_oid if possible */
771 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) == 0) {
772 giterr_set(GITERR_SUBMODULE
,
773 "Cannot add submodule without HEAD to index");
777 git_oid_cpy(&entry
.id
, &sm
->wd_oid
);
779 if ((error
= git_commit_lookup(&head
, sm_repo
, &sm
->wd_oid
)) < 0)
782 entry
.ctime
.seconds
= (int32_t)git_commit_time(head
);
783 entry
.ctime
.nanoseconds
= 0;
784 entry
.mtime
.seconds
= (int32_t)git_commit_time(head
);
785 entry
.mtime
.nanoseconds
= 0;
787 git_commit_free(head
);
790 error
= git_index_add(index
, &entry
);
792 /* write it, if requested */
793 if (!error
&& write_index
) {
794 error
= git_index_write(index
);
797 git_oid_cpy(&sm
->index_oid
, &sm
->wd_oid
);
801 git_repository_free(sm_repo
);
806 const char *git_submodule_update_to_str(git_submodule_update_t update
)
809 for (i
= 0; i
< (int)ARRAY_SIZE(_sm_update_map
); ++i
)
810 if (_sm_update_map
[i
].map_value
== (int)update
)
811 return _sm_update_map
[i
].str_match
;
815 git_repository
*git_submodule_owner(git_submodule
*submodule
)
818 return submodule
->repo
;
821 const char *git_submodule_name(git_submodule
*submodule
)
824 return submodule
->name
;
827 const char *git_submodule_path(git_submodule
*submodule
)
830 return submodule
->path
;
833 const char *git_submodule_url(git_submodule
*submodule
)
836 return submodule
->url
;
839 int git_submodule_resolve_url(git_buf
*out
, git_repository
*repo
, const char *url
)
842 git_buf normalized
= GIT_BUF_INIT
;
844 assert(out
&& repo
&& url
);
846 git_buf_sanitize(out
);
848 /* We do this in all platforms in case someone on Windows created the .gitmodules */
849 if (strchr(url
, '\\')) {
850 if ((error
= git_path_normalize_slashes(&normalized
, url
)) < 0)
853 url
= normalized
.ptr
;
857 if (git_path_is_relative(url
)) {
858 if (!(error
= get_url_base(out
, repo
)))
859 error
= git_path_apply_relative(out
, url
);
860 } else if (strchr(url
, ':') != NULL
|| url
[0] == '/') {
861 error
= git_buf_sets(out
, url
);
863 giterr_set(GITERR_SUBMODULE
, "Invalid format for submodule URL");
867 git_buf_free(&normalized
);
871 static int write_var(git_repository
*repo
, const char *name
, const char *var
, const char *val
)
873 git_buf key
= GIT_BUF_INIT
;
874 git_config_backend
*mods
;
877 mods
= open_gitmodules(repo
, GITMODULES_CREATE
);
881 if ((error
= git_buf_printf(&key
, "submodule.%s.%s", name
, var
)) < 0)
885 error
= git_config_file_set_string(mods
, key
.ptr
, val
);
887 error
= git_config_file_delete(mods
, key
.ptr
);
892 git_config_file_free(mods
);
896 static int write_mapped_var(git_repository
*repo
, const char *name
, git_cvar_map
*maps
, size_t nmaps
, const char *var
, int ival
)
901 if (git_config_lookup_map_enum(&type
, &val
, maps
, nmaps
, ival
) < 0) {
902 giterr_set(GITERR_SUBMODULE
, "invalid value for %s", var
);
906 if (type
== GIT_CVAR_TRUE
)
909 return write_var(repo
, name
, var
, val
);
912 const char *git_submodule_branch(git_submodule
*submodule
)
915 return submodule
->branch
;
918 int git_submodule_set_branch(git_repository
*repo
, const char *name
, const char *branch
)
921 assert(repo
&& name
);
923 return write_var(repo
, name
, "branch", branch
);
926 int git_submodule_set_url(git_repository
*repo
, const char *name
, const char *url
)
928 assert(repo
&& name
&& url
);
930 return write_var(repo
, name
, "url", url
);
933 const git_oid
*git_submodule_index_id(git_submodule
*submodule
)
937 if (submodule
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
938 return &submodule
->index_oid
;
943 const git_oid
*git_submodule_head_id(git_submodule
*submodule
)
947 if (submodule
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
948 return &submodule
->head_oid
;
953 const git_oid
*git_submodule_wd_id(git_submodule
*submodule
)
957 /* load unless we think we have a valid oid */
958 if (!(submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)) {
959 git_repository
*subrepo
;
961 /* calling submodule open grabs the HEAD OID if possible */
962 if (!git_submodule_open_bare(&subrepo
, submodule
))
963 git_repository_free(subrepo
);
968 if (submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)
969 return &submodule
->wd_oid
;
974 git_submodule_ignore_t
git_submodule_ignore(git_submodule
*submodule
)
977 return (submodule
->ignore
< GIT_SUBMODULE_IGNORE_NONE
) ?
978 GIT_SUBMODULE_IGNORE_NONE
: submodule
->ignore
;
981 int git_submodule_set_ignore(git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
983 assert(repo
&& name
);
985 return write_mapped_var(repo
, name
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), "ignore", ignore
);
988 git_submodule_update_t
git_submodule_update_strategy(git_submodule
*submodule
)
991 return (submodule
->update
< GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
992 GIT_SUBMODULE_UPDATE_CHECKOUT
: submodule
->update
;
995 int git_submodule_set_update(git_repository
*repo
, const char *name
, git_submodule_update_t update
)
997 assert(repo
&& name
);
999 return write_mapped_var(repo
, name
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), "update", update
);
1002 git_submodule_recurse_t
git_submodule_fetch_recurse_submodules(
1003 git_submodule
*submodule
)
1006 return submodule
->fetch_recurse
;
1009 int git_submodule_set_fetch_recurse_submodules(git_repository
*repo
, const char *name
, git_submodule_recurse_t recurse
)
1011 assert(repo
&& name
);
1013 return write_mapped_var(repo
, name
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), "fetchRecurseSubmodules", recurse
);
1016 static int submodule_repo_create(
1017 git_repository
**out
,
1018 git_repository
*parent_repo
,
1022 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
1023 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
1024 git_repository
*subrepo
= NULL
;
1027 GIT_REPOSITORY_INIT_MKPATH
|
1028 GIT_REPOSITORY_INIT_NO_REINIT
|
1029 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
1030 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
1032 /* Workdir: path to sub-repo working directory */
1033 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
1037 initopt
.workdir_path
= workdir
.ptr
;
1040 * Repodir: path to the sub-repo. sub-repo goes in:
1041 * <repo-dir>/modules/<name>/ with a gitlink in the
1042 * sub-repo workdir directory to that repository.
1044 error
= git_buf_join3(
1045 &repodir
, '/', git_repository_path(parent_repo
), "modules", path
);
1049 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
1052 git_buf_free(&workdir
);
1053 git_buf_free(&repodir
);
1061 * Callback to override sub-repository creation when
1062 * cloning a sub-repository.
1064 static int git_submodule_update_repo_init_cb(
1065 git_repository
**out
,
1076 return submodule_repo_create(out
, sm
->repo
, path
);
1079 int git_submodule_update_init_options(git_submodule_update_options
*opts
, unsigned int version
)
1081 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1082 opts
, version
, git_submodule_update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_INIT
);
1086 int git_submodule_update(git_submodule
*sm
, int init
, git_submodule_update_options
*_update_options
)
1089 unsigned int submodule_status
;
1090 git_config
*config
= NULL
;
1091 const char *submodule_url
;
1092 git_repository
*sub_repo
= NULL
;
1093 git_remote
*remote
= NULL
;
1094 git_object
*target_commit
= NULL
;
1095 git_buf buf
= GIT_BUF_INIT
;
1096 git_submodule_update_options update_options
= GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
1097 git_clone_options clone_options
= GIT_CLONE_OPTIONS_INIT
;
1101 if (_update_options
)
1102 memcpy(&update_options
, _update_options
, sizeof(git_submodule_update_options
));
1104 GITERR_CHECK_VERSION(&update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
1106 /* Copy over the remote callbacks */
1107 memcpy(&clone_options
.fetch_opts
, &update_options
.fetch_opts
, sizeof(git_fetch_options
));
1109 /* Get the status of the submodule to determine if it is already initialized */
1110 if ((error
= git_submodule_status(&submodule_status
, sm
->repo
, sm
->name
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
)) < 0)
1114 * If submodule work dir is not already initialized, check to see
1115 * what we need to do (initialize, clone, return error...)
1117 if (submodule_status
& GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
) {
1119 * Work dir is not initialized, check to see if the submodule
1120 * info has been copied into .git/config
1122 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1123 (error
= git_buf_printf(&buf
, "submodule.%s.url", git_submodule_name(sm
))) < 0)
1126 if ((error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0) {
1128 * If the error is not "not found" or if it is "not found" and we are not
1129 * initializing the submodule, then return error.
1131 if (error
!= GIT_ENOTFOUND
)
1134 if (error
== GIT_ENOTFOUND
&& !init
) {
1135 giterr_set(GITERR_SUBMODULE
, "Submodule is not initialized.");
1140 /* The submodule has not been initialized yet - initialize it now.*/
1141 if ((error
= git_submodule_init(sm
, 0)) < 0)
1144 git_config_free(config
);
1147 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1148 (error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0)
1152 /** submodule is initialized - now clone it **/
1153 /* override repo creation */
1154 clone_options
.repository_cb
= git_submodule_update_repo_init_cb
;
1155 clone_options
.repository_cb_payload
= sm
;
1158 * Do not perform checkout as part of clone, instead we
1159 * will checkout the specific commit manually.
1161 clone_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
1162 update_options
.checkout_opts
.checkout_strategy
= update_options
.clone_checkout_strategy
;
1164 if ((error
= git_clone(&sub_repo
, submodule_url
, sm
->path
, &clone_options
)) < 0 ||
1165 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0 ||
1166 (error
= git_checkout_head(sub_repo
, &update_options
.checkout_opts
)) != 0)
1170 * Work dir is initialized - look up the commit in the parent repository's index,
1171 * update the workdir contents of the subrepository, and set the subrepository's
1172 * head to the new commit.
1174 if ((error
= git_submodule_open(&sub_repo
, sm
)) < 0 ||
1175 (error
= git_object_lookup(&target_commit
, sub_repo
, git_submodule_index_id(sm
), GIT_OBJ_COMMIT
)) < 0 ||
1176 (error
= git_checkout_tree(sub_repo
, target_commit
, &update_options
.checkout_opts
)) != 0 ||
1177 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0)
1180 /* Invalidate the wd flags as the workdir has been updated. */
1181 sm
->flags
= sm
->flags
&
1182 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1183 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1184 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1189 git_config_free(config
);
1190 git_object_free(target_commit
);
1191 git_remote_free(remote
);
1192 git_repository_free(sub_repo
);
1197 int git_submodule_init(git_submodule
*sm
, int overwrite
)
1201 git_buf key
= GIT_BUF_INIT
, effective_submodule_url
= GIT_BUF_INIT
;
1202 git_config
*cfg
= NULL
;
1205 giterr_set(GITERR_SUBMODULE
,
1206 "No URL configured for submodule '%s'", sm
->name
);
1210 if ((error
= git_repository_config(&cfg
, sm
->repo
)) < 0)
1213 /* write "submodule.NAME.url" */
1215 if ((error
= git_submodule_resolve_url(&effective_submodule_url
, sm
->repo
, sm
->url
)) < 0 ||
1216 (error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)) < 0 ||
1217 (error
= git_config__update_entry(
1218 cfg
, key
.ptr
, effective_submodule_url
.ptr
, overwrite
!= 0, false)) < 0)
1221 /* write "submodule.NAME.update" if not default */
1223 val
= (sm
->update
== GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1224 NULL
: git_submodule_update_to_str(sm
->update
);
1226 if ((error
= git_buf_printf(&key
, "submodule.%s.update", sm
->name
)) < 0 ||
1227 (error
= git_config__update_entry(
1228 cfg
, key
.ptr
, val
, overwrite
!= 0, false)) < 0)
1234 git_config_free(cfg
);
1236 git_buf_free(&effective_submodule_url
);
1241 int git_submodule_sync(git_submodule
*sm
)
1244 git_config
*cfg
= NULL
;
1245 git_buf key
= GIT_BUF_INIT
;
1246 git_repository
*smrepo
= NULL
;
1249 giterr_set(GITERR_SUBMODULE
,
1250 "No URL configured for submodule '%s'", sm
->name
);
1254 /* copy URL over to config only if it already exists */
1256 if (!(error
= git_repository_config__weakptr(&cfg
, sm
->repo
)) &&
1257 !(error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)))
1258 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, true);
1260 /* if submodule exists in the working directory, update remote url */
1263 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) != 0 &&
1264 !(error
= git_submodule_open(&smrepo
, sm
)))
1266 git_buf remote_name
= GIT_BUF_INIT
;
1268 if ((error
= git_repository_config__weakptr(&cfg
, smrepo
)) < 0)
1269 /* return error from reading submodule config */;
1270 else if ((error
= lookup_head_remote_key(&remote_name
, smrepo
)) < 0) {
1272 error
= git_buf_sets(&key
, "remote.origin.url");
1274 error
= git_buf_join3(
1275 &key
, '.', "remote", remote_name
.ptr
, "url");
1276 git_buf_free(&remote_name
);
1280 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, false);
1282 git_repository_free(smrepo
);
1290 static int git_submodule__open(
1291 git_repository
**subrepo
, git_submodule
*sm
, bool bare
)
1294 git_buf path
= GIT_BUF_INIT
;
1295 unsigned int flags
= GIT_REPOSITORY_OPEN_NO_SEARCH
;
1298 assert(sm
&& subrepo
);
1300 if (git_repository__ensure_not_bare(
1301 sm
->repo
, "open submodule repository") < 0)
1302 return GIT_EBAREREPO
;
1304 wd
= git_repository_workdir(sm
->repo
);
1306 if (git_buf_joinpath(&path
, wd
, sm
->path
) < 0 ||
1307 git_buf_joinpath(&path
, path
.ptr
, DOT_GIT
) < 0)
1310 sm
->flags
= sm
->flags
&
1311 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1312 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1313 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1316 flags
|= GIT_REPOSITORY_OPEN_BARE
;
1318 error
= git_repository_open_ext(subrepo
, path
.ptr
, flags
, wd
);
1320 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1322 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
|
1323 GIT_SUBMODULE_STATUS__WD_SCANNED
;
1325 if (!git_reference_name_to_id(&sm
->wd_oid
, *subrepo
, GIT_HEAD_FILE
))
1326 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_OID_VALID
;
1329 } else if (git_path_exists(path
.ptr
)) {
1330 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
|
1331 GIT_SUBMODULE_STATUS_IN_WD
;
1333 git_buf_rtruncate_at_char(&path
, '/'); /* remove "/.git" */
1335 if (git_path_isdir(path
.ptr
))
1336 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1339 git_buf_free(&path
);
1344 int git_submodule_open_bare(git_repository
**subrepo
, git_submodule
*sm
)
1346 return git_submodule__open(subrepo
, sm
, true);
1349 int git_submodule_open(git_repository
**subrepo
, git_submodule
*sm
)
1351 return git_submodule__open(subrepo
, sm
, false);
1354 static void submodule_update_from_index_entry(
1355 git_submodule
*sm
, const git_index_entry
*ie
)
1357 bool already_found
= (sm
->flags
& GIT_SUBMODULE_STATUS_IN_INDEX
) != 0;
1359 if (!S_ISGITLINK(ie
->mode
)) {
1361 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
1364 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
1366 git_oid_cpy(&sm
->index_oid
, &ie
->id
);
1368 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
1369 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
1373 static int submodule_update_index(git_submodule
*sm
)
1376 const git_index_entry
*ie
;
1378 if (git_repository_index__weakptr(&index
, sm
->repo
) < 0)
1381 sm
->flags
= sm
->flags
&
1382 ~(GIT_SUBMODULE_STATUS_IN_INDEX
|
1383 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
1385 if (!(ie
= git_index_get_bypath(index
, sm
->path
, 0)))
1388 submodule_update_from_index_entry(sm
, ie
);
1393 static void submodule_update_from_head_data(
1394 git_submodule
*sm
, mode_t mode
, const git_oid
*id
)
1396 if (!S_ISGITLINK(mode
))
1397 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
1399 git_oid_cpy(&sm
->head_oid
, id
);
1401 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
1402 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
1406 static int submodule_update_head(git_submodule
*submodule
)
1408 git_tree
*head
= NULL
;
1409 git_tree_entry
*te
= NULL
;
1411 submodule
->flags
= submodule
->flags
&
1412 ~(GIT_SUBMODULE_STATUS_IN_HEAD
|
1413 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
1415 /* if we can't look up file in current head, then done */
1416 if (git_repository_head_tree(&head
, submodule
->repo
) < 0 ||
1417 git_tree_entry_bypath(&te
, head
, submodule
->path
) < 0)
1420 submodule_update_from_head_data(submodule
, te
->attr
, &te
->oid
);
1422 git_tree_entry_free(te
);
1423 git_tree_free(head
);
1427 int git_submodule_reload(git_submodule
*sm
, int force
)
1436 if (!git_repository_is_bare(sm
->repo
)) {
1437 /* refresh config data */
1438 mods
= gitmodules_snapshot(sm
->repo
);
1440 error
= submodule_read_config(sm
, mods
);
1441 git_config_free(mods
);
1447 /* refresh wd data */
1449 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1450 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1451 GIT_SUBMODULE_STATUS__WD_FLAGS
);
1453 error
= submodule_load_from_wd_lite(sm
);
1456 if (error
== 0 && (error
= submodule_update_index(sm
)) == 0)
1457 error
= submodule_update_head(sm
);
1462 static void submodule_copy_oid_maybe(
1463 git_oid
*tgt
, const git_oid
*src
, bool valid
)
1467 memcpy(tgt
, src
, sizeof(*tgt
));
1469 memset(tgt
, 0, sizeof(*tgt
));
1473 int git_submodule__status(
1474 unsigned int *out_status
,
1475 git_oid
*out_head_id
,
1476 git_oid
*out_index_id
,
1479 git_submodule_ignore_t ign
)
1481 unsigned int status
;
1482 git_repository
*smrepo
= NULL
;
1484 if (ign
== GIT_SUBMODULE_IGNORE_UNSPECIFIED
)
1487 /* only return location info if ignore == all */
1488 if (ign
== GIT_SUBMODULE_IGNORE_ALL
) {
1489 *out_status
= (sm
->flags
& GIT_SUBMODULE_STATUS__IN_FLAGS
);
1493 /* refresh the index OID */
1494 if (submodule_update_index(sm
) < 0)
1497 /* refresh the HEAD OID */
1498 if (submodule_update_head(sm
) < 0)
1501 /* for ignore == dirty, don't scan the working directory */
1502 if (ign
== GIT_SUBMODULE_IGNORE_DIRTY
) {
1503 /* git_submodule_open_bare will load WD OID data */
1504 if (git_submodule_open_bare(&smrepo
, sm
) < 0)
1507 git_repository_free(smrepo
);
1509 } else if (git_submodule_open(&smrepo
, sm
) < 0) {
1514 status
= GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm
->flags
);
1516 submodule_get_index_status(&status
, sm
);
1517 submodule_get_wd_status(&status
, sm
, smrepo
, ign
);
1519 git_repository_free(smrepo
);
1521 *out_status
= status
;
1523 submodule_copy_oid_maybe(out_head_id
, &sm
->head_oid
,
1524 (sm
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
) != 0);
1525 submodule_copy_oid_maybe(out_index_id
, &sm
->index_oid
,
1526 (sm
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
) != 0);
1527 submodule_copy_oid_maybe(out_wd_id
, &sm
->wd_oid
,
1528 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) != 0);
1533 int git_submodule_status(unsigned int *status
, git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1538 assert(status
&& repo
&& name
);
1540 if ((error
= git_submodule_lookup(&sm
, repo
, name
)) < 0)
1543 error
= git_submodule__status(status
, NULL
, NULL
, NULL
, sm
, ignore
);
1544 git_submodule_free(sm
);
1549 int git_submodule_location(unsigned int *location
, git_submodule
*sm
)
1551 assert(location
&& sm
);
1553 return git_submodule__status(
1554 location
, NULL
, NULL
, NULL
, sm
, GIT_SUBMODULE_IGNORE_ALL
);
1559 * INTERNAL FUNCTIONS
1562 static int submodule_alloc(
1563 git_submodule
**out
, git_repository
*repo
, const char *name
)
1568 if (!name
|| !(namelen
= strlen(name
))) {
1569 giterr_set(GITERR_SUBMODULE
, "Invalid submodule name");
1573 sm
= git__calloc(1, sizeof(git_submodule
));
1574 GITERR_CHECK_ALLOC(sm
);
1576 sm
->name
= sm
->path
= git__strdup(name
);
1582 GIT_REFCOUNT_INC(sm
);
1583 sm
->ignore
= sm
->ignore_default
= GIT_SUBMODULE_IGNORE_NONE
;
1584 sm
->update
= sm
->update_default
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1585 sm
->fetch_recurse
= sm
->fetch_recurse_default
= GIT_SUBMODULE_RECURSE_NO
;
1593 static void submodule_release(git_submodule
*sm
)
1602 if (sm
->path
!= sm
->name
)
1603 git__free(sm
->path
);
1604 git__free(sm
->name
);
1606 git__free(sm
->branch
);
1607 git__memzero(sm
, sizeof(*sm
));
1611 void git_submodule_free(git_submodule
*sm
)
1615 GIT_REFCOUNT_DEC(sm
, submodule_release
);
1618 static int submodule_config_error(const char *property
, const char *value
)
1620 giterr_set(GITERR_INVALID
,
1621 "Invalid value for submodule '%s' property: '%s'", property
, value
);
1625 int git_submodule_parse_ignore(git_submodule_ignore_t
*out
, const char *value
)
1629 if (git_config_lookup_map_value(
1630 &val
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), value
) < 0) {
1631 *out
= GIT_SUBMODULE_IGNORE_NONE
;
1632 return submodule_config_error("ignore", value
);
1635 *out
= (git_submodule_ignore_t
)val
;
1639 int git_submodule_parse_update(git_submodule_update_t
*out
, const char *value
)
1643 if (git_config_lookup_map_value(
1644 &val
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), value
) < 0) {
1645 *out
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1646 return submodule_config_error("update", value
);
1649 *out
= (git_submodule_update_t
)val
;
1653 int git_submodule_parse_recurse(git_submodule_recurse_t
*out
, const char *value
)
1657 if (git_config_lookup_map_value(
1658 &val
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), value
) < 0) {
1659 *out
= GIT_SUBMODULE_RECURSE_YES
;
1660 return submodule_config_error("recurse", value
);
1663 *out
= (git_submodule_recurse_t
)val
;
1667 static int get_value(const char **out
, git_config
*cfg
, git_buf
*buf
, const char *name
, const char *field
)
1673 if ((error
= git_buf_printf(buf
, "submodule.%s.%s", name
, field
)) < 0 ||
1674 (error
= git_config_get_string(out
, cfg
, buf
->ptr
)) < 0)
1680 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
)
1682 git_buf key
= GIT_BUF_INIT
;
1684 int error
, in_config
= 0;
1687 * TODO: Look up path in index and if it is present but not a GITLINK
1688 * then this should be deleted (at least to match git's behavior)
1691 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "path")) == 0) {
1694 * TODO: if case insensitive filesystem, then the following strcmp
1695 * should be strcasecmp
1697 if (strcmp(sm
->name
, value
) != 0) {
1698 if (sm
->path
!= sm
->name
)
1699 git__free(sm
->path
);
1700 sm
->path
= git__strdup(value
);
1701 GITERR_CHECK_ALLOC(sm
->path
);
1703 } else if (error
!= GIT_ENOTFOUND
) {
1707 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "url")) == 0) {
1709 sm
->url
= git__strdup(value
);
1710 GITERR_CHECK_ALLOC(sm
->url
);
1711 } else if (error
!= GIT_ENOTFOUND
) {
1715 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "branch")) == 0) {
1717 sm
->branch
= git__strdup(value
);
1718 GITERR_CHECK_ALLOC(sm
->branch
);
1719 } else if (error
!= GIT_ENOTFOUND
) {
1723 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "update")) == 0) {
1725 if ((error
= git_submodule_parse_update(&sm
->update
, value
)) < 0)
1727 sm
->update_default
= sm
->update
;
1728 } else if (error
!= GIT_ENOTFOUND
) {
1732 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "fetchRecurseSubmodules")) == 0) {
1734 if ((error
= git_submodule_parse_recurse(&sm
->fetch_recurse
, value
)) < 0)
1736 sm
->fetch_recurse_default
= sm
->fetch_recurse
;
1737 } else if (error
!= GIT_ENOTFOUND
) {
1741 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "ignore")) == 0) {
1743 if ((error
= git_submodule_parse_ignore(&sm
->ignore
, value
)) < 0)
1745 sm
->ignore_default
= sm
->ignore
;
1746 } else if (error
!= GIT_ENOTFOUND
) {
1751 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
1760 static int submodule_load_each(const git_config_entry
*entry
, void *payload
)
1762 lfc_data
*data
= payload
;
1763 const char *namestart
, *property
;
1764 git_strmap_iter pos
;
1765 git_strmap
*map
= data
->map
;
1766 git_buf name
= GIT_BUF_INIT
;
1770 if (git__prefixcmp(entry
->name
, "submodule.") != 0)
1773 namestart
= entry
->name
+ strlen("submodule.");
1774 property
= strrchr(namestart
, '.');
1776 if (!property
|| (property
== namestart
))
1781 if ((error
= git_buf_set(&name
, namestart
, property
- namestart
-1)) < 0)
1785 * Now that we have the submodule's name, we can use that to
1786 * figure out whether it's in the map. If it's not, we create
1787 * a new submodule, load the config and insert it. If it's
1788 * already inserted, we've already loaded it, so we skip.
1790 pos
= git_strmap_lookup_index(map
, name
.ptr
);
1791 if (git_strmap_valid_index(map
, pos
)) {
1796 if ((error
= submodule_alloc(&sm
, data
->repo
, name
.ptr
)) < 0)
1799 if ((error
= submodule_read_config(sm
, data
->mods
)) < 0) {
1800 git_submodule_free(sm
);
1804 git_strmap_insert(map
, sm
->name
, sm
, error
);
1812 git_buf_free(&name
);
1816 static int submodule_load_from_wd_lite(git_submodule
*sm
)
1818 git_buf path
= GIT_BUF_INIT
;
1820 if (git_buf_joinpath(&path
, git_repository_workdir(sm
->repo
), sm
->path
) < 0)
1823 if (git_path_isdir(path
.ptr
))
1824 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1826 if (git_path_contains(&path
, DOT_GIT
))
1827 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
;
1829 git_buf_free(&path
);
1834 * Returns a snapshot of $WORK_TREE/.gitmodules.
1836 * We ignore any errors and just pretend the file isn't there.
1838 static git_config
*gitmodules_snapshot(git_repository
*repo
)
1840 const char *workdir
= git_repository_workdir(repo
);
1841 git_config
*mods
= NULL
, *snap
= NULL
;
1842 git_buf path
= GIT_BUF_INIT
;
1844 if (workdir
!= NULL
) {
1845 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1848 if (git_config_open_ondisk(&mods
, path
.ptr
) < 0)
1852 git_buf_free(&path
);
1855 git_config_snapshot(&snap
, mods
);
1856 git_config_free(mods
);
1862 static git_config_backend
*open_gitmodules(
1863 git_repository
*repo
,
1866 const char *workdir
= git_repository_workdir(repo
);
1867 git_buf path
= GIT_BUF_INIT
;
1868 git_config_backend
*mods
= NULL
;
1870 if (workdir
!= NULL
) {
1871 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1874 if (okay_to_create
|| git_path_isfile(path
.ptr
)) {
1875 /* git_config_file__ondisk should only fail if OOM */
1876 if (git_config_file__ondisk(&mods
, path
.ptr
) < 0)
1878 /* open should only fail here if the file is malformed */
1879 else if (git_config_file_open(mods
, GIT_CONFIG_LEVEL_LOCAL
) < 0) {
1880 git_config_file_free(mods
);
1886 git_buf_free(&path
);
1891 /* Lookup name of remote of the local tracking branch HEAD points to */
1892 static int lookup_head_remote_key(git_buf
*remote_name
, git_repository
*repo
)
1895 git_reference
*head
= NULL
;
1896 git_buf upstream_name
= GIT_BUF_INIT
;
1898 /* lookup and dereference HEAD */
1899 if ((error
= git_repository_head(&head
, repo
)) < 0)
1903 * If head does not refer to a branch, then return
1904 * GIT_ENOTFOUND to indicate that we could not find
1905 * a remote key for the local tracking branch HEAD points to.
1907 if (!git_reference_is_branch(head
)) {
1908 giterr_set(GITERR_INVALID
,
1909 "HEAD does not refer to a branch.");
1910 error
= GIT_ENOTFOUND
;
1914 /* lookup remote tracking branch of HEAD */
1915 if ((error
= git_branch_upstream_name(
1918 git_reference_name(head
))) < 0)
1921 /* lookup remote of remote tracking branch */
1922 if ((error
= git_branch_remote_name(remote_name
, repo
, upstream_name
.ptr
)) < 0)
1926 git_buf_free(&upstream_name
);
1927 git_reference_free(head
);
1932 /* Lookup the remote of the local tracking branch HEAD points to */
1933 static int lookup_head_remote(git_remote
**remote
, git_repository
*repo
)
1936 git_buf remote_name
= GIT_BUF_INIT
;
1938 /* lookup remote of remote tracking branch name */
1939 if (!(error
= lookup_head_remote_key(&remote_name
, repo
)))
1940 error
= git_remote_lookup(remote
, repo
, remote_name
.ptr
);
1942 git_buf_free(&remote_name
);
1947 /* Lookup remote, either from HEAD or fall back on origin */
1948 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
)
1950 int error
= lookup_head_remote(remote
, repo
);
1952 /* if that failed, use 'origin' instead */
1953 if (error
== GIT_ENOTFOUND
)
1954 error
= git_remote_lookup(remote
, repo
, "origin");
1956 if (error
== GIT_ENOTFOUND
)
1959 "Cannot get default remote for submodule - no local tracking "
1960 "branch for HEAD and origin does not exist");
1965 static int get_url_base(git_buf
*url
, git_repository
*repo
)
1968 git_remote
*remote
= NULL
;
1970 if (!(error
= lookup_default_remote(&remote
, repo
))) {
1971 error
= git_buf_sets(url
, git_remote_url(remote
));
1972 git_remote_free(remote
);
1974 else if (error
== GIT_ENOTFOUND
) {
1975 /* if repository does not have a default remote, use workdir instead */
1977 error
= git_buf_sets(url
, git_repository_workdir(repo
));
1983 static void submodule_get_index_status(unsigned int *status
, git_submodule
*sm
)
1985 const git_oid
*head_oid
= git_submodule_head_id(sm
);
1986 const git_oid
*index_oid
= git_submodule_index_id(sm
);
1988 *status
= *status
& ~GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
1992 *status
|= GIT_SUBMODULE_STATUS_INDEX_ADDED
;
1994 else if (!index_oid
)
1995 *status
|= GIT_SUBMODULE_STATUS_INDEX_DELETED
;
1996 else if (!git_oid_equal(head_oid
, index_oid
))
1997 *status
|= GIT_SUBMODULE_STATUS_INDEX_MODIFIED
;
2001 static void submodule_get_wd_status(
2002 unsigned int *status
,
2004 git_repository
*sm_repo
,
2005 git_submodule_ignore_t ign
)
2007 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2008 const git_oid
*wd_oid
=
2009 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) ? &sm
->wd_oid
: NULL
;
2010 git_tree
*sm_head
= NULL
;
2011 git_index
*index
= NULL
;
2012 git_diff_options opt
= GIT_DIFF_OPTIONS_INIT
;
2015 *status
= *status
& ~GIT_SUBMODULE_STATUS__WD_FLAGS
;
2019 *status
|= GIT_SUBMODULE_STATUS_WD_ADDED
;
2022 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_SCANNED
) != 0 &&
2023 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) == 0)
2024 *status
|= GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
;
2026 *status
|= GIT_SUBMODULE_STATUS_WD_DELETED
;
2028 else if (!git_oid_equal(index_oid
, wd_oid
))
2029 *status
|= GIT_SUBMODULE_STATUS_WD_MODIFIED
;
2031 /* if we have no repo, then we're done */
2035 /* the diffs below could be optimized with an early termination
2036 * option to the git_diff functions, but for now this is sufficient
2037 * (and certainly no worse that what core git does).
2040 if (ign
== GIT_SUBMODULE_IGNORE_NONE
)
2041 opt
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
2043 (void)git_repository_index__weakptr(&index
, sm_repo
);
2045 /* if we don't have an unborn head, check diff with index */
2046 if (git_repository_head_tree(&sm_head
, sm_repo
) < 0)
2049 /* perform head to index diff on submodule */
2050 if (git_diff_tree_to_index(&diff
, sm_repo
, sm_head
, index
, &opt
) < 0)
2053 if (git_diff_num_deltas(diff
) > 0)
2054 *status
|= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
2055 git_diff_free(diff
);
2059 git_tree_free(sm_head
);
2062 /* perform index-to-workdir diff on submodule */
2063 if (git_diff_index_to_workdir(&diff
, sm_repo
, index
, &opt
) < 0)
2067 git_diff_num_deltas_of_type(diff
, GIT_DELTA_UNTRACKED
);
2070 *status
|= GIT_SUBMODULE_STATUS_WD_UNTRACKED
;
2072 if (git_diff_num_deltas(diff
) != untracked
)
2073 *status
|= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
;
2075 git_diff_free(diff
);