{"thread":{"id":"65734","subject":"[PATCH 0/4] t: fix broken TAP output","startedAt":"2026-06-02T08:54:34Z","lastAt":"2026-06-09T01:22:38Z","messageCount":18,"participants":["Patrick Steinhardt","Junio C Hamano","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"544473","messageId":"20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im","threadId":"65734","inReplyTo":null,"subject":"[PATCH 0/4] t: fix broken TAP output","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-02T08:54:26Z","receivedAt":"2026-06-02T08:54:34Z","isPatch":true,"body":"Hi,\n\nthis small patch series fixes another instance of broken TAP output that\nhas landed via 4d11b9c218 (Merge branch 'pt/fsmonitor-linux', 2026-05-31).\n\nAs this has happened multiple times by now I decided to have a look at\nwhether we can fix this class of issues a bit more holistically. So this\nseries also contains a change that makes prove bail out when it sees\ninvalid TAP output, which uncovers a small set of preexisting issues in\nour test suite.\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (4):\n      t7527: fix broken TAP output\n      t/test-lib: silence EBUSY errors on Windows during test cleanup\n      t/lib-git-p4: silence output when killing p4d and its watchdog\n      t: let prove fail when parsing invalid TAP output\n\n t/lib-git-p4.sh              |  3 ++-\n t/t7527-builtin-fsmonitor.sh |  7 ++++---\n t/test-lib.sh                | 10 ++++++++--\n 3 files changed, 14 insertions(+), 6 deletions(-)\n\n\n---\nbase-commit: 1666c1265231b0bc5f613fbbf3f0a9896cdef76e\nchange-id: 20260601-pks-t7527-fix-tap-output-105da1d73df0\n\n"},{"id":"544474","messageId":"20260602-pks-t7527-fix-tap-output-v1-1-db3da2a1b137@pks.im","threadId":"65734","inReplyTo":"20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im","subject":"[PATCH 1/4] t7527: fix broken TAP output","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-02T08:54:27Z","receivedAt":"2026-06-02T08:54:34Z","isPatch":true,"body":"Before running the tests in t7527 we first verify whether the fsmonitor\neven works, which seems to depend on the actual filesystem that is in\nuse. The verification executes outside of any prerequisite or test body,\nso its stdout/stderr is not being redirected.\n\nThe consequence of this is that any command that prints to stdout/stderr\nmay break the TAP specification by printing invalid lines. And in fact\nwe already do that, as git-init(1) prints the path to the created Git\nrepository by default.\n\nFix this issue by moving the logic into a lazy prerequisite.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/t7527-builtin-fsmonitor.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh\nindex b63c162f9b..d881e27466 100755\n--- a/t/t7527-builtin-fsmonitor.sh\n+++ b/t/t7527-builtin-fsmonitor.sh\n@@ -25,7 +25,8 @@ maybe_timeout () {\n \t\t\"$@\"\n \tfi\n }\n-verify_fsmonitor_works () {\n+\n+test_lazy_prereq FSMONITOR_WORKS '\n \tgit init test_fsmonitor_smoke || return 1\n \n \tGIT_TRACE_FSMONITOR=\"$PWD/smoke.trace\" &&\n@@ -50,9 +51,9 @@ verify_fsmonitor_works () {\n \tret=$?\n \trm -rf test_fsmonitor_smoke smoke.trace\n \treturn $ret\n-}\n+'\n \n-if ! verify_fsmonitor_works\n+if ! test_have_prereq FSMONITOR_WORKS\n then\n \tskip_all=\"filesystem does not deliver fsmonitor events (container/overlayfs?)\"\n \ttest_done\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544475","messageId":"20260602-pks-t7527-fix-tap-output-v1-2-db3da2a1b137@pks.im","threadId":"65734","inReplyTo":"20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im","subject":"[PATCH 2/4] t/test-lib: silence EBUSY errors on Windows during test cleanup","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-02T08:54:28Z","receivedAt":"2026-06-02T08:54:37Z","isPatch":true,"body":"When tests have finished we clean up the trash directory via `rm -rf`.\nOn Windows this can fail with EBUSY in cases where a process still holds\nsome of the files open, for example when we have spawned a daemonized\nprocess that wasn't properly terminated. We thus retry several times,\nbut every failure will result in error messages being printed, and that\nin turn breaks the TAP output format.\n\nOne such case where this is causing issues is in t921x, which contains\ntests related to Scalar. Some tests spawn the fsmonitor daemon, and we\nnever properly terminate it.\n\nThe obvious fix would be to ensure that we never leak any processes, but\nthat gets ugly fast. Instead, let's work around the issue by silencing\nerror messages printed by the `rm -rf` calls. We already know to print\nan error when the retry loop fails, so we don't loose much.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/test-lib.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 4a7357b547..d1d24c4124 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -1299,10 +1299,10 @@ test_done () {\n \t\t\terror \"Tests passed but trash directory already removed before test cleanup; aborting\"\n \n \t\t\tcd \"$TRASH_DIRECTORY/..\" &&\n-\t\t\trm -fr \"$TRASH_DIRECTORY\" || {\n+\t\t\trm -fr \"$TRASH_DIRECTORY\" 2>/dev/null || {\n \t\t\t\t# try again in a bit\n \t\t\t\tsleep 5;\n-\t\t\t\trm -fr \"$TRASH_DIRECTORY\"\n+\t\t\t\trm -fr \"$TRASH_DIRECTORY\" 2>/dev/null\n \t\t\t} ||\n \t\t\terror \"Tests passed but test cleanup failed; aborting\"\n \t\tfi\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544476","messageId":"20260602-pks-t7527-fix-tap-output-v1-3-db3da2a1b137@pks.im","threadId":"65734","inReplyTo":"20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im","subject":"[PATCH 3/4] t/lib-git-p4: silence output when killing p4d and its watchdog","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-02T08:54:29Z","receivedAt":"2026-06-02T08:54:39Z","isPatch":true,"body":"When stopping the p4d watchdog process via \"kill -9\", the shell may\nprint a job-control notification like:\n\n  ./test-lib.sh: line 1269: 57960 Killed: 9               while true; do\n      if test $nr_tries_left -eq 0; then\n          kill -9 $p4d_pid; exit 1;\n      fi; sleep 1; nr_tries_left=$(($nr_tries_left - 1));\n  done 2> /dev/null 4>&2  (wd: ~)\n\nThis message is printed asynchronously by the shell when it reaps the\nprocess. While harmless right now, this will cause breakage once we\nenable strict parsing of the TAP protocol in a subsequent commit.\n\nFix this by using `wait` so that we can synchronously reap the watchdog\nprocess and swallow the diagnostic.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/lib-git-p4.sh | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh\nindex d22e9c684a..0afa5111ab 100644\n--- a/t/lib-git-p4.sh\n+++ b/t/lib-git-p4.sh\n@@ -65,6 +65,7 @@ pidfile=\"$TRASH_DIRECTORY/p4d.pid\"\n \n stop_p4d_and_watchdog () {\n \tkill -9 $p4d_pid $watchdog_pid\n+\twait $p4d $watchdog_pid 2>/dev/null\n }\n \n # git p4 submit generates a temp file, which will\n@@ -175,7 +176,7 @@ retry_until_success () {\n \n stop_and_cleanup_p4d () {\n \tkill -9 $p4d_pid $watchdog_pid\n-\twait $p4d_pid\n+\twait $p4d_pid $watchdog_pid 2>/dev/null\n \trm -rf \"$db\" \"$cli\" \"$pidfile\"\n }\n \n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544477","messageId":"20260602-pks-t7527-fix-tap-output-v1-4-db3da2a1b137@pks.im","threadId":"65734","inReplyTo":"20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im","subject":"[PATCH 4/4] t: let prove fail when parsing invalid TAP output","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-02T08:54:30Z","receivedAt":"2026-06-02T08:54:42Z","isPatch":true,"body":"To make the result of our tests accessible we use the TAP protocol. This\nprotocol is parsed by either prove or by Meson. Unfortunately, these two\ntools differ when it comes to their strictness when parsing the\nprotocol:\n\n  - Prove by default happily accepts lines not specified by the\n    protocol.\n\n  - Meson will also accept such lines, but prints a big and ugly warning\n    message.\n\nWe have fixed our test suite in the past to not print invalid TAP lines\nanymore via b1dc2e796e (Merge branch 'ps/meson-tap-parse', 2025-06-17).\nBut as none of our tools perform a strict check it's still possible for\nbroken tests to sneak back in, like for example in 362f69547f (Merge\nbranch 'ps/t1006-tap-fix', 2025-07-16). This doesn't hurt at all when\nusing prove, but it's quite annoying when using Meson due to the\ngenerated warnings.\n\nUnfortunately, there doesn't seem to be a portable way to make all tools\ncomplain about violations of the TAP format. The TAP 14 specification\nhas added pragmas to the protocol that would allow us to say `pragma\n+strict`, and the effect of that would be to treat invalid TAP lines as\na test failure. But the release of TAP 14 is still rather recent, and\nTest-Harness for example only gained support for it in version 3.48,\nwhich was released in 2023.\n\nIn fact though, this pragma was already introduced as an inofficial\nextension of the TAP protocol with Test-Harness 3.10, released in 2008.\nSo while not all tools understand the pragma, at least prove does for a\nlong time.\n\nUnconditionally enable the pragma when using prove so that we'll detect\ntests that emit broken TAP output right away. This would have detected\nthe issues fixed in preceding commits:\n\n    $ prove t7527-builtin-fsmonitor.sh\n    t7527-builtin-fsmonitor.sh .. All 69 subtests passed\n            (less 6 skipped subtests: 63 okay)\n\n    Test Summary Report\n    -------------------\n    t7527-builtin-fsmonitor.sh (Wstat: 0 Tests: 69 Failed: 0)\n      Parse errors: Unknown TAP token: \"Initialized empty Git repository in /tmp/git/test_fsmonitor_smoke/.git/\"\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/test-lib.sh | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex d1d24c4124..ceefb99bff 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -1532,6 +1532,12 @@ then\n \tBAIL_OUT 'You need to build test-tool; Run \"make t/helper/test-tool\" in the source (toplevel) directory'\n fi\n \n+if test -n \"$HARNESS_ACTIVE\"\n+then\n+\tsay \"TAP version 13\"\n+\tsay \"pragma +strict\"\n+fi\n+\n # Are we running this test at all?\n remove_trash=\n this_test=${0##*/}\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544484","messageId":"xmqqecipxp6g.fsf@gitster.g","threadId":"65734","inReplyTo":"20260602-pks-t7527-fix-tap-output-v1-3-db3da2a1b137@pks.im","subject":"Re: [PATCH 3/4] t/lib-git-p4: silence output when killing p4d and its watchdog","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-02T09:32:55Z","receivedAt":"2026-06-02T09:32:57Z","isPatch":true,"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n>  stop_p4d_and_watchdog () {\n>  \tkill -9 $p4d_pid $watchdog_pid\n> +\twait $p4d $watchdog_pid 2>/dev/null\n>  }\n\nShoudln't we be waiting on $p4d_pid (not $p4d)...\n\n> @@ -175,7 +176,7 @@ retry_until_success () {\n>  \n>  stop_and_cleanup_p4d () {\n>  \tkill -9 $p4d_pid $watchdog_pid\n> -\twait $p4d_pid\n> +\twait $p4d_pid $watchdog_pid 2>/dev/null\n>  \trm -rf \"$db\" \"$cli\" \"$pidfile\"\n>  }\n\n... like we do here?\n"},{"id":"544487","messageId":"ah6uZ6tdIh38X2uZ@pks.im","threadId":"65734","inReplyTo":"xmqqecipxp6g.fsf@gitster.g","subject":"Re: [PATCH 3/4] t/lib-git-p4: silence output when killing p4d and its watchdog","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-02T10:20:23Z","receivedAt":"2026-06-02T10:20:30Z","isPatch":true,"body":"On Tue, Jun 02, 2026 at 06:32:55PM +0900, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> >  stop_p4d_and_watchdog () {\n> >  \tkill -9 $p4d_pid $watchdog_pid\n> > +\twait $p4d $watchdog_pid 2>/dev/null\n> >  }\n> \n> Shoudln't we be waiting on $p4d_pid (not $p4d)...\n> \n> > @@ -175,7 +176,7 @@ retry_until_success () {\n> >  \n> >  stop_and_cleanup_p4d () {\n> >  \tkill -9 $p4d_pid $watchdog_pid\n> > -\twait $p4d_pid\n> > +\twait $p4d_pid $watchdog_pid 2>/dev/null\n> >  \trm -rf \"$db\" \"$cli\" \"$pidfile\"\n> >  }\n> \n> ... like we do here?\n\nOh, good catch. The statement basically doesn't do anything, which isn't\nmuch of a problem because we really only care about silencing the error\nmessage when the watchdog is being terminated. Will fix.\n\nPatrick\n"},{"id":"544506","messageId":"xmqqtsrlw09t.fsf@gitster.g","threadId":"65734","inReplyTo":"ah6uZ6tdIh38X2uZ@pks.im","subject":"Re: [PATCH 3/4] t/lib-git-p4: silence output when killing p4d and its watchdog","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-02T13:16:14Z","receivedAt":"2026-06-02T13:16:18Z","isPatch":true,"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Tue, Jun 02, 2026 at 06:32:55PM +0900, Junio C Hamano wrote:\n>> Patrick Steinhardt <ps@pks.im> writes:\n>> \n>> >  stop_p4d_and_watchdog () {\n>> >  \tkill -9 $p4d_pid $watchdog_pid\n>> > +\twait $p4d $watchdog_pid 2>/dev/null\n>> >  }\n>> \n>> Shoudln't we be waiting on $p4d_pid (not $p4d)...\n>> \n>> > @@ -175,7 +176,7 @@ retry_until_success () {\n>> >  \n>> >  stop_and_cleanup_p4d () {\n>> >  \tkill -9 $p4d_pid $watchdog_pid\n>> > -\twait $p4d_pid\n>> > +\twait $p4d_pid $watchdog_pid 2>/dev/null\n>> >  \trm -rf \"$db\" \"$cli\" \"$pidfile\"\n>> >  }\n>> \n>> ... like we do here?\n>\n> Oh, good catch. The statement basically doesn't do anything, which isn't\n> much of a problem because we really only care about silencing the error\n> message when the watchdog is being terminated. Will fix.\n\nThanks.  Another thing I noticed is that they look suspiciously\nsimilar.\n"},{"id":"544706","messageId":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im","subject":"[PATCH v3 0/8] t: fix broken TAP output","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:30Z","receivedAt":"2026-06-04T10:07:39Z","isPatch":true,"body":"Hi,\n\nthis small patch series fixes another instance of broken TAP output that\nhas landed via 4d11b9c218 (Merge branch 'pt/fsmonitor-linux', 2026-05-31).\n\nAs this has happened multiple times by now I decided to have a look at\nwhether we can fix this class of issues a bit more holistically. So this\nseries also contains a change that makes prove bail out when it sees\ninvalid TAP output, which uncovers a small set of preexisting issues in\nour test suite.\n\nChanges in v3:\n  - Fix a test gap for AlmaLinux and Debian in GitLab CI, which uncovers\n    an issue flagged by Peff.\n  - Fix TAP breakage in t7810.\n  - Link to v2: https://patch.msgid.link/20260603-pks-t7527-fix-tap-output-v2-0-cf3af5694e20@pks.im\n\nChanges in v2:\n  - Fix waiting for p4d, and deduplicate the logic that does this.\n  - Link to v1: https://patch.msgid.link/20260602-pks-t7527-fix-tap-output-v1-0-db3da2a1b137@pks.im\n\nTest runs can be found at [1] and [2]. Note that GitHub-side tests are\nfailing on Windows, but that is a preexisting failure on \"master\".\n\nThanks!\n\nPatrick\n\n[1]: https://gitlab.com/gitlab-org/git/-/merge_requests/585\n[2]: https://github.com/git/git/pull/2320\n\n---\nPatrick Steinhardt (8):\n      gitlab-ci: rearrange Linux jobs to match GitHub's order\n      gitlab-ci: add missing Linux jobs\n      ci: unify Linux images across GitLab and GitHub\n      t7527: fix broken TAP output\n      t7810: turn MB_REGEX check into a lazy prereq\n      t/test-lib: silence EBUSY errors on Windows during test cleanup\n      t/lib-git-p4: silence output when killing p4d and its watchdog\n      t: let prove fail when parsing invalid TAP output\n\n .github/workflows/main.yml   |  2 +-\n .gitlab-ci.yml               | 23 +++++++++++++++--------\n ci/lib.sh                    |  2 +-\n t/lib-git-p4.sh              |  4 ++--\n t/t7527-builtin-fsmonitor.sh |  7 ++++---\n t/t7810-grep.sh              |  5 +++--\n t/test-lib.sh                | 10 ++++++++--\n 7 files changed, 34 insertions(+), 19 deletions(-)\n\nRange-diff versus v2:\n\n-:  ---------- > 1:  5e817b102f gitlab-ci: rearrange Linux jobs to match GitHub's order\n-:  ---------- > 2:  83646cc834 gitlab-ci: add missing Linux jobs\n-:  ---------- > 3:  cca1567fbf ci: unify Linux images across GitLab and GitHub\n1:  52abbd5280 = 4:  430bc51818 t7527: fix broken TAP output\n-:  ---------- > 5:  78ef22df8d t7810: turn MB_REGEX check into a lazy prereq\n2:  ea1f1eb466 = 6:  7bbaeff48c t/test-lib: silence EBUSY errors on Windows during test cleanup\n3:  e97a515470 = 7:  abf2be09e6 t/lib-git-p4: silence output when killing p4d and its watchdog\n4:  436d7d8cf3 = 8:  04367c34be t: let prove fail when parsing invalid TAP output\n\n---\nbase-commit: 1666c1265231b0bc5f613fbbf3f0a9896cdef76e\nchange-id: 20260601-pks-t7527-fix-tap-output-105da1d73df0\n\n"},{"id":"544707","messageId":"20260604-pks-t7527-fix-tap-output-v3-1-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 1/8] gitlab-ci: rearrange Linux jobs to match GitHub's order","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:31Z","receivedAt":"2026-06-04T10:07:39Z","isPatch":true,"body":"Rearrange the order of Linux jobs that we have defined in GitLab CI so\nthat it matches the order on GitHub's side. This makes it easier to\ncompare whether the list of jobs actually matches on both sides.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitlab-ci.yml | 15 ++++++++-------\n 1 file changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex e0b9a0d82b..8cb41baa14 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -42,15 +42,15 @@ test:linux:\n       - jobname: linux-reftable\n         image: ubuntu:rolling\n         CC: clang\n+      - jobname: linux-TEST-vars\n+        image: ubuntu:20.04\n+        CC: gcc\n+        CC_PACKAGE: gcc-8\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n       - jobname: fedora-breaking-changes-meson\n         image: fedora:latest\n-      - jobname: linux-TEST-vars\n-        image: ubuntu:20.04\n-        CC: gcc\n-        CC_PACKAGE: gcc-8\n       - jobname: linux-leaks\n         image: ubuntu:rolling\n         CC: gcc\n@@ -60,13 +60,14 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n+      - jobname: linux-meson\n+        image: ubuntu:rolling\n+        CC: gcc\n       - jobname: linux-musl-meson\n         image: alpine:latest\n+        # Supported until 2025-04-02.\n       - jobname: linux32\n         image: i386/ubuntu:20.04\n-      - jobname: linux-meson\n-        image: ubuntu:rolling\n-        CC: gcc\n   artifacts:\n     paths:\n       - t/failed-test-artifacts\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544708","messageId":"20260604-pks-t7527-fix-tap-output-v3-2-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 2/8] gitlab-ci: add missing Linux jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:32Z","receivedAt":"2026-06-04T10:07:41Z","isPatch":true,"body":"The GitLab CI definitions are missing jobs for AlmaLinux and Debian,\nboth of which exist in GitHub Workflows. Plug this gap.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitlab-ci.yml | 6 ++++++\n ci/lib.sh      | 2 +-\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex 8cb41baa14..a5bdec5159 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -68,6 +68,12 @@ test:linux:\n         # Supported until 2025-04-02.\n       - jobname: linux32\n         image: i386/ubuntu:20.04\n+      # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n+      - jobname: almalinux-8\n+        image: almalinux:8\n+      # Supported until 2026-08-31.\n+      - jobname: debian-11\n+        image: debian:11\n   artifacts:\n     paths:\n       - t/failed-test-artifacts\ndiff --git a/ci/lib.sh b/ci/lib.sh\nindex 6e3799cfc3..b939110a6e 100755\n--- a/ci/lib.sh\n+++ b/ci/lib.sh\n@@ -254,7 +254,7 @@ then\n \t\tCI_OS_NAME=osx\n \t\tJOBS=$(nproc)\n \t\t;;\n-\t*,alpine:*|*,fedora:*|*,ubuntu:*|*,i386/ubuntu:*)\n+\t*,almalinux:*|*,alpine:*|*,debian:*|*,fedora:*|*,ubuntu:*|*,i386/ubuntu:*)\n \t\tCI_OS_NAME=linux\n \t\tJOBS=$(nproc)\n \t\t;;\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544709","messageId":"20260604-pks-t7527-fix-tap-output-v3-3-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 3/8] ci: unify Linux images across GitLab and GitHub","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:33Z","receivedAt":"2026-06-04T10:07:44Z","isPatch":true,"body":"The image for the \"linux-breaking-changes\" job has drifted apart across\nGitHub and GitLab. Adapt it to use \"ubuntu:rolling\" on both systems.\n\nWith this change there's only one difference remaining: GitHub uses\n\"ubuntu:focal\" for the \"linux32\" job while GitLab uses \"ubuntu:20.04\".\nThese are different names for the same image, so there is no actual\ndifference here. Adjust GitHub to use the \"20.04\" tag -- this matches\nall the other jobs which use version numbers, and you don't have to\nlearn Ubuntu's release names by heart.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml | 2 +-\n .gitlab-ci.yml             | 2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex 3da5326f0b..cf341d74db 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -407,7 +407,7 @@ jobs:\n           image: alpine:latest\n         # Supported until 2025-04-02.\n         - jobname: linux32\n-          image: i386/ubuntu:focal\n+          image: i386/ubuntu:20.04\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex a5bdec5159..49f3689b6a 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -47,7 +47,7 @@ test:linux:\n         CC: gcc\n         CC_PACKAGE: gcc-8\n       - jobname: linux-breaking-changes\n-        image: ubuntu:20.04\n+        image: ubuntu:rolling\n         CC: gcc\n       - jobname: fedora-breaking-changes-meson\n         image: fedora:latest\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544710","messageId":"20260604-pks-t7527-fix-tap-output-v3-4-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 4/8] t7527: fix broken TAP output","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:34Z","receivedAt":"2026-06-04T10:07:46Z","isPatch":true,"body":"Before running the tests in t7527 we first verify whether the fsmonitor\neven works, which seems to depend on the actual filesystem that is in\nuse. The verification executes outside of any prerequisite or test body,\nso its stdout/stderr is not being redirected.\n\nThe consequence of this is that any command that prints to stdout/stderr\nmay break the TAP specification by printing invalid lines. And in fact\nwe already do that, as git-init(1) prints the path to the created Git\nrepository by default.\n\nFix this issue by moving the logic into a lazy prerequisite.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/t7527-builtin-fsmonitor.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh\nindex b63c162f9b..d881e27466 100755\n--- a/t/t7527-builtin-fsmonitor.sh\n+++ b/t/t7527-builtin-fsmonitor.sh\n@@ -25,7 +25,8 @@ maybe_timeout () {\n \t\t\"$@\"\n \tfi\n }\n-verify_fsmonitor_works () {\n+\n+test_lazy_prereq FSMONITOR_WORKS '\n \tgit init test_fsmonitor_smoke || return 1\n \n \tGIT_TRACE_FSMONITOR=\"$PWD/smoke.trace\" &&\n@@ -50,9 +51,9 @@ verify_fsmonitor_works () {\n \tret=$?\n \trm -rf test_fsmonitor_smoke smoke.trace\n \treturn $ret\n-}\n+'\n \n-if ! verify_fsmonitor_works\n+if ! test_have_prereq FSMONITOR_WORKS\n then\n \tskip_all=\"filesystem does not deliver fsmonitor events (container/overlayfs?)\"\n \ttest_done\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544711","messageId":"20260604-pks-t7527-fix-tap-output-v3-5-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 5/8] t7810: turn MB_REGEX check into a lazy prereq","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:35Z","receivedAt":"2026-06-04T10:07:50Z","isPatch":true,"body":"In t7810 we verify whether the system has proper multibyte locale\nsupport by executing `test-tool regex` with a unicode character. When\nthis check fails though we'll output an error that breaks the TAP\nformat.\n\nFix this issue by turning the logic into a lazy prerequisite.\n\nReported-by: Jeff King <peff@peff.net>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/t7810-grep.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 1b195bee59..d61c4a4d73 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -18,8 +18,9 @@ test_invalid_grep_expression() {\n \t'\n }\n \n-LC_ALL=en_US.UTF-8 test-tool regex '^.$' '¿' &&\n-  test_set_prereq MB_REGEX\n+test_lazy_prereq MB_REGEX '\n+\tLC_ALL=en_US.UTF-8 test-tool regex \"^.$\" \"¿\"\n+'\n \n cat >hello.c <<EOF\n #include <assert.h>\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544712","messageId":"20260604-pks-t7527-fix-tap-output-v3-6-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 6/8] t/test-lib: silence EBUSY errors on Windows during test cleanup","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:36Z","receivedAt":"2026-06-04T10:07:53Z","isPatch":true,"body":"When tests have finished we clean up the trash directory via `rm -rf`.\nOn Windows this can fail with EBUSY in cases where a process still holds\nsome of the files open, for example when we have spawned a daemonized\nprocess that wasn't properly terminated. We thus retry several times,\nbut every failure will result in error messages being printed, and that\nin turn breaks the TAP output format.\n\nOne such case where this is causing issues is in t921x, which contains\ntests related to Scalar. Some tests spawn the fsmonitor daemon, and we\nnever properly terminate it.\n\nThe obvious fix would be to ensure that we never leak any processes, but\nthat gets ugly fast. Instead, let's work around the issue by silencing\nerror messages printed by the `rm -rf` calls. We already know to print\nan error when the retry loop fails, so we don't loose much.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/test-lib.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 4a7357b547..d1d24c4124 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -1299,10 +1299,10 @@ test_done () {\n \t\t\terror \"Tests passed but trash directory already removed before test cleanup; aborting\"\n \n \t\t\tcd \"$TRASH_DIRECTORY/..\" &&\n-\t\t\trm -fr \"$TRASH_DIRECTORY\" || {\n+\t\t\trm -fr \"$TRASH_DIRECTORY\" 2>/dev/null || {\n \t\t\t\t# try again in a bit\n \t\t\t\tsleep 5;\n-\t\t\t\trm -fr \"$TRASH_DIRECTORY\"\n+\t\t\t\trm -fr \"$TRASH_DIRECTORY\" 2>/dev/null\n \t\t\t} ||\n \t\t\terror \"Tests passed but test cleanup failed; aborting\"\n \t\tfi\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544713","messageId":"20260604-pks-t7527-fix-tap-output-v3-7-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 7/8] t/lib-git-p4: silence output when killing p4d and its watchdog","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:37Z","receivedAt":"2026-06-04T10:07:55Z","isPatch":true,"body":"When stopping the p4d watchdog process via \"kill -9\", the shell may\nprint a job-control notification like:\n\n  ./test-lib.sh: line 1269: 57960 Killed: 9               while true; do\n      if test $nr_tries_left -eq 0; then\n          kill -9 $p4d_pid; exit 1;\n      fi; sleep 1; nr_tries_left=$(($nr_tries_left - 1));\n  done 2> /dev/null 4>&2  (wd: ~)\n\nThis message is printed asynchronously by the shell when it reaps the\nprocess. While harmless right now, this will cause breakage once we\nenable strict parsing of the TAP protocol in a subsequent commit.\n\nFix this by using `wait` so that we can synchronously reap the watchdog\nprocess and swallow the diagnostic.\n\nWhile at it, deduplicate the logic we have in `stop_p4d_and_watchdog ()`\nand `stop_and_cleanup_p4d ()`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/lib-git-p4.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh\nindex d22e9c684a..9108868187 100644\n--- a/t/lib-git-p4.sh\n+++ b/t/lib-git-p4.sh\n@@ -65,6 +65,7 @@ pidfile=\"$TRASH_DIRECTORY/p4d.pid\"\n \n stop_p4d_and_watchdog () {\n \tkill -9 $p4d_pid $watchdog_pid\n+\twait $p4d_pid $watchdog_pid 2>/dev/null\n }\n \n # git p4 submit generates a temp file, which will\n@@ -174,8 +175,7 @@ retry_until_success () {\n }\n \n stop_and_cleanup_p4d () {\n-\tkill -9 $p4d_pid $watchdog_pid\n-\twait $p4d_pid\n+\tstop_p4d_and_watchdog\n \trm -rf \"$db\" \"$cli\" \"$pidfile\"\n }\n \n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544714","messageId":"20260604-pks-t7527-fix-tap-output-v3-8-7d766ed481e4@pks.im","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im","subject":"[PATCH v3 8/8] t: let prove fail when parsing invalid TAP output","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-04T10:07:38Z","receivedAt":"2026-06-04T10:07:57Z","isPatch":true,"body":"To make the result of our tests accessible we use the TAP protocol. This\nprotocol is parsed by either prove or by Meson. Unfortunately, these two\ntools differ when it comes to their strictness when parsing the\nprotocol:\n\n  - Prove by default happily accepts lines not specified by the\n    protocol.\n\n  - Meson will also accept such lines, but prints a big and ugly warning\n    message.\n\nWe have fixed our test suite in the past to not print invalid TAP lines\nanymore via b1dc2e796e (Merge branch 'ps/meson-tap-parse', 2025-06-17).\nBut as none of our tools perform a strict check it's still possible for\nbroken tests to sneak back in, like for example in 362f69547f (Merge\nbranch 'ps/t1006-tap-fix', 2025-07-16). This doesn't hurt at all when\nusing prove, but it's quite annoying when using Meson due to the\ngenerated warnings.\n\nUnfortunately, there doesn't seem to be a portable way to make all tools\ncomplain about violations of the TAP format. The TAP 14 specification\nhas added pragmas to the protocol that would allow us to say `pragma\n+strict`, and the effect of that would be to treat invalid TAP lines as\na test failure. But the release of TAP 14 is still rather recent, and\nTest-Harness for example only gained support for it in version 3.48,\nwhich was released in 2023.\n\nIn fact though, this pragma was already introduced as an inofficial\nextension of the TAP protocol with Test-Harness 3.10, released in 2008.\nSo while not all tools understand the pragma, at least prove does for a\nlong time.\n\nUnconditionally enable the pragma when using prove so that we'll detect\ntests that emit broken TAP output right away. This would have detected\nthe issues fixed in preceding commits:\n\n    $ prove t7527-builtin-fsmonitor.sh\n    t7527-builtin-fsmonitor.sh .. All 69 subtests passed\n            (less 6 skipped subtests: 63 okay)\n\n    Test Summary Report\n    -------------------\n    t7527-builtin-fsmonitor.sh (Wstat: 0 Tests: 69 Failed: 0)\n      Parse errors: Unknown TAP token: \"Initialized empty Git repository in /tmp/git/test_fsmonitor_smoke/.git/\"\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n t/test-lib.sh | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex d1d24c4124..ceefb99bff 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -1532,6 +1532,12 @@ then\n \tBAIL_OUT 'You need to build test-tool; Run \"make t/helper/test-tool\" in the source (toplevel) directory'\n fi\n \n+if test -n \"$HARNESS_ACTIVE\"\n+then\n+\tsay \"TAP version 13\"\n+\tsay \"pragma +strict\"\n+fi\n+\n # Are we running this test at all?\n remove_trash=\n this_test=${0##*/}\n\n-- \n2.54.0.1064.gd145956f57.dirty\n\n"},{"id":"544993","messageId":"20260609012236.GA1502349@coredump.intra.peff.net","threadId":"65734","inReplyTo":"20260604-pks-t7527-fix-tap-output-v3-5-7d766ed481e4@pks.im","subject":"Re: [PATCH v3 5/8] t7810: turn MB_REGEX check into a lazy prereq","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-06-09T01:22:36Z","receivedAt":"2026-06-09T01:22:38Z","isPatch":true,"body":"On Thu, Jun 04, 2026 at 12:07:35PM +0200, Patrick Steinhardt wrote:\n\n> diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\n> index 1b195bee59..d61c4a4d73 100755\n> --- a/t/t7810-grep.sh\n> +++ b/t/t7810-grep.sh\n> @@ -18,8 +18,9 @@ test_invalid_grep_expression() {\n>  \t'\n>  }\n>  \n> -LC_ALL=en_US.UTF-8 test-tool regex '^.$' '¿' &&\n> -  test_set_prereq MB_REGEX\n> +test_lazy_prereq MB_REGEX '\n> +\tLC_ALL=en_US.UTF-8 test-tool regex \"^.$\" \"¿\"\n> +'\n\nOh good. Since the error was coming from the shell, I was worried that\nthe use of LC_ALL inside the test snippets was somehow causing output to\nleak to stderr. But it was just (yet another) case where we ran a tool\noutside of a snippet, which is easy to fix.\n\nThis also allays my fears that the tests might have been misbehaving on\nthose other platforms. They are (and were) caught by this prereq and not\nrun at all, which is the right thing.\n\nThanks for fixing.\n\n-Peff\n"}]}