git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 03/12] git rm: display a warning for every unremovable file

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Mar 27, 2010, 11:01 UTC
Message-ID
<20100327110147.GA1008@progeny.tock>
In-Reply-To
<1269617140-7827-4-git-send-email-peter@pcc.me.uk>
Peter Collingbourne wrote:
Show 5 quoted lines
> This patch causes git-rm to display a warning if it was unable to
> remove a file other than the first one, rather than silently ignoring
> the error, which was the previous behaviour.
> 
> Signed-off-by: Peter Collingbourne <peter@pcc.me.uk>
[...]
Show 6 quoted lines
> @@ -259,6 +259,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
>  			}
>  			if (!removed)
>  				die_errno("git rm: '%s'", path);
> +			else
> +				warning("git rm: '%s': %s", path, strerror(errno));

My first reaction was to wonder what is going on. Clearly someone had been bothered by the obvious behavior of giving a long stream of warnings or we wouldn’t have the current behavior.

But in fact, the unchanged code comment before the code you changed and the message for commit d9b814cc (Add builtin "git rm" command, 2006-05-19) shows me wrong:

    So what happens is that if the _first_ file fails to be removed with "-f", 
    we abort the whole "git rm". But once we've started removing, we don't 
    leave anything half done. If some of the other files don't exist, we'll 
    just ignore errors of removal from the working tree.
    This is only an issue with "-f", of course.
    I think the new behaviour is strictly an improvement, but perhaps more 
    importantly, it is _different_. As a special case, the semantics are 
    identical for the single-file case (which is the only one our test-suite 
    seems to test).
I think the commit message could avoid this confusion.  Something like:
	When ‘git rm’ was built in (d9b814cc, 2006-05-19), its
	semantics changed: before, it just removed files until it
	encountered an error and then would error out, whereas since
	then, it makes an attempt to either remove all files or remove
	none at all.  In particular, if ‘git rm’ fails to remove a
	file after other files have already been removed, it does not
	abort but instead silently accepts the error.
	Better to warn the user in this case!
	This problem is particularly noticeable when dealing with
	submodules because ...
Some tests would be nice as well --- maybe something like the following?
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 0aaf0ad..a3861b8 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -126,6 +126,75 @@ test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
 	git rm --ignore-unmatch nonexistent
 '
 
+test_expect_success 'If the first (in alphabetical order) removal fails, rm is cancelled' '
+	touch xyzzy &&
+	mkdir -p plugh &&
+	touch plugh/xyzzy &&
+	git add xyzzy plugh/xyzzy &&
+	git commit --allow-empty -a -m "two files to remove" &&
+	chmod a-w plugh &&
+	git ls-files --stage >before &&
+	test $(grep xyzzy before | wc -l) = 2 &&
+
+	test_must_fail git rm xyzzy plugh/xyzzy &&
+
+	test -e plugh/xyzzy &&
+	test -e xyzzy &&
+	git ls-files --stage >after &&
+	test_cmp before after
+'
+! test -e plugh || chmod 775 plugh
+rm -fr before after plugh xyzzy
+
+test_expect_success 'Best-effort behavior if the second removal fails' '
+	touch plugh &&
+	mkdir -p xyzzy &&
+	touch xyzzy/plugh &&
+	git add plugh xyzzy/plugh &&
+	git commit --allow-empty -a -m "two files to remove" &&
+	chmod a-w xyzzy &&
+	: >expect &&
+
+	git rm plugh xyzzy/plugh &&
+
+	test -e xyzzy/plugh &&
+	! test -e plugh &&
+	git ls-files --stage plugh xyzzy/plugh >actual &&
+	test_cmp expect actual
+'
+! test -e xyzzy || chmod 775 xyzzy
+rm -fr expect actual plugh xyzzy
+
+test_expect_success 'Message when first removal fails' '
+	touch xyzzy &&
+	mkdir -p plugh &&
+	touch plugh/xyzzy &&
+	git add xyzzy plugh/xyzzy &&
+	git commit --allow-empty -a -m "two files to remove" &&
+	chmod a-w plugh &&
+
+	test_must_fail git rm xyzzy plugh/xyzzy 2>msg &&
+
+	grep "git rm: '\''plugh/xyzzy'\'':" msg
+'
+! test -e plugh || chmod 775 plugh
+rm -fr msg plugh xyzzy
+
+test_expect_success 'Message when second removal fails' '
+	touch plugh &&
+	mkdir -p xyzzy &&
+	touch xyzzy/plugh &&
+	git add plugh xyzzy/plugh &&
+	git commit --allow-empty -a -m "two files to remove" &&
+	chmod a-w xyzzy &&
+
+	git rm plugh xyzzy/plugh 2>msg &&
+
+	grep "git rm: '\''xyzzy/plugh'\'':" msg
+'
+! test -e xyzzy || chmod 775 xyzzy
+rm -fr expect actual plugh xyzzy
+
 test_expect_success '"rm" command printed' '
 	echo frotz > test-file &&
 	git add test-file &&
Previous: Peter CollingbourneNext: Peter Collingbourne
Message 9 of 18 in “Improve handling of moving and removing submodules”
  1. 00/12 Improve handling of moving and removing submodulesPeter Collingbourne, Mar 26, 2010
  2. 01/12 Generate unique ID for submodules created using "git submodule add"Peter Collingbourne, Mar 26, 2010
  3. Jonathan NiederMar 27, 2010
  4. Peter CollingbourneApr 3, 2010
  5. 1/2 Prefix submodule names with the path basenamePeter Collingbourne, Apr 3, 2010
  6. 2/2 Truncate the SHA1 part of the submodule name to 7 charactersPeter Collingbourne, Apr 3, 2010
  7. 02/12 Implement "git mv" for submodulesPeter Collingbourne, Mar 26, 2010
  8. 03/12 git rm: display a warning for every unremovable filePeter Collingbourne, Mar 26, 2010
  9. Jonathan NiederMar 27, 2010
  10. 04/12 Generalise the unlink_or_warn functionPeter Collingbourne, Mar 26, 2010
  11. 05/12 Implement the rmdir_or_warn functionPeter Collingbourne, Mar 26, 2010
  12. 06/12 Introduce remove_or_warn functionPeter Collingbourne, Mar 26, 2010
  13. 07/12 Remove a redundant errno test in a usage of remove_pathPeter Collingbourne, Mar 26, 2010
  14. 08/12 git rm: collect file modesPeter Collingbourne, Mar 26, 2010
  15. 09/12 Add a mode parameter to the remove_path functionPeter Collingbourne, Mar 26, 2010
  16. 10/12 git rm: do not abort due to an initialised submodulePeter Collingbourne, Mar 26, 2010
  17. 11/12 git submodule: infrastructure for reading .gitmodules files in arbitrary locationsPeter Collingbourne, Mar 26, 2010
  18. 12/12 git rm: remove submodule entries from .gitmodulesPeter Collingbourne, Mar 26, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.