Merge branch 'kj/renamed-submodule'
The case where a new submodule takes a path where used to be a completely different subproject is now dealt a bit better than before. * kj/renamed-submodule: fixup! submodule: skip redundant active entries when pattern covers path fixup! submodule: prevent overwriting .gitmodules on path reuse submodule: skip redundant active entries when pattern covers path submodule: prevent overwriting .gitmodules on path reuse
This commit is contained in:
@@ -307,6 +307,13 @@ OPTIONS
|
||||
--force::
|
||||
This option is only valid for add, deinit and update commands.
|
||||
When running add, allow adding an otherwise ignored submodule path.
|
||||
This option is also used to bypass a check that the submodule's name
|
||||
is not already in use. By default, 'git submodule add' will fail if
|
||||
the proposed name (which is derived from the path) is already registered
|
||||
for another submodule in the repository. Using '--force' allows the command
|
||||
to proceed by automatically generating a unique name by appending a number
|
||||
to the conflicting name (e.g., if a submodule named 'child' exists, it will
|
||||
try 'child1', and so on).
|
||||
When running deinit the submodule working trees will be removed even
|
||||
if they contain local changes.
|
||||
When running update (only effective with the checkout procedure),
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "advice.h"
|
||||
#include "branch.h"
|
||||
#include "list-objects-filter-options.h"
|
||||
#include "wildmatch.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
#define OPT_QUIET (1 << 0)
|
||||
#define OPT_CACHED (1 << 1)
|
||||
@@ -3307,6 +3309,8 @@ static void configure_added_submodule(struct add_data *add_data)
|
||||
char *key;
|
||||
struct child_process add_submod = CHILD_PROCESS_INIT;
|
||||
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
|
||||
const struct string_list *values;
|
||||
int matched = 0;
|
||||
|
||||
key = xstrfmt("submodule.%s.url", add_data->sm_name);
|
||||
repo_config_set_gently(the_repository, key, add_data->realrepo);
|
||||
@@ -3349,20 +3353,28 @@ static void configure_added_submodule(struct add_data *add_data)
|
||||
* is_submodule_active(), since that function needs to find
|
||||
* out the value of "submodule.active" again anyway.
|
||||
*/
|
||||
if (!repo_config_get(the_repository, "submodule.active")) {
|
||||
if (repo_config_get(the_repository, "submodule.active") || /* key absent */
|
||||
repo_config_get_string_multi(the_repository, "submodule.active", &values)) {
|
||||
/*
|
||||
* If the submodule being added isn't already covered by the
|
||||
* current configured pathspec, set the submodule's active flag
|
||||
*/
|
||||
if (!is_submodule_active(the_repository, add_data->sm_path)) {
|
||||
key = xstrfmt("submodule.%s.active", add_data->sm_name);
|
||||
repo_config_set_gently(the_repository, key, "true");
|
||||
free(key);
|
||||
} else {
|
||||
for (size_t i = 0; i < values->nr; i++) {
|
||||
const char *pat = values->items[i].string;
|
||||
if (!wildmatch(pat, add_data->sm_path, 0)) { /* match found */
|
||||
matched = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched) { /* no pattern matched -> force-enable */
|
||||
key = xstrfmt("submodule.%s.active", add_data->sm_name);
|
||||
repo_config_set_gently(the_repository, key, "true");
|
||||
free(key);
|
||||
}
|
||||
} else {
|
||||
key = xstrfmt("submodule.%s.active", add_data->sm_name);
|
||||
repo_config_set_gently(the_repository, key, "true");
|
||||
free(key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3423,6 +3435,9 @@ static int module_add(int argc, const char **argv, const char *prefix,
|
||||
struct add_data add_data = ADD_DATA_INIT;
|
||||
const char *ref_storage_format = NULL;
|
||||
char *to_free = NULL;
|
||||
const struct submodule *existing;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
char *sm_name_to_free = NULL;
|
||||
struct option options[] = {
|
||||
OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
|
||||
N_("branch of repository to add as submodule")),
|
||||
@@ -3525,6 +3540,28 @@ static int module_add(int argc, const char **argv, const char *prefix,
|
||||
if(!add_data.sm_name)
|
||||
add_data.sm_name = add_data.sm_path;
|
||||
|
||||
existing = submodule_from_name(the_repository,
|
||||
null_oid(the_hash_algo),
|
||||
add_data.sm_name);
|
||||
|
||||
if (existing && strcmp(existing->path, add_data.sm_path)) {
|
||||
if (!force) {
|
||||
die(_("submodule name '%s' already used for path '%s'"),
|
||||
add_data.sm_name, existing->path);
|
||||
}
|
||||
/* --force: build <name><n> until unique */
|
||||
for (int i = 1; ; i++) {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "%s%d", add_data.sm_name, i);
|
||||
if (!submodule_from_name(the_repository,
|
||||
null_oid(the_hash_algo),
|
||||
buf.buf)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
add_data.sm_name = sm_name_to_free = strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
if (check_submodule_name(add_data.sm_name))
|
||||
die(_("'%s' is not a valid submodule name"), add_data.sm_name);
|
||||
|
||||
@@ -3540,6 +3577,7 @@ static int module_add(int argc, const char **argv, const char *prefix,
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
free(sm_name_to_free);
|
||||
free(add_data.sm_path);
|
||||
free(to_free);
|
||||
strbuf_release(&sb);
|
||||
|
||||
@@ -1482,4 +1482,27 @@ test_expect_success '`submodule init` and `init.templateDir`' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'submodule add fails when name is reused' '
|
||||
git init test-submodule &&
|
||||
(
|
||||
cd test-submodule &&
|
||||
git commit --allow-empty -m init &&
|
||||
|
||||
git init ../child-origin &&
|
||||
git -C ../child-origin commit --allow-empty -m init &&
|
||||
|
||||
git submodule add ../child-origin child &&
|
||||
git commit -m "Add submodule child" &&
|
||||
|
||||
git mv child child_old &&
|
||||
git commit -m "Move child to child_old" &&
|
||||
|
||||
# Now adding a *new* repo at the old name must fail
|
||||
git init ../child2-origin &&
|
||||
git -C ../child2-origin commit --allow-empty -m init &&
|
||||
test_must_fail git submodule add ../child2-origin child 2>err &&
|
||||
test_grep "already used for" err
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -124,4 +124,19 @@ test_expect_success 'is-active, submodule.active and submodule add' '
|
||||
git -C super2 config --get submodule.mod.active
|
||||
'
|
||||
|
||||
test_expect_success 'submodule add skips redundant active entry' '
|
||||
git init repo &&
|
||||
(
|
||||
cd repo &&
|
||||
git config submodule.active "lib/*" &&
|
||||
git commit --allow-empty -m init &&
|
||||
|
||||
git init ../lib-origin &&
|
||||
git -C ../lib-origin commit --allow-empty -m init &&
|
||||
|
||||
git submodule add ../lib-origin lib/foo &&
|
||||
test_must_fail git config --get submodule.lib/foo.active
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
Reference in New Issue
Block a user