Merge branch 'sb/submodule-rm-absorb'
"git rm" used to refuse to remove a submodule when it has its own git repository embedded in its working tree. It learned to move the repository away to $GIT_DIR/modules/ of the superproject instead, and allow the submodule to be deleted (as long as there will be no loss of local modifications, that is). * sb/submodule-rm-absorb: rm: absorb a submodules git dir before deletion submodule: rename and add flags to ok_to_remove_submodule submodule: modernize ok_to_remove_submodule to use argv_array submodule.h: add extern keyword to functions
This commit is contained in:
84
builtin/rm.c
84
builtin/rm.c
@ -59,27 +59,9 @@ static void print_error_files(struct string_list *files_list,
|
||||
}
|
||||
}
|
||||
|
||||
static void error_removing_concrete_submodules(struct string_list *files, int *errs)
|
||||
{
|
||||
print_error_files(files,
|
||||
Q_("the following submodule (or one of its nested "
|
||||
"submodules)\n"
|
||||
"uses a .git directory:",
|
||||
"the following submodules (or one of their nested "
|
||||
"submodules)\n"
|
||||
"use a .git directory:", files->nr),
|
||||
_("\n(use 'rm -rf' if you really want to remove "
|
||||
"it including all of its history)"),
|
||||
errs);
|
||||
string_list_clear(files, 0);
|
||||
}
|
||||
|
||||
static int check_submodules_use_gitfiles(void)
|
||||
static void submodules_absorb_gitdir_if_needed(const char *prefix)
|
||||
{
|
||||
int i;
|
||||
int errs = 0;
|
||||
struct string_list files = STRING_LIST_INIT_NODUP;
|
||||
|
||||
for (i = 0; i < list.nr; i++) {
|
||||
const char *name = list.entry[i].name;
|
||||
int pos;
|
||||
@ -99,12 +81,9 @@ static int check_submodules_use_gitfiles(void)
|
||||
continue;
|
||||
|
||||
if (!submodule_uses_gitfile(name))
|
||||
string_list_append(&files, name);
|
||||
absorb_git_dir_into_superproject(prefix, name,
|
||||
ABSORB_GITDIR_RECURSE_SUBMODULES);
|
||||
}
|
||||
|
||||
error_removing_concrete_submodules(&files, &errs);
|
||||
|
||||
return errs;
|
||||
}
|
||||
|
||||
static int check_local_mod(struct object_id *head, int index_only)
|
||||
@ -120,7 +99,6 @@ static int check_local_mod(struct object_id *head, int index_only)
|
||||
int errs = 0;
|
||||
struct string_list files_staged = STRING_LIST_INIT_NODUP;
|
||||
struct string_list files_cached = STRING_LIST_INIT_NODUP;
|
||||
struct string_list files_submodule = STRING_LIST_INIT_NODUP;
|
||||
struct string_list files_local = STRING_LIST_INIT_NODUP;
|
||||
|
||||
no_head = is_null_oid(head);
|
||||
@ -187,7 +165,9 @@ static int check_local_mod(struct object_id *head, int index_only)
|
||||
*/
|
||||
if (ce_match_stat(ce, &st, 0) ||
|
||||
(S_ISGITLINK(ce->ce_mode) &&
|
||||
!ok_to_remove_submodule(ce->name)))
|
||||
bad_to_remove_submodule(ce->name,
|
||||
SUBMODULE_REMOVAL_DIE_ON_ERROR |
|
||||
SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED)))
|
||||
local_changes = 1;
|
||||
|
||||
/*
|
||||
@ -217,13 +197,8 @@ static int check_local_mod(struct object_id *head, int index_only)
|
||||
else if (!index_only) {
|
||||
if (staged_changes)
|
||||
string_list_append(&files_cached, name);
|
||||
if (local_changes) {
|
||||
if (S_ISGITLINK(ce->ce_mode) &&
|
||||
!submodule_uses_gitfile(name))
|
||||
string_list_append(&files_submodule, name);
|
||||
else
|
||||
string_list_append(&files_local, name);
|
||||
}
|
||||
if (local_changes)
|
||||
string_list_append(&files_local, name);
|
||||
}
|
||||
}
|
||||
print_error_files(&files_staged,
|
||||
@ -245,8 +220,6 @@ static int check_local_mod(struct object_id *head, int index_only)
|
||||
&errs);
|
||||
string_list_clear(&files_cached, 0);
|
||||
|
||||
error_removing_concrete_submodules(&files_submodule, &errs);
|
||||
|
||||
print_error_files(&files_local,
|
||||
Q_("the following file has local modifications:",
|
||||
"the following files have local modifications:",
|
||||
@ -340,6 +313,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!index_only)
|
||||
submodules_absorb_gitdir_if_needed(prefix);
|
||||
|
||||
/*
|
||||
* If not forced, the file, the index and the HEAD (if exists)
|
||||
* must match; but the file can already been removed, since
|
||||
@ -356,9 +332,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
oidclr(&oid);
|
||||
if (check_local_mod(&oid, index_only))
|
||||
exit(1);
|
||||
} else if (!index_only) {
|
||||
if (check_submodules_use_gitfiles())
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -387,32 +360,20 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
*/
|
||||
if (!index_only) {
|
||||
int removed = 0, gitmodules_modified = 0;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
for (i = 0; i < list.nr; i++) {
|
||||
const char *path = list.entry[i].name;
|
||||
if (list.entry[i].is_submodule) {
|
||||
if (is_empty_dir(path)) {
|
||||
if (!rmdir(path)) {
|
||||
removed = 1;
|
||||
if (!remove_path_from_gitmodules(path))
|
||||
gitmodules_modified = 1;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addstr(&buf, path);
|
||||
if (!remove_dir_recursively(&buf, 0)) {
|
||||
removed = 1;
|
||||
if (!remove_path_from_gitmodules(path))
|
||||
gitmodules_modified = 1;
|
||||
strbuf_release(&buf);
|
||||
continue;
|
||||
} else if (!file_exists(path))
|
||||
/* Submodule was removed by user */
|
||||
if (!remove_path_from_gitmodules(path))
|
||||
gitmodules_modified = 1;
|
||||
/* Fallthrough and let remove_path() fail. */
|
||||
}
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
strbuf_addstr(&buf, path);
|
||||
if (remove_dir_recursively(&buf, 0))
|
||||
die(_("could not remove '%s'"), path);
|
||||
strbuf_release(&buf);
|
||||
|
||||
removed = 1;
|
||||
if (!remove_path_from_gitmodules(path))
|
||||
gitmodules_modified = 1;
|
||||
continue;
|
||||
}
|
||||
if (!remove_path(path)) {
|
||||
removed = 1;
|
||||
@ -421,7 +382,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
if (!removed)
|
||||
die_errno("git rm: '%s'", path);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
if (gitmodules_modified)
|
||||
stage_updated_gitmodules();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user