Show 109 quoted lines
>> diff --git a/submodule.c b/submodule.c
>> index f645372a18..85ca7ea0fb 100644
>> --- a/submodule.c
>> +++ b/submodule.c
>> @@ -2570,30 +2570,39 @@ int submodule_to_gitdir(struct repository *repo,
>> void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
>> const char *submodule_name)
>> {
>> - /*
>> - * NEEDSWORK: The current way of mapping a submodule's name to
>> - * its location in .git/modules/ has problems with some naming
>> - * schemes. For example, if a submodule is named "foo" and
>> - * another is named "foo/bar" (whether present in the same
>> - * superproject commit or not - the problem will arise if both
>> - * superproject commits have been checked out at any point in
>> - * time), or if two submodule names only have different cases in
>> - * a case-insensitive filesystem.
>> - *
>> - * There are several solutions, including encoding the path in
>> - * some way, introducing a submodule.<name>.gitdir config in
>> - * .git/config (not .gitmodules) that allows overriding what the
>> - * gitdir of a submodule would be (and teach Git, upon noticing
>> - * a clash, to automatically determine a non-clashing name and
>> - * to write such a config), or introducing a
>> - * submodule.<name>.gitdir config in .gitmodules that repo
>> - * administrators can explicitly set. Nothing has been decided,
>> - * so for now, just append the name at the end of the path.
>> - */
>> - repo_git_path_append(r, buf, "modules/");
>> - strbuf_addstr(buf, submodule_name);
>> + const char *gitdir;
>> + char *key;
>> + int ret;
>> +
>> + /* If extensions.submodulePathConfig is disabled, continue to use the plain path */
>> + if (!r->repository_format_submodule_path_cfg) {
>> + repo_git_path_append(r, buf, "modules/%s", submodule_name);
>> + if (validate_submodule_git_dir(buf->buf, submodule_name) < 0)
>> + die(_("refusing to create/use '%s' in another submodule's "
>> + "git dir"), buf->buf);
>> +
>> + return; /* plain gitdir is valid for use */
>> + }
>> +
>> + /* Extension is enabled: use the gitdir config if it exists */
>> + key = xstrfmt("submodule.%s.gitdir", submodule_name);
>> + ret = repo_config_get_string_tmp(r, key, &gitdir);
>> + FREE_AND_NULL(key);
>> +
>> + if (!ret) {
>> + strbuf_addstr(buf, gitdir);
>> +
>> + /* validate because users might have modified the config */
>> + if (validate_submodule_git_dir(buf->buf, submodule_name))
>> + die(_("invalid 'submodule.%s.gitdir' config: '%s' please check "
>> + "if it is unique or conflicts with another module"),
>> + submodule_name, gitdir);
>> +
>> + return; /* gitdir from config is valid for use */
>> + }
>>
>> - if (validate_submodule_git_dir(buf->buf, submodule_name) < 0)
>> - die(_("refusing to create/use '%s' in another submodule's "
>> - "git dir"), buf->buf);
>> + die(_("the 'submodule.%s.gitdir' config does not exist for module '%s'. "
>> + "Please ensure it is set, for example by running something like: "
>> + "'git config submodule.%s.gitdir .git/modules/%s'"),
>> + submodule_name, submodule_name, submodule_name, submodule_name);
>
> I think the logic would flow a bit more naturally if we didn't have all
> the early returns. Something like the following untested and uncompiled
> code:
>
> void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
> const char *submodule_name)
> {
> if (!r->repository_format_submodule_path_cfg) {
> /*
> * If extensions.submodulePathConfig is disabled,
> * continue to use the plain path.
> */
> repo_git_path_append(r, buf, "modules/%s", submodule_name);
> } else {
> const char *gitdir;
> char *key;
>
> /* Otherwise, if the extension is enabled, we use the gitdir config. */
> key = xstrfmt("submodule.%s.gitdir", submodule_name);
>
> if (repo_config_get_string_tmp(r, key, &gitdir)) {
> die(_("the 'submodule.%s.gitdir' config does not exist for module '%s'. "
> "Please ensure it is set, for example by running something like: "
> "'git config submodule.%s.gitdir .git/modules/%s'"),
> submodule_name, submodule_name, submodule_name, submodule_name);
> }
>
> strbuf_addstr(buf, gitdir);
> FREE_AND_NULL(key);
> }
>
> if (validate_submodule_git_dir(buf->buf, submodule_name)) {
> die(_("invalid 'submodule.%s.gitdir' config: '%s' please check "
> "if it is unique or conflicts with another module"),
> submodule_name, gitdir);
> }
> }
>
> I think it would make sense to also hint at the extension in the error
> message here so that users know _why_ we expect the key to be set.