summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Lehmann <Jens.Lehmann@web.de>2012-06-19 20:55:45 +0200
committerJunio C Hamano <gitster@pobox.com>2013-12-26 11:59:04 -0800
commit500aa5eaf58530961b77590d9844a3857fcff5d2 (patch)
treeddc3cbfad41570abd114bf17223aa3a990d20f4d
parent1962f06493f17eeef4c30d08d87e92bf092f334e (diff)
downloadgit-500aa5eaf58530961b77590d9844a3857fcff5d2.tar.gz
submodule: teach unpack_trees() to remove submodule contents
Implement the functionality needed to enable work tree manipulating commands to that a deleted submodule should not only affect the index (leaving all the files of the submodule in the work tree) but also to remove the work tree of the superproject (including any untracked files). That will only work properly when the submodule uses a gitfile instead of a .git directory and no untracked files are present. Otherwise the removal will fail with a warning (which is just what happened until now). Extend rmdir_or_warn() to remove the directories of those submodules which are scheduled for removal. Also teach verify_clean_submodule() to check that a submodule configured to be removed is not modified before scheduling it for removal. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--submodule.c37
-rw-r--r--submodule.h1
-rw-r--r--unpack-trees.c6
-rw-r--r--wrapper.c3
4 files changed, 44 insertions, 3 deletions
diff --git a/submodule.c b/submodule.c
index 3f18d4d752..a25db46784 100644
--- a/submodule.c
+++ b/submodule.c
@@ -412,6 +412,43 @@ int submodule_needs_update(const char *path)
return config_update_recurse_submodules != RECURSE_SUBMODULES_OFF;
}
+int depopulate_submodule(const char *path)
+{
+ struct strbuf dot_git = STRBUF_INIT;
+ struct child_process cp;
+ const char *argv[] = {"rm", "-rf", path, NULL};
+
+ /* Is it populated? */
+ strbuf_addf(&dot_git, "%s/.git", path);
+ if (!resolve_gitdir(dot_git.buf)) {
+ strbuf_release(&dot_git);
+ return 0;
+ }
+ strbuf_release(&dot_git);
+
+ /* Does it have a .git directory? */
+ if (!submodule_uses_gitfile(path)) {
+ warning(_("cannot remove submodule '%s' because it (or one of "
+ "its nested submodules) uses a .git directory"),
+ path);
+ return -1;
+ }
+
+ /* Remove the whole submodule directory */
+ memset(&cp, 0, sizeof(cp));
+ cp.argv = argv;
+ cp.env = local_repo_env;
+ cp.git_cmd = 0;
+ cp.no_stdin = 1;
+ if (run_command(&cp)) {
+ warning("Could not remove submodule %s", path);
+ strbuf_release(&dot_git);
+ return -1;
+ }
+
+ return 0;
+}
+
void show_submodule_summary(FILE *f, const char *path,
const char *line_prefix,
unsigned char one[20], unsigned char two[20],
diff --git a/submodule.h b/submodule.h
index 055918c061..df291cf83d 100644
--- a/submodule.h
+++ b/submodule.h
@@ -24,6 +24,7 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
int submodule_needs_update(const char *path);
+int depopulate_submodule(const char *path);
void show_submodule_summary(FILE *f, const char *path,
const char *line_prefix,
unsigned char one[20], unsigned char two[20],
diff --git a/unpack-trees.c b/unpack-trees.c
index ad3e9a04fe..89b506a45b 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -8,6 +8,7 @@
#include "progress.h"
#include "refs.h"
#include "attr.h"
+#include "submodule.h"
/*
* Error messages expected by scripts out of plumbing commands such as
@@ -1263,14 +1264,13 @@ static void invalidate_ce_path(const struct cache_entry *ce,
/*
* Check that checking out ce->sha1 in subdir ce->name is not
* going to overwrite any working files.
- *
- * Currently, git does not checkout subprojects during a superproject
- * checkout, so it is not going to overwrite anything.
*/
static int verify_clean_submodule(const struct cache_entry *ce,
enum unpack_trees_error_types error_type,
struct unpack_trees_options *o)
{
+ if (submodule_needs_update(ce->name) && is_submodule_modified(ce->name, 0))
+ return 1;
return 0;
}
diff --git a/wrapper.c b/wrapper.c
index 0cc56368bd..425a3fd08b 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -2,6 +2,7 @@
* Various trivial helper wrappers around standard functions
*/
#include "cache.h"
+#include "submodule.h"
static void do_nothing(size_t size)
{
@@ -409,6 +410,8 @@ int unlink_or_warn(const char *file)
int rmdir_or_warn(const char *file)
{
+ if (submodule_needs_update(file) && depopulate_submodule(file))
+ return -1;
return warn_if_unremovable("rmdir", file, rmdir(file));
}