git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH,RFC] Implement 'git rm --if-missing'
@ 2008-07-16 18:00 Ciaran McCreesh
  2008-07-16 18:06 ` Petr Baudis
  2008-07-16 18:48 ` Junio C Hamano
  0 siblings, 2 replies; 6+ messages in thread
From: Ciaran McCreesh @ 2008-07-16 18:00 UTC (permalink / raw)
  To: git; +Cc: Ciaran McCreesh

git rm --if-missing will only remove files if they've already been removed from
disk.

Signed-off-by: Ciaran McCreesh <ciaran.mccreesh@googlemail.com>
---

There's nothing here that can't be done using git update-index, but git rm
is less scary.

Regarding exit status: I'm not sure whether exit status should be based upon
whether any files were actually removed, or whether it should be based upon
whether or not all of the supplied patterns were matched. I've gone for the
latter, so that 'git rm --if-missing -r .' succeeds if there's nothing to
remove.

I'm not sure whether 'missing' is the best word. '--if-noent' might be more
appropriate, but less familiar to some. Or is this worth a short option?

 Documentation/git-rm.txt |    8 +++++++-
 builtin-rm.c             |    9 ++++++++-
 t/t3600-rm.sh            |   43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index 4d0c495..f9335f3 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -7,7 +7,8 @@ git-rm - Remove files from the working tree and from the index
 
 SYNOPSIS
 --------
-'git rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
+'git rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--if-missing]
+	  [--quiet] [--] <file>...
 
 DESCRIPTION
 -----------
@@ -61,6 +62,11 @@ OPTIONS
 --ignore-unmatch::
 	Exit with a zero status even if no files matched.
 
+--if-missing::
+	Only remove files if they have been removed from disk. Exit status
+	is still based upon whether matches succeed, not whether a remove
+	actually took place.
+
 -q::
 --quiet::
 	'git-rm' normally outputs one line (in the form of an "rm" command)
diff --git a/builtin-rm.c b/builtin-rm.c
index 22c9bd1..4b89705 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -125,7 +125,7 @@ static int check_local_mod(unsigned char *head, int index_only)
 static struct lock_file lock_file;
 
 static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
-static int ignore_unmatch = 0;
+static int ignore_unmatch = 0, if_missing = 0;
 
 static struct option builtin_rm_options[] = {
 	OPT__DRY_RUN(&show_only),
@@ -135,6 +135,7 @@ static struct option builtin_rm_options[] = {
 	OPT_BOOLEAN('r', NULL,             &recursive,  "allow recursive removal"),
 	OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
 				"exit with a zero status even if nothing matched"),
+	OPT_BOOLEAN( 0 , "if-missing",     &if_missing, "only remove missing files"),
 	OPT_END(),
 };
 
@@ -168,6 +169,12 @@ 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;
+		if (if_missing)
+		{
+			struct stat st;
+			if ((lstat(ce->name, &st) == 0) || (errno != ENOENT))
+				continue;
+		}
 		add_list(ce->name);
 	}
 
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index f542f0a..c7c1810 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -143,6 +143,45 @@ test_expect_success '"rm" command suppressed with --quiet' '
 	git commit -m "remove file from rm --quiet test"
 '
 
+test_expect_success 'Test that "rm --if-missing" works' '
+	echo frotz > test-file &&
+	echo frotz > other-file &&
+	git add test-file other-file &&
+	git commit -m "add files from rm --if-missing test" &&
+	rm test-file &&
+	git rm --if-missing test-file other-file &&
+	! git ls-files --error-unmatch test-file &&
+	git ls-files --error-unmatch other-file &&
+	git rm other-file &&
+	git commit -m "remove file from rm --if-missing test"
+'
+
+test_expect_success 'Test that "rm --if-missing -r *" works' '
+	echo frotz > test-file &&
+	mkdir -p frotz &&
+	echo frotz > frotz/other-file &&
+	git add test-file frotz/other-file &&
+	git commit -m "add file from rm --if-missing -r * test" &&
+	rm frotz/other-file
+	git rm --if-missing --ignore-unmatch -r \* &&
+	git ls-files --error-unmatch test-file &&
+	git rm test-file &&
+	git commit -m "remove file from rm --missing -r * test &&
+	! test -d frotz"
+'
+
+test_expect_success 'Test that "rm --if-missing -r *" works even if nothing is removed' '
+	echo frotz > test-file &&
+	mkdir -p frotz &&
+	echo frotz > frotz/other-file &&
+	git add test-file frotz/other-file &&
+	git commit -m "add file from rm --if-missing -r * test" &&
+	git rm --if-missing --ignore-unmatch -r \* &&
+	git rm test-file frotz/other-file &&
+	git commit -m "remove file from rm --missing -r * test &&
+	! test -d frotz"
+'
+
 # Now, failure cases.
 test_expect_success 'Re-add foo and baz' '
 	git add foo baz &&
@@ -217,4 +256,8 @@ test_expect_success 'Remove nonexistent file returns nonzero exit status' '
 	! git rm nonexistent
 '
 
+test_expect_success 'Test that "rm --if-missing nonexistent" fails' '
+	! git rm --if-missing nonexistent
+'
+
 test_done
-- 
1.5.6.3.385.g7c3f1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-07-16 20:14 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-16 18:00 [PATCH,RFC] Implement 'git rm --if-missing' Ciaran McCreesh
2008-07-16 18:06 ` Petr Baudis
2008-07-16 18:17   ` Avery Pennarun
2008-07-16 18:48 ` Junio C Hamano
2008-07-16 18:58   ` Peter Baumann
2008-07-16 19:43     ` David Christensen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).