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
== blen
&& strncmp(a
, b
, alen
) == 0);
87 str
, static kh_inline
, const char *, void *, 1,
88 str_hash_no_trailing_slash
, str_equal_no_trailing_slash
)
90 static int submodule_alloc(git_submodule
**out
, git_repository
*repo
, const char *name
);
91 static git_config_backend
*open_gitmodules(git_repository
*repo
, int gitmod
);
92 static git_config
*gitmodules_snapshot(git_repository
*repo
);
93 static int get_url_base(git_buf
*url
, git_repository
*repo
);
94 static int lookup_head_remote_key(git_buf
*remote_key
, git_repository
*repo
);
95 static int submodule_load_each(const git_config_entry
*entry
, void *payload
);
96 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
);
97 static int submodule_load_from_wd_lite(git_submodule
*);
98 static void submodule_get_index_status(unsigned int *, git_submodule
*);
99 static void submodule_get_wd_status(unsigned int *, git_submodule
*, git_repository
*, git_submodule_ignore_t
);
100 static void submodule_update_from_index_entry(git_submodule
*sm
, const git_index_entry
*ie
);
101 static void submodule_update_from_head_data(git_submodule
*sm
, mode_t mode
, const git_oid
*id
);
103 static int submodule_cmp(const void *a
, const void *b
)
105 return strcmp(((git_submodule
*)a
)->name
, ((git_submodule
*)b
)->name
);
108 static int submodule_config_key_trunc_puts(git_buf
*key
, const char *suffix
)
110 ssize_t idx
= git_buf_rfind(key
, '.');
111 git_buf_truncate(key
, (size_t)(idx
+ 1));
112 return git_buf_puts(key
, suffix
);
119 static void submodule_set_lookup_error(int error
, const char *name
)
124 giterr_set(GITERR_SUBMODULE
, (error
== GIT_ENOTFOUND
) ?
125 "No submodule named '%s'" :
126 "Submodule '%s' has not been added yet", name
);
134 static int find_by_path(const git_config_entry
*entry
, void *payload
)
136 fbp_data
*data
= payload
;
138 if (!strcmp(entry
->value
, data
->path
)) {
139 const char *fdot
, *ldot
;
140 fdot
= strchr(entry
->name
, '.');
141 ldot
= strrchr(entry
->name
, '.');
142 data
->name
= git__strndup(fdot
+ 1, ldot
- fdot
- 1);
143 GITERR_CHECK_ALLOC(data
->name
);
150 * Find out the name of a submodule from its path
152 static int name_from_path(git_buf
*out
, git_config
*cfg
, const char *path
)
154 const char *key
= "submodule\\..*\\.path";
155 git_config_iterator
*iter
;
156 git_config_entry
*entry
;
159 if ((error
= git_config_iterator_glob_new(&iter
, cfg
, key
)) < 0)
162 while ((error
= git_config_next(&entry
, iter
)) == 0) {
163 const char *fdot
, *ldot
;
164 /* TODO: this should maybe be strcasecmp on a case-insensitive fs */
165 if (strcmp(path
, entry
->value
) != 0)
168 fdot
= strchr(entry
->name
, '.');
169 ldot
= strrchr(entry
->name
, '.');
172 git_buf_put(out
, fdot
+ 1, ldot
- fdot
- 1);
176 if (error
== GIT_ITEROVER
) {
177 giterr_set(GITERR_SUBMODULE
, "could not find a submodule name for '%s'", path
);
178 error
= GIT_ENOTFOUND
;
182 git_config_iterator_free(iter
);
186 int git_submodule_lookup(
187 git_submodule
**out
, /* NULL if user only wants to test existence */
188 git_repository
*repo
,
189 const char *name
) /* trailing slash is allowed */
192 unsigned int location
;
195 assert(repo
&& name
);
197 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
200 if ((error
= git_submodule_reload(sm
, false)) < 0) {
201 git_submodule_free(sm
);
205 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
206 git_submodule_free(sm
);
210 /* If it's not configured or we're looking by path */
211 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
212 git_config_backend
*mods
;
213 const char *pattern
= "submodule\\..*\\.path";
214 git_buf path
= GIT_BUF_INIT
;
215 fbp_data data
= { NULL
, NULL
};
217 git_buf_puts(&path
, name
);
218 while (path
.ptr
[path
.size
-1] == '/') {
219 path
.ptr
[--path
.size
] = '\0';
221 data
.path
= path
.ptr
;
223 mods
= open_gitmodules(repo
, GITMODULES_EXISTING
);
226 error
= git_config_file_foreach_match(mods
, pattern
, find_by_path
, &data
);
228 git_config_file_free(mods
);
231 git_submodule_free(sm
);
238 sm
->name
= data
.name
;
239 sm
->path
= git_buf_detach(&path
);
241 /* Try to load again with the right name */
242 if ((error
= git_submodule_reload(sm
, false)) < 0) {
243 git_submodule_free(sm
);
251 if ((error
= git_submodule_location(&location
, sm
)) < 0) {
252 git_submodule_free(sm
);
256 /* If we still haven't found it, do the WD check */
257 if (location
== 0 || location
== GIT_SUBMODULE_STATUS_IN_WD
) {
258 git_submodule_free(sm
);
259 error
= GIT_ENOTFOUND
;
261 /* If it's not configured, we still check if there's a repo at the path */
262 if (git_repository_workdir(repo
)) {
263 git_buf path
= GIT_BUF_INIT
;
264 if (git_buf_join3(&path
,
265 '/', git_repository_workdir(repo
), name
, DOT_GIT
) < 0)
268 if (git_path_exists(path
.ptr
))
274 submodule_set_lookup_error(error
, name
);
281 git_submodule_free(sm
);
286 static void submodule_free_dup(void *sm
)
288 git_submodule_free(sm
);
291 static int submodule_get_or_create(git_submodule
**out
, git_repository
*repo
, git_strmap
*map
, const char *name
)
295 git_submodule
*sm
= NULL
;
297 pos
= git_strmap_lookup_index(map
, name
);
298 if (git_strmap_valid_index(map
, pos
)) {
299 sm
= git_strmap_value_at(map
, pos
);
303 /* if the submodule doesn't exist yet in the map, create it */
304 if ((error
= submodule_alloc(&sm
, repo
, name
)) < 0)
307 pos
= kh_put(str
, map
, sm
->name
, &error
);
308 /* nobody can beat us to adding it */
311 git_submodule_free(sm
);
315 git_strmap_set_value_at(map
, pos
, sm
);
318 GIT_REFCOUNT_INC(sm
);
323 static int submodules_from_index(git_strmap
*map
, git_index
*idx
, git_config
*cfg
)
327 const git_index_entry
*entry
;
328 git_buf name
= GIT_BUF_INIT
;
330 if ((error
= git_iterator_for_index(&i
, git_index_owner(idx
), idx
, NULL
)) < 0)
333 while (!(error
= git_iterator_advance(&entry
, i
))) {
334 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
337 git_buf_clear(&name
);
338 if (!name_from_path(&name
, cfg
, entry
->path
)) {
339 git_strmap_lookup_index(map
, name
.ptr
);
342 if (git_strmap_valid_index(map
, pos
)) {
343 sm
= git_strmap_value_at(map
, pos
);
345 if (S_ISGITLINK(entry
->mode
))
346 submodule_update_from_index_entry(sm
, entry
);
348 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
349 } else if (S_ISGITLINK(entry
->mode
)) {
350 if (!submodule_get_or_create(&sm
, git_index_owner(idx
), map
, name
.ptr
? name
.ptr
: entry
->path
)) {
351 submodule_update_from_index_entry(sm
, entry
);
352 git_submodule_free(sm
);
357 if (error
== GIT_ITEROVER
)
361 git_iterator_free(i
);
366 static int submodules_from_head(git_strmap
*map
, git_tree
*head
, git_config
*cfg
)
370 const git_index_entry
*entry
;
371 git_buf name
= GIT_BUF_INIT
;
373 if ((error
= git_iterator_for_tree(&i
, head
, NULL
)) < 0)
376 while (!(error
= git_iterator_advance(&entry
, i
))) {
377 khiter_t pos
= git_strmap_lookup_index(map
, entry
->path
);
380 git_buf_clear(&name
);
381 if (!name_from_path(&name
, cfg
, entry
->path
)) {
382 git_strmap_lookup_index(map
, name
.ptr
);
385 if (git_strmap_valid_index(map
, pos
)) {
386 sm
= git_strmap_value_at(map
, pos
);
388 if (S_ISGITLINK(entry
->mode
))
389 submodule_update_from_head_data(sm
, entry
->mode
, &entry
->id
);
391 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
392 } else if (S_ISGITLINK(entry
->mode
)) {
393 if (!submodule_get_or_create(&sm
, git_tree_owner(head
), map
, name
.ptr
? name
.ptr
: entry
->path
)) {
394 submodule_update_from_head_data(
395 sm
, entry
->mode
, &entry
->id
);
396 git_submodule_free(sm
);
401 if (error
== GIT_ITEROVER
)
405 git_iterator_free(i
);
410 /* If have_sm is true, sm is populated, otherwise map an repo are. */
414 git_repository
*repo
;
417 static int all_submodules(git_repository
*repo
, git_strmap
*map
)
420 git_index
*idx
= NULL
;
421 git_tree
*head
= NULL
;
422 const char *wd
= NULL
;
423 git_buf path
= GIT_BUF_INIT
;
425 git_config
*mods
= NULL
;
430 /* get sources that we will need to check */
431 if (git_repository_index(&idx
, repo
) < 0)
433 if (git_repository_head_tree(&head
, repo
) < 0)
436 wd
= git_repository_workdir(repo
);
437 if (wd
&& (error
= git_buf_joinpath(&path
, wd
, GIT_MODULES_FILE
)) < 0)
440 /* clear submodule flags that are to be refreshed */
442 mask
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
443 GIT_SUBMODULE_STATUS__INDEX_FLAGS
|
444 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
|
445 GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
447 mask
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
448 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
449 mask
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
451 mask
|= GIT_SUBMODULE_STATUS_IN_WD
|
452 GIT_SUBMODULE_STATUS__WD_SCANNED
|
453 GIT_SUBMODULE_STATUS__WD_FLAGS
|
454 GIT_SUBMODULE_STATUS__WD_OID_VALID
;
456 /* add submodule information from .gitmodules */
458 lfc_data data
= { 0 };
462 if ((mods
= gitmodules_snapshot(repo
)) == NULL
)
466 if ((error
= git_config_foreach(
467 mods
, submodule_load_each
, &data
)) < 0)
470 /* add back submodule information from index */
472 if ((error
= submodules_from_index(map
, idx
, mods
)) < 0)
475 /* add submodule information from HEAD */
477 if ((error
= submodules_from_head(map
, head
, mods
)) < 0)
480 /* shallow scan submodules in work tree as needed */
481 if (wd
&& mask
!= 0) {
482 git_strmap_foreach_value(map
, sm
, {
483 submodule_load_from_wd_lite(sm
);
488 git_config_free(mods
);
489 /* TODO: if we got an error, mark submodule config as invalid? */
496 int git_submodule_foreach(
497 git_repository
*repo
,
498 git_submodule_cb callback
,
501 git_vector snapshot
= GIT_VECTOR_INIT
;
502 git_strmap
*submodules
;
507 if ((error
= git_strmap_alloc(&submodules
)) < 0)
510 if ((error
= all_submodules(repo
, submodules
)) < 0)
513 if (!(error
= git_vector_init(
514 &snapshot
, kh_size(submodules
), submodule_cmp
))) {
516 git_strmap_foreach_value(submodules
, sm
, {
517 if ((error
= git_vector_insert(&snapshot
, sm
)) < 0)
519 GIT_REFCOUNT_INC(sm
);
526 git_vector_uniq(&snapshot
, submodule_free_dup
);
528 git_vector_foreach(&snapshot
, i
, sm
) {
529 if ((error
= callback(sm
, sm
->name
, payload
)) != 0) {
530 giterr_set_after_callback(error
);
536 git_vector_foreach(&snapshot
, i
, sm
)
537 git_submodule_free(sm
);
538 git_vector_free(&snapshot
);
540 git_strmap_foreach_value(submodules
, sm
, {
541 git_submodule_free(sm
);
543 git_strmap_free(submodules
);
548 static int submodule_repo_init(
549 git_repository
**out
,
550 git_repository
*parent_repo
,
556 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
557 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
558 git_repository
*subrepo
= NULL
;
560 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
564 initopt
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_NO_REINIT
;
565 initopt
.origin_url
= url
;
567 /* init submodule repository and add origin remote as needed */
569 /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a
570 * gitlink in the sub-repo workdir directory to that repository
572 * Old style: sub-repo goes directly into repo/<name>/.git/
575 error
= git_buf_join3(
576 &repodir
, '/', git_repository_path(parent_repo
), "modules", path
);
580 initopt
.workdir_path
= workdir
.ptr
;
582 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
583 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
585 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
587 error
= git_repository_init_ext(&subrepo
, workdir
.ptr
, &initopt
);
590 git_buf_free(&workdir
);
591 git_buf_free(&repodir
);
598 int git_submodule_add_setup(
600 git_repository
*repo
,
606 git_config_backend
*mods
= NULL
;
607 git_submodule
*sm
= NULL
;
608 git_buf name
= GIT_BUF_INIT
, real_url
= GIT_BUF_INIT
;
609 git_repository
*subrepo
= NULL
;
611 assert(repo
&& url
&& path
);
613 /* see if there is already an entry for this submodule */
615 if (git_submodule_lookup(NULL
, repo
, path
) < 0)
618 giterr_set(GITERR_SUBMODULE
,
619 "Attempt to add submodule '%s' that already exists", path
);
623 /* validate and normalize path */
625 if (git__prefixcmp(path
, git_repository_workdir(repo
)) == 0)
626 path
+= strlen(git_repository_workdir(repo
));
628 if (git_path_root(path
) >= 0) {
629 giterr_set(GITERR_SUBMODULE
, "Submodule path must be a relative path");
634 /* update .gitmodules */
636 if (!(mods
= open_gitmodules(repo
, GITMODULES_CREATE
))) {
637 giterr_set(GITERR_SUBMODULE
,
638 "Adding submodules to a bare repository is not supported");
642 if ((error
= git_buf_printf(&name
, "submodule.%s.path", path
)) < 0 ||
643 (error
= git_config_file_set_string(mods
, name
.ptr
, path
)) < 0)
646 if ((error
= submodule_config_key_trunc_puts(&name
, "url")) < 0 ||
647 (error
= git_config_file_set_string(mods
, name
.ptr
, url
)) < 0)
650 git_buf_clear(&name
);
652 /* init submodule repository and add origin remote as needed */
654 error
= git_buf_joinpath(&name
, git_repository_workdir(repo
), path
);
658 /* if the repo does not already exist, then init a new repo and add it.
659 * Otherwise, just add the existing repo.
661 if (!(git_path_exists(name
.ptr
) &&
662 git_path_contains(&name
, DOT_GIT
))) {
664 /* resolve the actual URL to use */
665 if ((error
= git_submodule_resolve_url(&real_url
, repo
, url
)) < 0)
668 if ((error
= submodule_repo_init(&subrepo
, repo
, path
, real_url
.ptr
, use_gitlink
)) < 0)
672 if ((error
= git_submodule_lookup(&sm
, repo
, path
)) < 0)
675 error
= git_submodule_init(sm
, false);
679 git_submodule_free(sm
);
685 git_config_file_free(mods
);
686 git_repository_free(subrepo
);
687 git_buf_free(&real_url
);
693 int git_submodule_repo_init(
694 git_repository
**out
,
695 const git_submodule
*sm
,
699 git_repository
*sub_repo
= NULL
;
700 const char *configured_url
;
701 git_config
*cfg
= NULL
;
702 git_buf buf
= GIT_BUF_INIT
;
706 /* get the configured remote url of the submodule */
707 if ((error
= git_buf_printf(&buf
, "submodule.%s.url", sm
->name
)) < 0 ||
708 (error
= git_repository_config_snapshot(&cfg
, sm
->repo
)) < 0 ||
709 (error
= git_config_get_string(&configured_url
, cfg
, buf
.ptr
)) < 0 ||
710 (error
= submodule_repo_init(&sub_repo
, sm
->repo
, sm
->path
, configured_url
, use_gitlink
)) < 0)
716 git_config_free(cfg
);
721 int git_submodule_add_finalize(git_submodule
*sm
)
728 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
729 (error
= git_index_add_bypath(index
, GIT_MODULES_FILE
)) < 0)
732 return git_submodule_add_to_index(sm
, true);
735 int git_submodule_add_to_index(git_submodule
*sm
, int write_index
)
738 git_repository
*sm_repo
= NULL
;
740 git_buf path
= GIT_BUF_INIT
;
742 git_index_entry entry
;
747 /* force reload of wd OID by git_submodule_open */
748 sm
->flags
= sm
->flags
& ~GIT_SUBMODULE_STATUS__WD_OID_VALID
;
750 if ((error
= git_repository_index__weakptr(&index
, sm
->repo
)) < 0 ||
751 (error
= git_buf_joinpath(
752 &path
, git_repository_workdir(sm
->repo
), sm
->path
)) < 0 ||
753 (error
= git_submodule_open(&sm_repo
, sm
)) < 0)
756 /* read stat information for submodule working directory */
757 if (p_stat(path
.ptr
, &st
) < 0) {
758 giterr_set(GITERR_SUBMODULE
,
759 "Cannot add submodule without working directory");
764 memset(&entry
, 0, sizeof(entry
));
765 entry
.path
= sm
->path
;
766 git_index_entry__init_from_stat(
767 &entry
, &st
, !(git_index_caps(index
) & GIT_INDEXCAP_NO_FILEMODE
));
769 /* calling git_submodule_open will have set sm->wd_oid if possible */
770 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) == 0) {
771 giterr_set(GITERR_SUBMODULE
,
772 "Cannot add submodule without HEAD to index");
776 git_oid_cpy(&entry
.id
, &sm
->wd_oid
);
778 if ((error
= git_commit_lookup(&head
, sm_repo
, &sm
->wd_oid
)) < 0)
781 entry
.ctime
.seconds
= (int32_t)git_commit_time(head
);
782 entry
.ctime
.nanoseconds
= 0;
783 entry
.mtime
.seconds
= (int32_t)git_commit_time(head
);
784 entry
.mtime
.nanoseconds
= 0;
786 git_commit_free(head
);
789 error
= git_index_add(index
, &entry
);
791 /* write it, if requested */
792 if (!error
&& write_index
) {
793 error
= git_index_write(index
);
796 git_oid_cpy(&sm
->index_oid
, &sm
->wd_oid
);
800 git_repository_free(sm_repo
);
805 const char *git_submodule_update_to_str(git_submodule_update_t update
)
808 for (i
= 0; i
< (int)ARRAY_SIZE(_sm_update_map
); ++i
)
809 if (_sm_update_map
[i
].map_value
== (int)update
)
810 return _sm_update_map
[i
].str_match
;
814 git_repository
*git_submodule_owner(git_submodule
*submodule
)
817 return submodule
->repo
;
820 const char *git_submodule_name(git_submodule
*submodule
)
823 return submodule
->name
;
826 const char *git_submodule_path(git_submodule
*submodule
)
829 return submodule
->path
;
832 const char *git_submodule_url(git_submodule
*submodule
)
835 return submodule
->url
;
838 int git_submodule_resolve_url(git_buf
*out
, git_repository
*repo
, const char *url
)
841 git_buf normalized
= GIT_BUF_INIT
;
843 assert(out
&& repo
&& url
);
845 git_buf_sanitize(out
);
847 /* We do this in all platforms in case someone on Windows created the .gitmodules */
848 if (strchr(url
, '\\')) {
849 if ((error
= git_path_normalize_slashes(&normalized
, url
)) < 0)
852 url
= normalized
.ptr
;
856 if (git_path_is_relative(url
)) {
857 if (!(error
= get_url_base(out
, repo
)))
858 error
= git_path_apply_relative(out
, url
);
859 } else if (strchr(url
, ':') != NULL
|| url
[0] == '/') {
860 error
= git_buf_sets(out
, url
);
862 giterr_set(GITERR_SUBMODULE
, "Invalid format for submodule URL");
866 git_buf_free(&normalized
);
870 static int write_var(git_repository
*repo
, const char *name
, const char *var
, const char *val
)
872 git_buf key
= GIT_BUF_INIT
;
873 git_config_backend
*mods
;
876 mods
= open_gitmodules(repo
, GITMODULES_CREATE
);
880 if ((error
= git_buf_printf(&key
, "submodule.%s.%s", name
, var
)) < 0)
884 error
= git_config_file_set_string(mods
, key
.ptr
, val
);
886 error
= git_config_file_delete(mods
, key
.ptr
);
891 git_config_file_free(mods
);
895 static int write_mapped_var(git_repository
*repo
, const char *name
, git_cvar_map
*maps
, size_t nmaps
, const char *var
, int ival
)
900 if (git_config_lookup_map_enum(&type
, &val
, maps
, nmaps
, ival
) < 0) {
901 giterr_set(GITERR_SUBMODULE
, "invalid value for %s", var
);
905 if (type
== GIT_CVAR_TRUE
)
908 return write_var(repo
, name
, var
, val
);
911 const char *git_submodule_branch(git_submodule
*submodule
)
914 return submodule
->branch
;
917 int git_submodule_set_branch(git_repository
*repo
, const char *name
, const char *branch
)
920 assert(repo
&& name
);
922 return write_var(repo
, name
, "branch", branch
);
925 int git_submodule_set_url(git_repository
*repo
, const char *name
, const char *url
)
927 assert(repo
&& name
&& url
);
929 return write_var(repo
, name
, "url", url
);
932 const git_oid
*git_submodule_index_id(git_submodule
*submodule
)
936 if (submodule
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
937 return &submodule
->index_oid
;
942 const git_oid
*git_submodule_head_id(git_submodule
*submodule
)
946 if (submodule
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
947 return &submodule
->head_oid
;
952 const git_oid
*git_submodule_wd_id(git_submodule
*submodule
)
956 /* load unless we think we have a valid oid */
957 if (!(submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)) {
958 git_repository
*subrepo
;
960 /* calling submodule open grabs the HEAD OID if possible */
961 if (!git_submodule_open_bare(&subrepo
, submodule
))
962 git_repository_free(subrepo
);
967 if (submodule
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
)
968 return &submodule
->wd_oid
;
973 git_submodule_ignore_t
git_submodule_ignore(git_submodule
*submodule
)
976 return (submodule
->ignore
< GIT_SUBMODULE_IGNORE_NONE
) ?
977 GIT_SUBMODULE_IGNORE_NONE
: submodule
->ignore
;
980 int git_submodule_set_ignore(git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
982 assert(repo
&& name
);
984 return write_mapped_var(repo
, name
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), "ignore", ignore
);
987 git_submodule_update_t
git_submodule_update_strategy(git_submodule
*submodule
)
990 return (submodule
->update
< GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
991 GIT_SUBMODULE_UPDATE_CHECKOUT
: submodule
->update
;
994 int git_submodule_set_update(git_repository
*repo
, const char *name
, git_submodule_update_t update
)
996 assert(repo
&& name
);
998 return write_mapped_var(repo
, name
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), "update", update
);
1001 git_submodule_recurse_t
git_submodule_fetch_recurse_submodules(
1002 git_submodule
*submodule
)
1005 return submodule
->fetch_recurse
;
1008 int git_submodule_set_fetch_recurse_submodules(git_repository
*repo
, const char *name
, git_submodule_recurse_t recurse
)
1010 assert(repo
&& name
);
1012 return write_mapped_var(repo
, name
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), "fetchRecurseSubmodules", recurse
);
1015 static int submodule_repo_create(
1016 git_repository
**out
,
1017 git_repository
*parent_repo
,
1021 git_buf workdir
= GIT_BUF_INIT
, repodir
= GIT_BUF_INIT
;
1022 git_repository_init_options initopt
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
1023 git_repository
*subrepo
= NULL
;
1026 GIT_REPOSITORY_INIT_MKPATH
|
1027 GIT_REPOSITORY_INIT_NO_REINIT
|
1028 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
|
1029 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
;
1031 /* Workdir: path to sub-repo working directory */
1032 error
= git_buf_joinpath(&workdir
, git_repository_workdir(parent_repo
), path
);
1036 initopt
.workdir_path
= workdir
.ptr
;
1039 * Repodir: path to the sub-repo. sub-repo goes in:
1040 * <repo-dir>/modules/<name>/ with a gitlink in the
1041 * sub-repo workdir directory to that repository.
1043 error
= git_buf_join3(
1044 &repodir
, '/', git_repository_path(parent_repo
), "modules", path
);
1048 error
= git_repository_init_ext(&subrepo
, repodir
.ptr
, &initopt
);
1051 git_buf_free(&workdir
);
1052 git_buf_free(&repodir
);
1060 * Callback to override sub-repository creation when
1061 * cloning a sub-repository.
1063 static int git_submodule_update_repo_init_cb(
1064 git_repository
**out
,
1075 return submodule_repo_create(out
, sm
->repo
, path
);
1078 int git_submodule_update_init_options(git_submodule_update_options
*opts
, unsigned int version
)
1080 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1081 opts
, version
, git_submodule_update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_INIT
);
1085 int git_submodule_update(git_submodule
*sm
, int init
, git_submodule_update_options
*_update_options
)
1088 unsigned int submodule_status
;
1089 git_config
*config
= NULL
;
1090 const char *submodule_url
;
1091 git_repository
*sub_repo
= NULL
;
1092 git_remote
*remote
= NULL
;
1093 git_object
*target_commit
= NULL
;
1094 git_buf buf
= GIT_BUF_INIT
;
1095 git_submodule_update_options update_options
= GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
1096 git_clone_options clone_options
= GIT_CLONE_OPTIONS_INIT
;
1100 if (_update_options
)
1101 memcpy(&update_options
, _update_options
, sizeof(git_submodule_update_options
));
1103 GITERR_CHECK_VERSION(&update_options
, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
, "git_submodule_update_options");
1105 /* Copy over the remote callbacks */
1106 memcpy(&clone_options
.fetch_opts
, &update_options
.fetch_opts
, sizeof(git_fetch_options
));
1108 /* Get the status of the submodule to determine if it is already initialized */
1109 if ((error
= git_submodule_status(&submodule_status
, sm
->repo
, sm
->name
, GIT_SUBMODULE_IGNORE_UNSPECIFIED
)) < 0)
1113 * If submodule work dir is not already initialized, check to see
1114 * what we need to do (initialize, clone, return error...)
1116 if (submodule_status
& GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
) {
1118 * Work dir is not initialized, check to see if the submodule
1119 * info has been copied into .git/config
1121 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1122 (error
= git_buf_printf(&buf
, "submodule.%s.url", git_submodule_name(sm
))) < 0)
1125 if ((error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0) {
1127 * If the error is not "not found" or if it is "not found" and we are not
1128 * initializing the submodule, then return error.
1130 if (error
!= GIT_ENOTFOUND
)
1133 if (error
== GIT_ENOTFOUND
&& !init
) {
1134 giterr_set(GITERR_SUBMODULE
, "Submodule is not initialized.");
1139 /* The submodule has not been initialized yet - initialize it now.*/
1140 if ((error
= git_submodule_init(sm
, 0)) < 0)
1143 git_config_free(config
);
1146 if ((error
= git_repository_config_snapshot(&config
, sm
->repo
)) < 0 ||
1147 (error
= git_config_get_string(&submodule_url
, config
, git_buf_cstr(&buf
))) < 0)
1151 /** submodule is initialized - now clone it **/
1152 /* override repo creation */
1153 clone_options
.repository_cb
= git_submodule_update_repo_init_cb
;
1154 clone_options
.repository_cb_payload
= sm
;
1157 * Do not perform checkout as part of clone, instead we
1158 * will checkout the specific commit manually.
1160 clone_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
1161 update_options
.checkout_opts
.checkout_strategy
= update_options
.clone_checkout_strategy
;
1163 if ((error
= git_clone(&sub_repo
, submodule_url
, sm
->path
, &clone_options
)) < 0 ||
1164 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0 ||
1165 (error
= git_checkout_head(sub_repo
, &update_options
.checkout_opts
)) != 0)
1169 * Work dir is initialized - look up the commit in the parent repository's index,
1170 * update the workdir contents of the subrepository, and set the subrepository's
1171 * head to the new commit.
1173 if ((error
= git_submodule_open(&sub_repo
, sm
)) < 0 ||
1174 (error
= git_object_lookup(&target_commit
, sub_repo
, git_submodule_index_id(sm
), GIT_OBJ_COMMIT
)) < 0 ||
1175 (error
= git_checkout_tree(sub_repo
, target_commit
, &update_options
.checkout_opts
)) != 0 ||
1176 (error
= git_repository_set_head_detached(sub_repo
, git_submodule_index_id(sm
))) < 0)
1179 /* Invalidate the wd flags as the workdir has been updated. */
1180 sm
->flags
= sm
->flags
&
1181 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1182 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1183 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1188 git_config_free(config
);
1189 git_object_free(target_commit
);
1190 git_remote_free(remote
);
1191 git_repository_free(sub_repo
);
1196 int git_submodule_init(git_submodule
*sm
, int overwrite
)
1200 git_buf key
= GIT_BUF_INIT
, effective_submodule_url
= GIT_BUF_INIT
;
1201 git_config
*cfg
= NULL
;
1204 giterr_set(GITERR_SUBMODULE
,
1205 "No URL configured for submodule '%s'", sm
->name
);
1209 if ((error
= git_repository_config(&cfg
, sm
->repo
)) < 0)
1212 /* write "submodule.NAME.url" */
1214 if ((error
= git_submodule_resolve_url(&effective_submodule_url
, sm
->repo
, sm
->url
)) < 0 ||
1215 (error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)) < 0 ||
1216 (error
= git_config__update_entry(
1217 cfg
, key
.ptr
, effective_submodule_url
.ptr
, overwrite
!= 0, false)) < 0)
1220 /* write "submodule.NAME.update" if not default */
1222 val
= (sm
->update
== GIT_SUBMODULE_UPDATE_CHECKOUT
) ?
1223 NULL
: git_submodule_update_to_str(sm
->update
);
1225 if ((error
= git_buf_printf(&key
, "submodule.%s.update", sm
->name
)) < 0 ||
1226 (error
= git_config__update_entry(
1227 cfg
, key
.ptr
, val
, overwrite
!= 0, false)) < 0)
1233 git_config_free(cfg
);
1235 git_buf_free(&effective_submodule_url
);
1240 int git_submodule_sync(git_submodule
*sm
)
1243 git_config
*cfg
= NULL
;
1244 git_buf key
= GIT_BUF_INIT
;
1245 git_repository
*smrepo
= NULL
;
1248 giterr_set(GITERR_SUBMODULE
,
1249 "No URL configured for submodule '%s'", sm
->name
);
1253 /* copy URL over to config only if it already exists */
1255 if (!(error
= git_repository_config__weakptr(&cfg
, sm
->repo
)) &&
1256 !(error
= git_buf_printf(&key
, "submodule.%s.url", sm
->name
)))
1257 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, true);
1259 /* if submodule exists in the working directory, update remote url */
1262 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) != 0 &&
1263 !(error
= git_submodule_open(&smrepo
, sm
)))
1265 git_buf remote_name
= GIT_BUF_INIT
;
1267 if ((error
= git_repository_config__weakptr(&cfg
, smrepo
)) < 0)
1268 /* return error from reading submodule config */;
1269 else if ((error
= lookup_head_remote_key(&remote_name
, smrepo
)) < 0) {
1271 error
= git_buf_sets(&key
, "remote.origin.url");
1273 error
= git_buf_join3(
1274 &key
, '.', "remote", remote_name
.ptr
, "url");
1275 git_buf_free(&remote_name
);
1279 error
= git_config__update_entry(cfg
, key
.ptr
, sm
->url
, true, false);
1281 git_repository_free(smrepo
);
1289 static int git_submodule__open(
1290 git_repository
**subrepo
, git_submodule
*sm
, bool bare
)
1293 git_buf path
= GIT_BUF_INIT
;
1294 unsigned int flags
= GIT_REPOSITORY_OPEN_NO_SEARCH
;
1297 assert(sm
&& subrepo
);
1299 if (git_repository__ensure_not_bare(
1300 sm
->repo
, "open submodule repository") < 0)
1301 return GIT_EBAREREPO
;
1303 wd
= git_repository_workdir(sm
->repo
);
1305 if (git_buf_joinpath(&path
, wd
, sm
->path
) < 0 ||
1306 git_buf_joinpath(&path
, path
.ptr
, DOT_GIT
) < 0)
1309 sm
->flags
= sm
->flags
&
1310 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1311 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1312 GIT_SUBMODULE_STATUS__WD_SCANNED
);
1315 flags
|= GIT_REPOSITORY_OPEN_BARE
;
1317 error
= git_repository_open_ext(subrepo
, path
.ptr
, flags
, wd
);
1319 /* if we opened the submodule successfully, grab HEAD OID, etc. */
1321 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
|
1322 GIT_SUBMODULE_STATUS__WD_SCANNED
;
1324 if (!git_reference_name_to_id(&sm
->wd_oid
, *subrepo
, GIT_HEAD_FILE
))
1325 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_OID_VALID
;
1328 } else if (git_path_exists(path
.ptr
)) {
1329 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
|
1330 GIT_SUBMODULE_STATUS_IN_WD
;
1332 git_buf_rtruncate_at_char(&path
, '/'); /* remove "/.git" */
1334 if (git_path_isdir(path
.ptr
))
1335 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1338 git_buf_free(&path
);
1343 int git_submodule_open_bare(git_repository
**subrepo
, git_submodule
*sm
)
1345 return git_submodule__open(subrepo
, sm
, true);
1348 int git_submodule_open(git_repository
**subrepo
, git_submodule
*sm
)
1350 return git_submodule__open(subrepo
, sm
, false);
1353 static void submodule_update_from_index_entry(
1354 git_submodule
*sm
, const git_index_entry
*ie
)
1356 bool already_found
= (sm
->flags
& GIT_SUBMODULE_STATUS_IN_INDEX
) != 0;
1358 if (!S_ISGITLINK(ie
->mode
)) {
1360 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
1363 sm
->flags
|= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
1365 git_oid_cpy(&sm
->index_oid
, &ie
->id
);
1367 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_INDEX
|
1368 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
1372 static int submodule_update_index(git_submodule
*sm
)
1375 const git_index_entry
*ie
;
1377 if (git_repository_index__weakptr(&index
, sm
->repo
) < 0)
1380 sm
->flags
= sm
->flags
&
1381 ~(GIT_SUBMODULE_STATUS_IN_INDEX
|
1382 GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
1384 if (!(ie
= git_index_get_bypath(index
, sm
->path
, 0)))
1387 submodule_update_from_index_entry(sm
, ie
);
1392 static void submodule_update_from_head_data(
1393 git_submodule
*sm
, mode_t mode
, const git_oid
*id
)
1395 if (!S_ISGITLINK(mode
))
1396 sm
->flags
|= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
1398 git_oid_cpy(&sm
->head_oid
, id
);
1400 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_HEAD
|
1401 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
1405 static int submodule_update_head(git_submodule
*submodule
)
1407 git_tree
*head
= NULL
;
1408 git_tree_entry
*te
= NULL
;
1410 submodule
->flags
= submodule
->flags
&
1411 ~(GIT_SUBMODULE_STATUS_IN_HEAD
|
1412 GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
1414 /* if we can't look up file in current head, then done */
1415 if (git_repository_head_tree(&head
, submodule
->repo
) < 0 ||
1416 git_tree_entry_bypath(&te
, head
, submodule
->path
) < 0)
1419 submodule_update_from_head_data(submodule
, te
->attr
, &te
->oid
);
1421 git_tree_entry_free(te
);
1422 git_tree_free(head
);
1426 int git_submodule_reload(git_submodule
*sm
, int force
)
1435 if (!git_repository_is_bare(sm
->repo
)) {
1436 /* refresh config data */
1437 mods
= gitmodules_snapshot(sm
->repo
);
1439 error
= submodule_read_config(sm
, mods
);
1440 git_config_free(mods
);
1446 /* refresh wd data */
1448 ~(GIT_SUBMODULE_STATUS_IN_WD
|
1449 GIT_SUBMODULE_STATUS__WD_OID_VALID
|
1450 GIT_SUBMODULE_STATUS__WD_FLAGS
);
1452 error
= submodule_load_from_wd_lite(sm
);
1455 if (error
== 0 && (error
= submodule_update_index(sm
)) == 0)
1456 error
= submodule_update_head(sm
);
1461 static void submodule_copy_oid_maybe(
1462 git_oid
*tgt
, const git_oid
*src
, bool valid
)
1466 memcpy(tgt
, src
, sizeof(*tgt
));
1468 memset(tgt
, 0, sizeof(*tgt
));
1472 int git_submodule__status(
1473 unsigned int *out_status
,
1474 git_oid
*out_head_id
,
1475 git_oid
*out_index_id
,
1478 git_submodule_ignore_t ign
)
1480 unsigned int status
;
1481 git_repository
*smrepo
= NULL
;
1483 if (ign
== GIT_SUBMODULE_IGNORE_UNSPECIFIED
)
1486 /* only return location info if ignore == all */
1487 if (ign
== GIT_SUBMODULE_IGNORE_ALL
) {
1488 *out_status
= (sm
->flags
& GIT_SUBMODULE_STATUS__IN_FLAGS
);
1492 /* refresh the index OID */
1493 if (submodule_update_index(sm
) < 0)
1496 /* refresh the HEAD OID */
1497 if (submodule_update_head(sm
) < 0)
1500 /* for ignore == dirty, don't scan the working directory */
1501 if (ign
== GIT_SUBMODULE_IGNORE_DIRTY
) {
1502 /* git_submodule_open_bare will load WD OID data */
1503 if (git_submodule_open_bare(&smrepo
, sm
) < 0)
1506 git_repository_free(smrepo
);
1508 } else if (git_submodule_open(&smrepo
, sm
) < 0) {
1513 status
= GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm
->flags
);
1515 submodule_get_index_status(&status
, sm
);
1516 submodule_get_wd_status(&status
, sm
, smrepo
, ign
);
1518 git_repository_free(smrepo
);
1520 *out_status
= status
;
1522 submodule_copy_oid_maybe(out_head_id
, &sm
->head_oid
,
1523 (sm
->flags
& GIT_SUBMODULE_STATUS__HEAD_OID_VALID
) != 0);
1524 submodule_copy_oid_maybe(out_index_id
, &sm
->index_oid
,
1525 (sm
->flags
& GIT_SUBMODULE_STATUS__INDEX_OID_VALID
) != 0);
1526 submodule_copy_oid_maybe(out_wd_id
, &sm
->wd_oid
,
1527 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) != 0);
1532 int git_submodule_status(unsigned int *status
, git_repository
*repo
, const char *name
, git_submodule_ignore_t ignore
)
1537 assert(status
&& repo
&& name
);
1539 if ((error
= git_submodule_lookup(&sm
, repo
, name
)) < 0)
1542 error
= git_submodule__status(status
, NULL
, NULL
, NULL
, sm
, ignore
);
1543 git_submodule_free(sm
);
1548 int git_submodule_location(unsigned int *location
, git_submodule
*sm
)
1550 assert(location
&& sm
);
1552 return git_submodule__status(
1553 location
, NULL
, NULL
, NULL
, sm
, GIT_SUBMODULE_IGNORE_ALL
);
1558 * INTERNAL FUNCTIONS
1561 static int submodule_alloc(
1562 git_submodule
**out
, git_repository
*repo
, const char *name
)
1567 if (!name
|| !(namelen
= strlen(name
))) {
1568 giterr_set(GITERR_SUBMODULE
, "Invalid submodule name");
1572 sm
= git__calloc(1, sizeof(git_submodule
));
1573 GITERR_CHECK_ALLOC(sm
);
1575 sm
->name
= sm
->path
= git__strdup(name
);
1581 GIT_REFCOUNT_INC(sm
);
1582 sm
->ignore
= sm
->ignore_default
= GIT_SUBMODULE_IGNORE_NONE
;
1583 sm
->update
= sm
->update_default
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1584 sm
->fetch_recurse
= sm
->fetch_recurse_default
= GIT_SUBMODULE_RECURSE_NO
;
1592 static void submodule_release(git_submodule
*sm
)
1601 if (sm
->path
!= sm
->name
)
1602 git__free(sm
->path
);
1603 git__free(sm
->name
);
1605 git__free(sm
->branch
);
1606 git__memzero(sm
, sizeof(*sm
));
1610 void git_submodule_free(git_submodule
*sm
)
1614 GIT_REFCOUNT_DEC(sm
, submodule_release
);
1617 static int submodule_config_error(const char *property
, const char *value
)
1619 giterr_set(GITERR_INVALID
,
1620 "Invalid value for submodule '%s' property: '%s'", property
, value
);
1624 int git_submodule_parse_ignore(git_submodule_ignore_t
*out
, const char *value
)
1628 if (git_config_lookup_map_value(
1629 &val
, _sm_ignore_map
, ARRAY_SIZE(_sm_ignore_map
), value
) < 0) {
1630 *out
= GIT_SUBMODULE_IGNORE_NONE
;
1631 return submodule_config_error("ignore", value
);
1634 *out
= (git_submodule_ignore_t
)val
;
1638 int git_submodule_parse_update(git_submodule_update_t
*out
, const char *value
)
1642 if (git_config_lookup_map_value(
1643 &val
, _sm_update_map
, ARRAY_SIZE(_sm_update_map
), value
) < 0) {
1644 *out
= GIT_SUBMODULE_UPDATE_CHECKOUT
;
1645 return submodule_config_error("update", value
);
1648 *out
= (git_submodule_update_t
)val
;
1652 int git_submodule_parse_recurse(git_submodule_recurse_t
*out
, const char *value
)
1656 if (git_config_lookup_map_value(
1657 &val
, _sm_recurse_map
, ARRAY_SIZE(_sm_recurse_map
), value
) < 0) {
1658 *out
= GIT_SUBMODULE_RECURSE_YES
;
1659 return submodule_config_error("recurse", value
);
1662 *out
= (git_submodule_recurse_t
)val
;
1666 static int get_value(const char **out
, git_config
*cfg
, git_buf
*buf
, const char *name
, const char *field
)
1672 if ((error
= git_buf_printf(buf
, "submodule.%s.%s", name
, field
)) < 0 ||
1673 (error
= git_config_get_string(out
, cfg
, buf
->ptr
)) < 0)
1679 static int submodule_read_config(git_submodule
*sm
, git_config
*cfg
)
1681 git_buf key
= GIT_BUF_INIT
;
1683 int error
, in_config
= 0;
1686 * TODO: Look up path in index and if it is present but not a GITLINK
1687 * then this should be deleted (at least to match git's behavior)
1690 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "path")) == 0) {
1693 * TODO: if case insensitive filesystem, then the following strcmp
1694 * should be strcasecmp
1696 if (strcmp(sm
->name
, value
) != 0) {
1697 if (sm
->path
!= sm
->name
)
1698 git__free(sm
->path
);
1699 sm
->path
= git__strdup(value
);
1700 GITERR_CHECK_ALLOC(sm
->path
);
1702 } else if (error
!= GIT_ENOTFOUND
) {
1706 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "url")) == 0) {
1708 sm
->url
= git__strdup(value
);
1709 GITERR_CHECK_ALLOC(sm
->url
);
1710 } else if (error
!= GIT_ENOTFOUND
) {
1714 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "branch")) == 0) {
1716 sm
->branch
= git__strdup(value
);
1717 GITERR_CHECK_ALLOC(sm
->branch
);
1718 } else if (error
!= GIT_ENOTFOUND
) {
1722 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "update")) == 0) {
1724 if ((error
= git_submodule_parse_update(&sm
->update
, value
)) < 0)
1726 sm
->update_default
= sm
->update
;
1727 } else if (error
!= GIT_ENOTFOUND
) {
1731 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "fetchRecurseSubmodules")) == 0) {
1733 if ((error
= git_submodule_parse_recurse(&sm
->fetch_recurse
, value
)) < 0)
1735 sm
->fetch_recurse_default
= sm
->fetch_recurse
;
1736 } else if (error
!= GIT_ENOTFOUND
) {
1740 if ((error
= get_value(&value
, cfg
, &key
, sm
->name
, "ignore")) == 0) {
1742 if ((error
= git_submodule_parse_ignore(&sm
->ignore
, value
)) < 0)
1744 sm
->ignore_default
= sm
->ignore
;
1745 } else if (error
!= GIT_ENOTFOUND
) {
1750 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_CONFIG
;
1759 static int submodule_load_each(const git_config_entry
*entry
, void *payload
)
1761 lfc_data
*data
= payload
;
1762 const char *namestart
, *property
;
1763 git_strmap_iter pos
;
1764 git_strmap
*map
= data
->map
;
1765 git_buf name
= GIT_BUF_INIT
;
1769 if (git__prefixcmp(entry
->name
, "submodule.") != 0)
1772 namestart
= entry
->name
+ strlen("submodule.");
1773 property
= strrchr(namestart
, '.');
1775 if (!property
|| (property
== namestart
))
1780 if ((error
= git_buf_set(&name
, namestart
, property
- namestart
-1)) < 0)
1784 * Now that we have the submodule's name, we can use that to
1785 * figure out whether it's in the map. If it's not, we create
1786 * a new submodule, load the config and insert it. If it's
1787 * already inserted, we've already loaded it, so we skip.
1789 pos
= git_strmap_lookup_index(map
, name
.ptr
);
1790 if (git_strmap_valid_index(map
, pos
)) {
1795 if ((error
= submodule_alloc(&sm
, data
->repo
, name
.ptr
)) < 0)
1798 if ((error
= submodule_read_config(sm
, data
->mods
)) < 0) {
1799 git_submodule_free(sm
);
1803 git_strmap_insert(map
, sm
->name
, sm
, error
);
1811 git_buf_free(&name
);
1815 static int submodule_load_from_wd_lite(git_submodule
*sm
)
1817 git_buf path
= GIT_BUF_INIT
;
1819 if (git_buf_joinpath(&path
, git_repository_workdir(sm
->repo
), sm
->path
) < 0)
1822 if (git_path_isdir(path
.ptr
))
1823 sm
->flags
|= GIT_SUBMODULE_STATUS__WD_SCANNED
;
1825 if (git_path_contains(&path
, DOT_GIT
))
1826 sm
->flags
|= GIT_SUBMODULE_STATUS_IN_WD
;
1828 git_buf_free(&path
);
1833 * Returns a snapshot of $WORK_TREE/.gitmodules.
1835 * We ignore any errors and just pretend the file isn't there.
1837 static git_config
*gitmodules_snapshot(git_repository
*repo
)
1839 const char *workdir
= git_repository_workdir(repo
);
1840 git_config
*mods
= NULL
, *snap
= NULL
;
1841 git_buf path
= GIT_BUF_INIT
;
1843 if (workdir
!= NULL
) {
1844 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1847 if (git_config_open_ondisk(&mods
, path
.ptr
) < 0)
1851 git_buf_free(&path
);
1854 git_config_snapshot(&snap
, mods
);
1855 git_config_free(mods
);
1861 static git_config_backend
*open_gitmodules(
1862 git_repository
*repo
,
1865 const char *workdir
= git_repository_workdir(repo
);
1866 git_buf path
= GIT_BUF_INIT
;
1867 git_config_backend
*mods
= NULL
;
1869 if (workdir
!= NULL
) {
1870 if (git_buf_joinpath(&path
, workdir
, GIT_MODULES_FILE
) != 0)
1873 if (okay_to_create
|| git_path_isfile(path
.ptr
)) {
1874 /* git_config_file__ondisk should only fail if OOM */
1875 if (git_config_file__ondisk(&mods
, path
.ptr
) < 0)
1877 /* open should only fail here if the file is malformed */
1878 else if (git_config_file_open(mods
, GIT_CONFIG_LEVEL_LOCAL
) < 0) {
1879 git_config_file_free(mods
);
1885 git_buf_free(&path
);
1890 /* Lookup name of remote of the local tracking branch HEAD points to */
1891 static int lookup_head_remote_key(git_buf
*remote_name
, git_repository
*repo
)
1894 git_reference
*head
= NULL
;
1895 git_buf upstream_name
= GIT_BUF_INIT
;
1897 /* lookup and dereference HEAD */
1898 if ((error
= git_repository_head(&head
, repo
)) < 0)
1902 * If head does not refer to a branch, then return
1903 * GIT_ENOTFOUND to indicate that we could not find
1904 * a remote key for the local tracking branch HEAD points to.
1906 if (!git_reference_is_branch(head
)) {
1907 giterr_set(GITERR_INVALID
,
1908 "HEAD does not refer to a branch.");
1909 error
= GIT_ENOTFOUND
;
1913 /* lookup remote tracking branch of HEAD */
1914 if ((error
= git_branch_upstream_name(
1917 git_reference_name(head
))) < 0)
1920 /* lookup remote of remote tracking branch */
1921 if ((error
= git_branch_remote_name(remote_name
, repo
, upstream_name
.ptr
)) < 0)
1925 git_buf_free(&upstream_name
);
1926 git_reference_free(head
);
1931 /* Lookup the remote of the local tracking branch HEAD points to */
1932 static int lookup_head_remote(git_remote
**remote
, git_repository
*repo
)
1935 git_buf remote_name
= GIT_BUF_INIT
;
1937 /* lookup remote of remote tracking branch name */
1938 if (!(error
= lookup_head_remote_key(&remote_name
, repo
)))
1939 error
= git_remote_lookup(remote
, repo
, remote_name
.ptr
);
1941 git_buf_free(&remote_name
);
1946 /* Lookup remote, either from HEAD or fall back on origin */
1947 static int lookup_default_remote(git_remote
**remote
, git_repository
*repo
)
1949 int error
= lookup_head_remote(remote
, repo
);
1951 /* if that failed, use 'origin' instead */
1952 if (error
== GIT_ENOTFOUND
)
1953 error
= git_remote_lookup(remote
, repo
, "origin");
1955 if (error
== GIT_ENOTFOUND
)
1958 "Cannot get default remote for submodule - no local tracking "
1959 "branch for HEAD and origin does not exist");
1964 static int get_url_base(git_buf
*url
, git_repository
*repo
)
1967 git_remote
*remote
= NULL
;
1969 if (!(error
= lookup_default_remote(&remote
, repo
))) {
1970 error
= git_buf_sets(url
, git_remote_url(remote
));
1971 git_remote_free(remote
);
1973 else if (error
== GIT_ENOTFOUND
) {
1974 /* if repository does not have a default remote, use workdir instead */
1976 error
= git_buf_sets(url
, git_repository_workdir(repo
));
1982 static void submodule_get_index_status(unsigned int *status
, git_submodule
*sm
)
1984 const git_oid
*head_oid
= git_submodule_head_id(sm
);
1985 const git_oid
*index_oid
= git_submodule_index_id(sm
);
1987 *status
= *status
& ~GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
1991 *status
|= GIT_SUBMODULE_STATUS_INDEX_ADDED
;
1993 else if (!index_oid
)
1994 *status
|= GIT_SUBMODULE_STATUS_INDEX_DELETED
;
1995 else if (!git_oid_equal(head_oid
, index_oid
))
1996 *status
|= GIT_SUBMODULE_STATUS_INDEX_MODIFIED
;
2000 static void submodule_get_wd_status(
2001 unsigned int *status
,
2003 git_repository
*sm_repo
,
2004 git_submodule_ignore_t ign
)
2006 const git_oid
*index_oid
= git_submodule_index_id(sm
);
2007 const git_oid
*wd_oid
=
2008 (sm
->flags
& GIT_SUBMODULE_STATUS__WD_OID_VALID
) ? &sm
->wd_oid
: NULL
;
2009 git_tree
*sm_head
= NULL
;
2010 git_index
*index
= NULL
;
2011 git_diff_options opt
= GIT_DIFF_OPTIONS_INIT
;
2014 *status
= *status
& ~GIT_SUBMODULE_STATUS__WD_FLAGS
;
2018 *status
|= GIT_SUBMODULE_STATUS_WD_ADDED
;
2021 if ((sm
->flags
& GIT_SUBMODULE_STATUS__WD_SCANNED
) != 0 &&
2022 (sm
->flags
& GIT_SUBMODULE_STATUS_IN_WD
) == 0)
2023 *status
|= GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
;
2025 *status
|= GIT_SUBMODULE_STATUS_WD_DELETED
;
2027 else if (!git_oid_equal(index_oid
, wd_oid
))
2028 *status
|= GIT_SUBMODULE_STATUS_WD_MODIFIED
;
2030 /* if we have no repo, then we're done */
2034 /* the diffs below could be optimized with an early termination
2035 * option to the git_diff functions, but for now this is sufficient
2036 * (and certainly no worse that what core git does).
2039 if (ign
== GIT_SUBMODULE_IGNORE_NONE
)
2040 opt
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
2042 (void)git_repository_index__weakptr(&index
, sm_repo
);
2044 /* if we don't have an unborn head, check diff with index */
2045 if (git_repository_head_tree(&sm_head
, sm_repo
) < 0)
2048 /* perform head to index diff on submodule */
2049 if (git_diff_tree_to_index(&diff
, sm_repo
, sm_head
, index
, &opt
) < 0)
2052 if (git_diff_num_deltas(diff
) > 0)
2053 *status
|= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
2054 git_diff_free(diff
);
2058 git_tree_free(sm_head
);
2061 /* perform index-to-workdir diff on submodule */
2062 if (git_diff_index_to_workdir(&diff
, sm_repo
, index
, &opt
) < 0)
2066 git_diff_num_deltas_of_type(diff
, GIT_DELTA_UNTRACKED
);
2069 *status
|= GIT_SUBMODULE_STATUS_WD_UNTRACKED
;
2071 if (git_diff_num_deltas(diff
) != untracked
)
2072 *status
|= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
;
2074 git_diff_free(diff
);