git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Jonathan Nieder" <jrnieder@gmail.com>,
	"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
	"SZEDER Gábor" <szeder.dev@gmail.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH v2] test-lib.sh: try to re-chmod & retry on failed trash removal
Date: Mon, 11 Oct 2021 03:41:59 +0200	[thread overview]
Message-ID: <patch-v2-1.1-9cfc0621067-20211011T014059Z-avarab@gmail.com> (raw)
In-Reply-To: <patch-1.1-d7e88a77fef-20211009T133043Z-avarab@gmail.com>

Try to re-chmod the trash directory on startup if we fail to "rm -rf"
it. This fixes problems where the test leaves the trash directory
behind in a bad permission state for whatever reason.

This fixes an interaction between [1] where t0004-unwritable.sh was
made to use "test_when_finished" for cleanup, and [2] which added the
"--immediate" mode. If a test in this file failed when running with
"--immediate" we wouldn't run the "test_when_finished" block, which
re-chmods the ".git/objects" directory (see [1]).

This can be demonstrated as e.g. (output snipped for less verbosity):

    $ ./t0004-unwritable.sh --run=3 --immediate
    ok 1 # skip setup (--run)
    ok 2 # skip write-tree should notice unwritable repository (--run)
    not ok 3 - commit should notice unwritable repository
    [...]
    $ ./t0004-unwritable.sh --run=3 --immediate
    rm: cannot remove '[...]/trash directory.t0004-unwritable/.git/objects/info': Permission denied
    FATAL: Cannot prepare test area
    [...]

Instead of some version of reverting [1] let's make the test-lib.sh
resilient to this edge-case, it will happen due to [1], but also
e.g. if the relevant "test-lib.sh" process is kill -9'd during the
test run. We should try harder to recover in this case. If we fail to
remove the test directory let's retry after (re-)chmod-ing it.

This doesn't need to be guarded by something that's equivalent to
"POSIXPERM" since if we don't support "chmod" we were about to fail
anyway.

Let's also discard any error output from (a possibly nonexisting)
"chmod", we'll fail on the subsequent "rm -rf" anyway, likewise for
the first "rm -rf" invocation, we don't want to get the "cannot
remove" output if we can get around it with the "chmod", but we do
want any error output from the second "rm -rf", in case that doesn't
fix the issue.

The lack of &&-chaining between the "chmod" and "rm -rf" is
intentional, if we fail the first "rm -rf", can't chmod, but then
succeed the second time around that's what we were hoping for. We just
want to nuke the directory, not carry forward every possible error
code or error message.

1. dbda967684d (t0004 (unwritable files): simplify error handling,
   2010-09-06)
2. b586744a864 (test: skip clean-up when running under --immediate
   mode, 2011-06-27)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
Range-diff against v1:
1:  d7e88a77fef ! 1:  9cfc0621067 test-lib.sh: try to re-chmod & retry on failed trash removal
    @@ Metadata
      ## Commit message ##
         test-lib.sh: try to re-chmod & retry on failed trash removal
     
    -    This fixes a regression in [1] where t0004-unwritable.sh was made to
    -    use "test_when_finished" for cleanup, we wouldn't re-chmod the
    -    ".git/objects" on failure, leading to a persistent error when running
    -    the test.
    +    Try to re-chmod the trash directory on startup if we fail to "rm -rf"
    +    it. This fixes problems where the test leaves the trash directory
    +    behind in a bad permission state for whatever reason.
    +
    +    This fixes an interaction between [1] where t0004-unwritable.sh was
    +    made to use "test_when_finished" for cleanup, and [2] which added the
    +    "--immediate" mode. If a test in this file failed when running with
    +    "--immediate" we wouldn't run the "test_when_finished" block, which
    +    re-chmods the ".git/objects" directory (see [1]).
     
         This can be demonstrated as e.g. (output snipped for less verbosity):
     
    @@ Commit message
             FATAL: Cannot prepare test area
             [...]
     
    -    I.e. if any of its tests failed, and the tests were being run under
    -    "--debug"[2] or "--immediate"[3] (which was introduced after [1]) we
    -    wouldn't re-chmod the object directory. We'd then fail on the next run
    -    since the test setup couldn't remove the trash files.
    -
         Instead of some version of reverting [1] let's make the test-lib.sh
         resilient to this edge-case, it will happen due to [1], but also
         e.g. if the relevant "test-lib.sh" process is kill -9'd during the
    @@ Commit message
     
         This doesn't need to be guarded by something that's equivalent to
         "POSIXPERM" since if we don't support "chmod" we were about to fail
    -    anyway. Let's also discard any error output from (a possibly
    -    nonexisting) "chmod", we'll fail on the subsequent "rm -rf"
         anyway.
     
    +    Let's also discard any error output from (a possibly nonexisting)
    +    "chmod", we'll fail on the subsequent "rm -rf" anyway, likewise for
    +    the first "rm -rf" invocation, we don't want to get the "cannot
    +    remove" output if we can get around it with the "chmod", but we do
    +    want any error output from the second "rm -rf", in case that doesn't
    +    fix the issue.
    +
         The lack of &&-chaining between the "chmod" and "rm -rf" is
         intentional, if we fail the first "rm -rf", can't chmod, but then
         succeed the second time around that's what we were hoping for. We just
    @@ Commit message
     
         1. dbda967684d (t0004 (unwritable files): simplify error handling,
            2010-09-06)
    -    2. 5a4a088add3 (test-lib: do not remove trash_directory if called with
    -       --debug, 2008-08-21)
    -    3. b586744a864 (test: skip clean-up when running under --immediate
    +    2. b586744a864 (test: skip clean-up when running under --immediate
            mode, 2011-06-27)
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## t/test-lib.sh ##
    -@@ t/test-lib.sh: test_done () {
    - 			error "Tests passed but trash directory already removed before test cleanup; aborting"
    - 
    - 			cd "$TRASH_DIRECTORY/.." &&
    --			rm -fr "$TRASH_DIRECTORY" || {
    -+			remove_trash_directory "$TRASH_DIRECTORY" || {
    - 				# try again in a bit
    - 				sleep 5;
    --				rm -fr "$TRASH_DIRECTORY"
    -+				remove_trash_directory "$TRASH_DIRECTORY"
    - 			} ||
    - 			error "Tests passed but test cleanup failed; aborting"
    - 		fi
    -@@ t/test-lib.sh: then
    - 	exit 1
    - fi
    +@@ t/test-lib.sh: HOME="$TRASH_DIRECTORY"
    + GNUPGHOME="$HOME/gnupg-home-not-used"
    + export HOME GNUPGHOME USER_HOME
      
    -+# Try really hard to clean up our mess
    ++# "rm -rf" existing trash directory, even if a previous run left it
    ++# with bad permissions.
     +remove_trash_directory() {
     +	dir="$1"
    -+	if ! rm -rf "$dir"
    ++	if ! rm -rf "$dir" 2>/dev/null
     +	then
    -+		say_color info >&3 "Failed to remove trash directory, trying to re-chmod it first..."
    -+		chmod -R u+w "$dir" 2>/dev/null
    ++		chmod -R u+wx "$dir"
     +		rm -rf "$dir"
     +	fi
     +	! test -d "$dir"
     +}
     +
    - # Are we running this test at all?
    - remove_trash=
    - this_test=${0##*/}
    -@@ t/test-lib.sh: GNUPGHOME="$HOME/gnupg-home-not-used"
    - export HOME GNUPGHOME USER_HOME
    - 
      # Test repository
     -rm -fr "$TRASH_DIRECTORY" || {
     +remove_trash_directory "$TRASH_DIRECTORY" || {

 t/test-lib.sh | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index aa1ad8180ed..ff6d3c79362 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1387,8 +1387,20 @@ HOME="$TRASH_DIRECTORY"
 GNUPGHOME="$HOME/gnupg-home-not-used"
 export HOME GNUPGHOME USER_HOME
 
+# "rm -rf" existing trash directory, even if a previous run left it
+# with bad permissions.
+remove_trash_directory() {
+	dir="$1"
+	if ! rm -rf "$dir" 2>/dev/null
+	then
+		chmod -R u+wx "$dir"
+		rm -rf "$dir"
+	fi
+	! test -d "$dir"
+}
+
 # Test repository
-rm -fr "$TRASH_DIRECTORY" || {
+remove_trash_directory "$TRASH_DIRECTORY" || {
 	GIT_EXIT_OK=t
 	echo >&5 "FATAL: Cannot prepare test area"
 	exit 1
-- 
2.33.0.1505.g38ce83107ad


  parent reply	other threads:[~2021-10-11  1:42 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-09 13:31 [PATCH] test-lib.sh: try to re-chmod & retry on failed trash removal Ævar Arnfjörð Bjarmason
2021-10-10 21:36 ` SZEDER Gábor
2021-10-10 22:14 ` Junio C Hamano
2021-10-11  4:34   ` Junio C Hamano
2021-10-11  1:41 ` Ævar Arnfjörð Bjarmason [this message]
2021-10-12 23:03   ` [PATCH v2] " Junio C Hamano

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=patch-v2-1.1-9cfc0621067-20211011T014059Z-avarab@gmail.com \
    --to=avarab@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jrnieder@gmail.com \
    --cc=szeder.dev@gmail.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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).