From: Petr Baudis <pasky@suse.cz>
To: git@vger.kernel.org
Cc: gitster@pobox.com
Subject: [PATCH 2/6] git rm: Support for removing submodules
Date: Fri, 12 Sep 2008 23:09:02 +0200 [thread overview]
Message-ID: <20080912210902.31628.7325.stgit@localhost> (raw)
In-Reply-To: <20080912210817.31628.69014.stgit@localhost>
This patch adds support for removing submodules to 'git rm', including
appropriately editing the .gitmodules file to reflect this. Submodule
_checkouts_ are never removed; that can be potentially catastrophic
and the user should remove them manually, if really desired.
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
Documentation/git-rm.txt | 6 +++-
builtin-rm.c | 65 ++++++++++++++++++++++++++++++++++++++--------
2 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index 5afb1e7..0c92687 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -20,7 +20,8 @@ and no updates to their contents can be staged in the index,
though that default behavior can be overridden with the `-f` option.
When '--cached' is given, the staged content has to
match either the tip of the branch or the file on disk,
-allowing the file to be removed from just the index.
+allowing the file to be removed from just the index;
+this is always the case when removing submodules.
OPTIONS
@@ -57,7 +58,8 @@ OPTIONS
--cached::
Use this option to unstage and remove paths only from the index.
Working tree files, whether modified or not, will be
- left alone.
+ left alone. Note that this is always assumed when removing
+ a checked-out submodule.
--ignore-unmatch::
Exit with a zero status even if no files matched.
diff --git a/builtin-rm.c b/builtin-rm.c
index 6bd8211..7475de2 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -9,6 +9,7 @@
#include "cache-tree.h"
#include "tree-walk.h"
#include "parse-options.h"
+#include "submodule.h"
static const char * const builtin_rm_usage[] = {
"git rm [options] [--] <file>...",
@@ -17,16 +18,21 @@ static const char * const builtin_rm_usage[] = {
static struct {
int nr, alloc;
- const char **name;
+ struct {
+ const char *name;
+ int is_gitlink;
+ } *info;
} list;
-static void add_list(const char *name)
+static void add_list(const char *name, int is_gitlink)
{
if (list.nr >= list.alloc) {
list.alloc = alloc_nr(list.alloc);
- list.name = xrealloc(list.name, list.alloc * sizeof(const char *));
+ list.info = xrealloc(list.info, list.alloc * sizeof(*list.info));
}
- list.name[list.nr++] = name;
+ list.info[list.nr].name = name;
+ list.info[list.nr].is_gitlink = is_gitlink;
+ list.nr++;
}
static int remove_file(const char *name)
@@ -38,6 +44,13 @@ static int remove_file(const char *name)
if (ret && errno == ENOENT)
/* The user has removed it from the filesystem by hand */
ret = errno = 0;
+ if (ret && errno == EISDIR) {
+ /* This is a gitlink entry; try to remove at least the
+ * directory if the submodule is not checked out; we always
+ * leave the checked out ones as they are */
+ if (!rmdir(name) || errno == ENOTEMPTY)
+ ret = errno = 0;
+ }
if (!ret && (slash = strrchr(name, '/'))) {
char *n = xstrdup(name);
@@ -65,7 +78,7 @@ static int check_local_mod(unsigned char *head, int index_only)
struct stat st;
int pos;
struct cache_entry *ce;
- const char *name = list.name[i];
+ const char *name = list.info[i].name;
unsigned char sha1[20];
unsigned mode;
int local_changes = 0;
@@ -83,7 +96,7 @@ static int check_local_mod(unsigned char *head, int index_only)
/* It already vanished from the working tree */
continue;
}
- else if (S_ISDIR(st.st_mode)) {
+ else if (S_ISDIR(st.st_mode) && !S_ISGITLINK(ce->ce_mode)) {
/* if a file was removed and it is now a
* directory, that is the same as ENOENT as
* far as git is concerned; we do not track
@@ -122,6 +135,22 @@ static int check_local_mod(unsigned char *head, int index_only)
return errs;
}
+static void remove_submodule(const char *name)
+{
+ char *key = submodule_by_path(name);
+ char *sectend = strrchr(key, '.');
+
+ assert(sectend);
+ *sectend = 0;
+
+ config_exclusive_filename = ".gitmodules";
+ if (git_config_rename_section(key, NULL) <= 0)
+ die("cannot remove section `%s' from .gitmodules", key);
+ config_exclusive_filename = NULL;
+
+ free(key);
+}
+
static struct lock_file lock_file;
static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
@@ -140,7 +169,7 @@ static struct option builtin_rm_options[] = {
int cmd_rm(int argc, const char **argv, const char *prefix)
{
- int i, newfd;
+ int i, newfd, subs;
const char **pathspec;
char *seen;
@@ -168,7 +197,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
struct cache_entry *ce = active_cache[i];
if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen))
continue;
- add_list(ce->name);
+ add_list(ce->name, S_ISGITLINK(ce->ce_mode));
}
if (pathspec) {
@@ -216,9 +245,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
* the index unless all of them succeed.
*/
for (i = 0; i < list.nr; i++) {
- const char *path = list.name[i];
+ const char *path = list.info[i].name;
if (!quiet)
- printf("rm '%s'\n", path);
+ printf("rm%s '%s'\n",
+ list.info[i].is_gitlink ? "dir" : "",
+ path);
if (remove_file_from_cache(path))
die("git rm: unable to remove %s", path);
@@ -238,7 +269,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (!index_only) {
int removed = 0;
for (i = 0; i < list.nr; i++) {
- const char *path = list.name[i];
+ const char *path = list.info[i].name;
if (!remove_file(path)) {
removed = 1;
continue;
@@ -248,6 +279,18 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
}
}
+ /*
+ * Get rid of stale submodule setup.
+ */
+ subs = 0;
+ for (i = 0; i < list.nr; i++)
+ if (list.info[i].is_gitlink) {
+ remove_submodule(list.info[i].name);
+ subs++;
+ }
+ if (subs && add_file_to_cache(".gitmodules", 0))
+ die("cannot add new .gitmodules to the index");
+
if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) ||
commit_locked_index(&lock_file))
next prev parent reply other threads:[~2008-09-12 21:10 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-12 21:08 [PATCH 0/6] Submodule support for git mv and git rm Petr Baudis
2008-09-12 21:08 ` [PATCH 1/6] submodule.*: Introduce simple C interface for submodule lookup by path Petr Baudis
2008-09-12 21:23 ` Junio C Hamano
2008-09-12 21:35 ` Jakub Narebski
2008-09-12 21:58 ` Petr Baudis
2008-09-12 21:09 ` Petr Baudis [this message]
2008-09-12 21:49 ` [PATCH 2/6] git rm: Support for removing submodules Junio C Hamano
2008-09-12 21:59 ` Junio C Hamano
2008-09-12 22:24 ` Petr Baudis
2008-09-12 22:42 ` Junio C Hamano
2008-09-12 21:09 ` [PATCH 3/6] git mv: Support moving submodules Petr Baudis
2008-09-12 21:42 ` [PATCH] " Petr Baudis
2008-09-12 22:19 ` Junio C Hamano
2008-09-12 21:09 ` [PATCH 4/6] t7403: Submodule git mv, git rm testsuite Petr Baudis
2008-09-12 21:09 ` [PATCH 5/6] t7400: Add short "git submodule add" testsuite Petr Baudis
2008-09-12 21:09 ` [PATCH 6/6] git submodule add: Fix naming clash handling Petr Baudis
2008-09-13 2:24 ` Junio C Hamano
2008-09-13 11:32 ` Lars Hjemli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080912210902.31628.7325.stgit@localhost \
--to=pasky@suse.cz \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.