From a6597405384492b9753b17ba84c9e0b5396d55d3 Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Sun, 18 Oct 2026 15:00:04 +0000 Subject: [PATCH 1/3] tests/test_repo_hygiene.py: the one-line-install check offers "name it in RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL" only to a `.md` in the notes directory that is no release's `v*.md`, after the install line, a test reads the message for a release's notes, another `.md` there and a file elsewhere, and every line of the release notes that holds both `curl` and `download/install.sh` holds the one line and, after it, nothing or the pinned form (#931) The message. A mistyped copy in a release's own notes (`| bsh` at v1.1.1.md:132) was told to name itself in the set, which the second test refuses. The `or, if it is not a release's notes, name ... in RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL` clause now goes only to a file in docs/release-notes/ whose name does not match `v*.md`, and it follows the indented install line, so it no longer reads as part of the line. The comment above the set says a `v*.md` other than v1.0.0.md named there fails the second test. A test reads the message. It is a module-level `_one_line_install_failure(name)` now, which the parametrised test uses, and `test_the_one_line_install_message_offers_the_set_only_where_it_works` calls it for docs/release-notes/v9.9.9.md, docs/release-notes/README.md and README.md. The install line is in all three, the clause in the second alone and after the line. Turning the `if` around, or dropping either half of its condition, now fails a test. Every line that runs the install. The new `test_every_release_notes_line_that_installs_holds_the_one_line_install` reads every `v*.md` but v1.0.0.md. A line with both `curl` and `download/install.sh` must hold the one line, and what follows it must be nothing or ` -s -- v..`, then only a closing backtick, punctuation and blanks. Each failure names the file, the line number and the line. The rule picks 4 lines today (v1.0.1.md:12 and :45, v1.1.0.md:49, v1.1.1.md:132) and passes on all 4, and the test asks for at least those per file (2, 1, 1) so a rule that matches nothing cannot pass; the counts are per file, not per line number, so an edit above a line does not fail it. M10 is held by the pinned-form rule (choice (a)): it passes today on all 4 lines and catches M10 with no list of special cases. What it does not read is the version in the pinned form, so ` -s -- v9.9.9` passes in any notes. Mutants, each made by hand, run with `-k one_line_install` (11 tests), and restored; the ones that edit the test file were restored from a copy and compared with `cmp`. | Mutant | Change | Result | |---|---|---| | M1 | `\| bsh` at v1.1.0.md:49 | caught (2 failed) | | M5 | `\| bsh` at v1.1.1.md:132 | caught (2 failed), message has no `or` clause | | M6 | v1.1.1.md added to the set | caught (1 failed) | | M7 | `\| bsh` at v1.0.1.md:12 | caught (1 failed, new test only) | | M8 | scratch docs/release-notes/README.md | caught (1 failed), message has the clause | | M10 | `\| bash -s -- --yes` at v1.1.1.md:132 | caught (1 failed, new test only) | | X3 | `if path.parent == RELEASE_NOTES` turned to `!=` | caught (1 failed, new test) | | X3b | `not path.match("v*.md")` turned to `path.match("v*.md")` | caught (1 failed, new test) | | X3c | the clause never offered | caught (1 failed, new test) | | X4 | the clause offered to every file | caught (1 failed, new test) | | X6 | the rule's `curl` test matches nothing | caught (1 failed, new test) | | extra | `-s -- main` at v1.0.1.md:45 | caught (1 failed, new test only) | Tests: tests/test_repo_hygiene.py + tests/test_release_workflow.py + tests/test_workflow_concurrency.py 153 passed (151 at the base, +2); `-k one_line_install` 11 passed (9 at the base). Tests only: no tool and no notes change. Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Sonnet 5.5 --- tests/test_repo_hygiene.py | 99 +++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/tests/test_repo_hygiene.py b/tests/test_repo_hygiene.py index 844246c2..56ab1c52 100644 --- a/tests/test_repo_hygiene.py +++ b/tests/test_repo_hygiene.py @@ -1569,8 +1569,8 @@ def test_the_openrepotools_install_line_is_the_same_everywhere(name): #: edit here (#885: the list named v1.0.1.md alone, so a mistyped line in #: v1.1.0.md passed). The set is the notes that predate the line: v1.0.0's #: carries none. A `.md` in that directory that is not a release's notes -#: fails with them until it is named here; a `v*.md` named here fails the -#: second test below. +#: fails with them until it is named here; a `v*.md` other than v1.0.0.md +#: named here fails the second test below. RELEASE_NOTES = REPO / "docs" / "release-notes" RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL = {"v1.0.0.md"} ONE_LINE_INSTALL_IN = [ @@ -1580,17 +1580,28 @@ def test_the_openrepotools_install_line_is_the_same_everywhere(name): if path.name not in RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL)] +def _one_line_install_failure(name): + """The message for `name`, a file that lacks the one-line install. + + Every file is told to carry the line. A file in the notes directory that + is no release's notes is also told it may be named in the set, and no + other is: the second test below refuses a release's `v*.md` there, so + offering it would send a person from one failure to the next (#931). The + line comes first, so the clause after it is no part of it. + """ + path = REPO / name + message = (f"{name} must carry the one-line install byte for byte:\n" + f" {ONE_LINE_INSTALL}") + if path.parent == RELEASE_NOTES and not path.match("v*.md"): + message += (f"\nor, if it is not a release's notes, name {path.name!r}" + " in RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL") + return message + + @pytest.mark.parametrize("name", ONE_LINE_INSTALL_IN) def test_the_one_line_install_is_the_same_everywhere(name): - path = REPO / name - text = path.read_text(encoding="utf-8") - other = "" - if path.parent == RELEASE_NOTES: - other = (f", or, if it is not a release's notes, name {path.name!r} " - "in RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL") - assert ONE_LINE_INSTALL in text, ( - f"{name} must carry the one-line install byte for byte{other}:\n" - f" {ONE_LINE_INSTALL}") + text = (REPO / name).read_text(encoding="utf-8") + assert ONE_LINE_INSTALL in text, _one_line_install_failure(name) def test_the_one_line_install_holds_the_release_notes_it_found(): @@ -1610,6 +1621,72 @@ def test_the_one_line_install_holds_the_release_notes_it_found(): "RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL") +def test_the_one_line_install_message_offers_the_set_only_where_it_works(): + """The message offers the set to a file it can serve and to no other. + + Every file is told to carry the line. The set is for names in the notes + directory that are no release's notes, so only such a file is told to + name itself there: a release's `v*.md` is refused in it by the test above, + and a file elsewhere is not looked up in it. A message that told either + would send a person to a second failure (#931). Nothing else reads the + message, so without this a comparison turned around in it passes every + test. + """ + clause = "RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL" + release = _one_line_install_failure("docs/release-notes/v9.9.9.md") + other_note = _one_line_install_failure("docs/release-notes/README.md") + elsewhere = _one_line_install_failure("README.md") + for message in (release, other_note, elsewhere): + assert f":\n {ONE_LINE_INSTALL}" in message + assert clause not in release + assert clause in other_note + assert clause not in elsewhere + assert other_note.index(ONE_LINE_INSTALL) < other_note.index(clause) + + +#: What may follow the one line on a line of the notes that runs it: nothing, +#: or the pinned form `install.sh` prints, ` -s -- v..`, +#: then a closing backtick or punctuation and trailing blanks. +ONE_LINE_INSTALL_MAY_END_WITH = re.compile( + r"(?: -s -- v\d+\.\d+\.\d+)?[`.,;:)]*\s*") + + +def test_every_release_notes_line_that_installs_holds_the_one_line_install(): + """Each line of the notes that runs the install holds the one line, and + what follows it is nothing or the pinned form (#931). + + The test of every file asks only that it hold the line somewhere. A + mistyped copy passes while another line holds the right one (`| bsh` at + v1.0.1.md:12, beside the pinned line at :45), and so does a line that has + the line as a prefix (`| bash -s -- --yes`). A line runs the install if + it holds both `curl` and `download/install.sh`: the handbook's rule, any + line with `download/install.sh`, would take the bare URLs of the verify + commands too. The notes are those that test holds, every `v*.md` but + v1.0.0.md, which predates the line. + """ + notes = [path for path in sorted(RELEASE_NOTES.glob("v*.md")) + if path.name != "v1.0.0.md"] + found, failures = {}, [] + for path in notes: + where = path.relative_to(REPO).as_posix() + lines = path.read_text(encoding="utf-8").splitlines() + for number, line in enumerate(lines, 1): + if "curl" not in line or "download/install.sh" not in line: + continue + found[path.name] = found.get(path.name, 0) + 1 + after = line.partition(ONE_LINE_INSTALL)[2] + if ONE_LINE_INSTALL not in line: + failures.append(f"{where}:{number} runs the install but does " + f"not hold the one-line install:\n {line}") + elif not ONE_LINE_INSTALL_MAY_END_WITH.fullmatch(after): + failures.append(f"{where}:{number} has more than the pinned " + f"form after the one-line install:\n" + f" {line}") + least = {"v1.0.1.md": 2, "v1.1.0.md": 1, "v1.1.1.md": 1} + assert all(found.get(name, 0) >= n for name, n in least.items()), found + assert not failures, "\n".join(failures) + + def test_every_handbook_copy_of_the_one_line_install_is_the_same(): """The handbook shows the one line in three code blocks: the masthead's, step 3's on the Linux, macOS and WSL2 tabs, and step 3's on the Windows From a1649ef605074442d8254016b85f6eab153abfac Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Sun, 18 Oct 2026 17:55:30 +0000 Subject: [PATCH 2/3] tests/test_repo_hygiene.py: the one-line install's per-line verdict is tested on its own, so a looser pinned-form rule fails, a `v` inside a name is no release's `v*.md`, and a failing count says what it found and wanted (#931) The review of #959 found the pinned-form rule's rejecting side had no case of its own: the notes pass today, so a regex loosened to ` -s -- .*` or `.*`, to `v[\d.]+`, a `match` for the `fullmatch`, or the "does not hold the line" branch turned off passed every test. - `_one_line_install_fault(line)` returns "" or the reason, and the loop uses it. Three tests hold it: the tails the notes end the line with, the tails they may not, and a mistyped line (`| bsh`). - The message test asks for `docs/release-notes/draft-v1.2.0.md`, so a name that merely holds a `v` is told it may be named in the set. - The docstrings say "other than v1.0.0.md", the comment names the six characters the regex allows after the line, "that test" names the test, and the count assert says what was found and what was wanted. Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Sonnet 5.5 --- tests/test_repo_hygiene.py | 71 +++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/tests/test_repo_hygiene.py b/tests/test_repo_hygiene.py index 56ab1c52..13b5c248 100644 --- a/tests/test_repo_hygiene.py +++ b/tests/test_repo_hygiene.py @@ -1585,9 +1585,10 @@ def _one_line_install_failure(name): Every file is told to carry the line. A file in the notes directory that is no release's notes is also told it may be named in the set, and no - other is: the second test below refuses a release's `v*.md` there, so - offering it would send a person from one failure to the next (#931). The - line comes first, so the clause after it is no part of it. + other is: the second test below refuses a release's `v*.md` other than + v1.0.0.md there, so offering it would send a person from one failure to + the next (#931). The line comes first, so the clause after it is no part + of it. """ path = REPO / name message = (f"{name} must carry the one-line install byte for byte:\n" @@ -1626,31 +1627,63 @@ def test_the_one_line_install_message_offers_the_set_only_where_it_works(): Every file is told to carry the line. The set is for names in the notes directory that are no release's notes, so only such a file is told to - name itself there: a release's `v*.md` is refused in it by the test above, - and a file elsewhere is not looked up in it. A message that told either - would send a person to a second failure (#931). Nothing else reads the - message, so without this a comparison turned around in it passes every - test. + name itself there: a release's `v*.md` other than v1.0.0.md is refused in + it by the test above, and a file elsewhere is not looked up in it. A + message that told either would send a person to a second failure (#931). + The line between them is the name's form, `v*.md`, not a `v` in it: + draft-v1.2.0.md is no release's notes. Nothing else reads the message, so + without this a comparison turned around in it passes every test. """ clause = "RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL" release = _one_line_install_failure("docs/release-notes/v9.9.9.md") other_note = _one_line_install_failure("docs/release-notes/README.md") + stray = _one_line_install_failure("docs/release-notes/draft-v1.2.0.md") elsewhere = _one_line_install_failure("README.md") for message in (release, other_note, elsewhere): assert f":\n {ONE_LINE_INSTALL}" in message assert clause not in release assert clause in other_note + assert clause in stray assert clause not in elsewhere assert other_note.index(ONE_LINE_INSTALL) < other_note.index(clause) #: What may follow the one line on a line of the notes that runs it: nothing, #: or the pinned form `install.sh` prints, ` -s -- v..`, -#: then a closing backtick or punctuation and trailing blanks. +#: then any run of a backtick, a period, a comma, a semicolon, a colon or a +#: closing parenthesis, and trailing blanks. Nothing else: not a quote, `**`, +#: a `#` comment or more words. ONE_LINE_INSTALL_MAY_END_WITH = re.compile( r"(?: -s -- v\d+\.\d+\.\d+)?[`.,;:)]*\s*") +def _one_line_install_fault(line): + """What is wrong with a line of the notes that runs the install, or ''.""" + if ONE_LINE_INSTALL not in line: + return "runs the install but does not hold the one-line install" + after = line.partition(ONE_LINE_INSTALL)[2] + if not ONE_LINE_INSTALL_MAY_END_WITH.fullmatch(after): + return "has more than the pinned form after the one-line install" + return "" + + +@pytest.mark.parametrize("tail", [ + "", " -s -- v1.0.1", "`,", " -s -- v1.0.1`,", ".", " "]) +def test_the_one_line_install_may_end_as_the_notes_end_it(tail): + assert _one_line_install_fault(ONE_LINE_INSTALL + tail) == "" + + +@pytest.mark.parametrize("tail", [ + " -s -- --yes", " -s -- main", " -s -- v1.0", " -s -- v1.0.1.2", + " -s -- v1.0.1 --yes", "x"]) +def test_the_one_line_install_may_not_end_any_other_way(tail): + assert _one_line_install_fault(ONE_LINE_INSTALL + tail) != "" + + +def test_a_mistyped_one_line_install_is_a_fault(): + assert _one_line_install_fault(ONE_LINE_INSTALL[:-4] + "bsh") != "" + + def test_every_release_notes_line_that_installs_holds_the_one_line_install(): """Each line of the notes that runs the install holds the one line, and what follows it is nothing or the pinned form (#931). @@ -1661,8 +1694,9 @@ def test_every_release_notes_line_that_installs_holds_the_one_line_install(): the line as a prefix (`| bash -s -- --yes`). A line runs the install if it holds both `curl` and `download/install.sh`: the handbook's rule, any line with `download/install.sh`, would take the bare URLs of the verify - commands too. The notes are those that test holds, every `v*.md` but - v1.0.0.md, which predates the line. + commands too. The notes read are those that + test_the_one_line_install_holds_the_release_notes_it_found holds: every + `v*.md` but v1.0.0.md, which predates the line. """ notes = [path for path in sorted(RELEASE_NOTES.glob("v*.md")) if path.name != "v1.0.0.md"] @@ -1674,16 +1708,13 @@ def test_every_release_notes_line_that_installs_holds_the_one_line_install(): if "curl" not in line or "download/install.sh" not in line: continue found[path.name] = found.get(path.name, 0) + 1 - after = line.partition(ONE_LINE_INSTALL)[2] - if ONE_LINE_INSTALL not in line: - failures.append(f"{where}:{number} runs the install but does " - f"not hold the one-line install:\n {line}") - elif not ONE_LINE_INSTALL_MAY_END_WITH.fullmatch(after): - failures.append(f"{where}:{number} has more than the pinned " - f"form after the one-line install:\n" - f" {line}") + fault = _one_line_install_fault(line) + if fault: + failures.append(f"{where}:{number} {fault}:\n {line}") least = {"v1.0.1.md": 2, "v1.1.0.md": 1, "v1.1.1.md": 1} - assert all(found.get(name, 0) >= n for name, n in least.items()), found + assert all(found.get(name, 0) >= n for name, n in least.items()), ( + "the rule found fewer install lines than the notes hold, " + f"found: {found}; wanted at least: {least}") assert not failures, "\n".join(failures) From daf0376d7fc6417d6679d0e9c500be112f751ec7 Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Sun, 18 Oct 2026 18:01:24 +0000 Subject: [PATCH 3/3] tests/test_repo_hygiene.py: the one-line install's accepted tails include `;`, `:`, `)` and a pinned form of two-digit parts, so a trailing class that drops one of them or a `\d` for the `\d+` fails, and the message test's docstring says what the name's form separates (#931) The re-check of #959 named two things left. - The accepted-tail list held no case for three of the six characters the trailing class allows, so a class without `;`, `:` or `)` passed, and none for a pinned form longer than one digit a part, so `\d` for `\d+` passed. The list now has `;`, `:`, `)` and ` -s -- v10.20.30`. - "The line between them" had no antecedent. It now reads "The line between a release's notes and any other `.md` there is the name's form". Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Sonnet 5.5 --- tests/test_repo_hygiene.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_repo_hygiene.py b/tests/test_repo_hygiene.py index 13b5c248..ba27fd79 100644 --- a/tests/test_repo_hygiene.py +++ b/tests/test_repo_hygiene.py @@ -1630,9 +1630,10 @@ def test_the_one_line_install_message_offers_the_set_only_where_it_works(): name itself there: a release's `v*.md` other than v1.0.0.md is refused in it by the test above, and a file elsewhere is not looked up in it. A message that told either would send a person to a second failure (#931). - The line between them is the name's form, `v*.md`, not a `v` in it: - draft-v1.2.0.md is no release's notes. Nothing else reads the message, so - without this a comparison turned around in it passes every test. + The line between a release's notes and any other `.md` there is the + name's form, `v*.md`, not a `v` in it: draft-v1.2.0.md is no release's + notes. Nothing else reads the message, so without this a comparison + turned around in it passes every test. """ clause = "RELEASE_NOTES_WITHOUT_THE_ONE_LINE_INSTALL" release = _one_line_install_failure("docs/release-notes/v9.9.9.md") @@ -1668,7 +1669,8 @@ def _one_line_install_fault(line): @pytest.mark.parametrize("tail", [ - "", " -s -- v1.0.1", "`,", " -s -- v1.0.1`,", ".", " "]) + "", " -s -- v1.0.1", "`,", " -s -- v1.0.1`,", ".", " ", ";", ":", ")", + " -s -- v10.20.30"]) def test_the_one_line_install_may_end_as_the_notes_end_it(tail): assert _one_line_install_fault(ONE_LINE_INSTALL + tail) == ""