Skip to content

Commit 59a0005

Browse files
author
Edward Thomson
authored
Merge pull request libgit2#3813 from stinb/submodule-update-fetch
submodule: Try to fetch when update fails to find the target commit.
2 parents d88e500 + de43efc commit 59a0005

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

include/git2/submodule.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,19 @@ typedef struct git_submodule_update_options {
154154
* in the working directory for the newly cloned repository.
155155
*/
156156
unsigned int clone_checkout_strategy;
157+
158+
/**
159+
* Allow fetching from the submodule's default remote if the target
160+
* commit isn't found. Enabled by default.
161+
*/
162+
int allow_fetch;
157163
} git_submodule_update_options;
158164

159165
#define GIT_SUBMODULE_UPDATE_OPTIONS_VERSION 1
160166
#define GIT_SUBMODULE_UPDATE_OPTIONS_INIT \
161-
{ GIT_CHECKOUT_OPTIONS_VERSION, \
167+
{ GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, \
162168
{ GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \
163-
GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE }
169+
GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE, 1 }
164170

165171
/**
166172
* Initializes a `git_submodule_update_options` with default values.
@@ -176,7 +182,9 @@ GIT_EXTERN(int) git_submodule_update_init_options(
176182
/**
177183
* Update a submodule. This will clone a missing submodule and
178184
* checkout the subrepository to the commit specified in the index of
179-
* containing repository.
185+
* the containing repository. If the submodule repository doesn't contain
186+
* the target commit (e.g. because fetchRecurseSubmodules isn't set), then
187+
* the submodule is fetched using the fetch options supplied in options.
180188
*
181189
* @param submodule Submodule object
182190
* @param init If the submodule is not initialized, setting this flag to true

src/submodule.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ static git_config_backend *open_gitmodules(git_repository *repo, int gitmod);
9393
static git_config *gitmodules_snapshot(git_repository *repo);
9494
static int get_url_base(git_buf *url, git_repository *repo);
9595
static int lookup_head_remote_key(git_buf *remote_key, git_repository *repo);
96+
static int lookup_default_remote(git_remote **remote, git_repository *repo);
9697
static int submodule_load_each(const git_config_entry *entry, void *payload);
9798
static int submodule_read_config(git_submodule *sm, git_config *cfg);
9899
static int submodule_load_from_wd_lite(git_submodule *);
@@ -1131,7 +1132,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
11311132
if (error != GIT_ENOTFOUND)
11321133
goto done;
11331134

1134-
if (error == GIT_ENOTFOUND && !init) {
1135+
if (!init) {
11351136
giterr_set(GITERR_SUBMODULE, "Submodule is not initialized.");
11361137
error = GIT_ERROR;
11371138
goto done;
@@ -1171,9 +1172,20 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
11711172
* update the workdir contents of the subrepository, and set the subrepository's
11721173
* head to the new commit.
11731174
*/
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 ||
1175+
if ((error = git_submodule_open(&sub_repo, sm)) < 0)
1176+
goto done;
1177+
1178+
/* Look up the target commit in the submodule. */
1179+
if ((error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJ_COMMIT)) < 0) {
1180+
/* If it isn't found then fetch and try again. */
1181+
if (error != GIT_ENOTFOUND || !update_options.allow_fetch ||
1182+
(error = lookup_default_remote(&remote, sub_repo)) < 0 ||
1183+
(error = git_remote_fetch(remote, NULL, &update_options.fetch_opts, NULL)) < 0 ||
1184+
(error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJ_COMMIT)) < 0)
1185+
goto done;
1186+
}
1187+
1188+
if ((error = git_checkout_tree(sub_repo, target_commit, &update_options.checkout_opts)) != 0 ||
11771189
(error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0)
11781190
goto done;
11791191

0 commit comments

Comments
 (0)