diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 9e8cdfe1b2..4aa237033a 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -41,61 +41,25 @@ typedef void (*each_submodule_fn)(const struct cache_entry *list_item, void *cb_data); -static int repo_get_default_remote(struct repository *repo, char **default_remote) -{ - char *dest = NULL; - struct strbuf sb = STRBUF_INIT; - struct ref_store *store = get_main_ref_store(repo); - const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL, - NULL); - - if (!refname) - return die_message(_("No such ref: %s"), "HEAD"); - - /* detached HEAD */ - if (!strcmp(refname, "HEAD")) { - *default_remote = xstrdup("origin"); - return 0; - } - - if (!skip_prefix(refname, "refs/heads/", &refname)) - return die_message(_("Expecting a full ref name, got %s"), - refname); - - strbuf_addf(&sb, "branch.%s.remote", refname); - if (repo_config_get_string(repo, sb.buf, &dest)) - *default_remote = xstrdup("origin"); - else - *default_remote = dest; - - strbuf_release(&sb); - return 0; -} - static int get_default_remote_submodule(const char *module_path, char **default_remote) { struct repository subrepo; - int ret; if (repo_submodule_init(&subrepo, the_repository, module_path, null_oid(the_hash_algo)) < 0) return die_message(_("could not get a repository handle for submodule '%s'"), module_path); - ret = repo_get_default_remote(&subrepo, default_remote); + + *default_remote = xstrdup(repo_default_remote(&subrepo)); + repo_clear(&subrepo); - return ret; + return 0; } static char *get_default_remote(void) { - char *default_remote; - int code = repo_get_default_remote(the_repository, &default_remote); - - if (code) - exit(code); - - return default_remote; + return xstrdup(repo_default_remote(the_repository)); } static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet) diff --git a/remote.c b/remote.c index e7ff21dc03..e35cf7ec61 100644 --- a/remote.c +++ b/remote.c @@ -1772,20 +1772,35 @@ static void set_merge(struct repository *repo, struct branch *ret) } } -struct branch *branch_get(const char *name) +static struct branch *repo_branch_get(struct repository *repo, const char *name) { struct branch *ret; - read_config(the_repository, 0); + read_config(repo, 0); if (!name || !*name || !strcmp(name, "HEAD")) - ret = the_repository->remote_state->current_branch; + ret = repo->remote_state->current_branch; else - ret = make_branch(the_repository->remote_state, name, + ret = make_branch(repo->remote_state, name, strlen(name)); - set_merge(the_repository, ret); + set_merge(repo, ret); return ret; } +struct branch *branch_get(const char *name) +{ + return repo_branch_get(the_repository, name); +} + +const char *repo_default_remote(struct repository *repo) +{ + struct branch *branch; + + read_config(repo, 0); + branch = repo_branch_get(repo, "HEAD"); + + return remotes_remote_for_branch(repo->remote_state, branch, NULL); +} + int branch_has_merge_config(struct branch *branch) { return branch && branch->set_merge; diff --git a/remote.h b/remote.h index 76d93bf88d..8dc5cfa49e 100644 --- a/remote.h +++ b/remote.h @@ -9,6 +9,7 @@ struct option; struct transport_ls_refs_options; +struct repository; /** * The API gives access to the configuration related to remotes. It handles @@ -338,6 +339,8 @@ const char *remote_for_branch(struct branch *branch, int *explicit); const char *pushremote_for_branch(struct branch *branch, int *explicit); char *remote_ref_for_branch(struct branch *branch, int for_push); +const char *repo_default_remote(struct repository *repo); + /* returns true if the given branch has merge configuration given. */ int branch_has_merge_config(struct branch *branch); diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index c562bad042..748b529745 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -1134,6 +1134,35 @@ test_expect_success 'setup clean recursive superproject' ' git clone --recurse-submodules top top-clean ' +test_expect_success 'submodule update with renamed remote' ' + test_when_finished "rm -fr top-cloned" && + cp -r top-clean top-cloned && + + # Create a commit in each repo, starting with bottom + test_commit -C bottom rename_commit && + # Create middle commit + git -C middle/bottom fetch && + git -C middle/bottom checkout -f FETCH_HEAD && + git -C middle add bottom && + git -C middle commit -m "rename_commit" && + # Create top commit + git -C top/middle fetch && + git -C top/middle checkout -f FETCH_HEAD && + git -C top add middle && + git -C top commit -m "rename_commit" && + + # rename the submodule remote + git -C top-cloned/middle remote rename origin upstream && + + # Make the update of "middle" a no-op, otherwise we error out + # because of its unmerged state + test_config -C top-cloned submodule.middle.update !true && + git -C top-cloned submodule update --recursive 2>actual.err && + cat >expect.err <<-\EOF && + EOF + test_cmp expect.err actual.err +' + test_expect_success 'submodule update should skip unmerged submodules' ' test_when_finished "rm -fr top-cloned" && cp -r top-clean top-cloned &&