Stop the mutation harness dropping the documentation's figures

`copy_tree()` excluded `*.png` from the scratch tree, which was right when the
only PNGs anywhere were libpng's and SDL_image's test corpora -- 39 MB that
nothing in this build reads. `docs/images/` changed that: `docs_examples`
asserts that every `screenshot=` block has its figure, so a copy with no images
fails thirteen blocks, the *baseline* comes back red, and the run aborts with
"Fix the suite before mutation testing" before mutating anything.

Mutation testing has therefore been unrunnable since the figures landed, and it
fails in the one way this repository's own notes warn about: looking like the
thing it measures is broken.

Keep the project's PNGs, still drop the dependencies'. The pattern list cannot
express that -- `ignore_patterns` matches basenames -- so it becomes a function
that adds the `*.png` rule only under `deps/`.

Verified: `--target src/symtab.c --max-mutants 2` now reports "Baseline OK." and
scores both mutants, where every invocation before this aborted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-01 23:36:02 -04:00
parent cb0e2d0800
commit caebc1a174

View File

@@ -286,9 +286,25 @@ def copy_tree(src, dst):
# other reason -- it was driven in place out of deps/basicinterpret -- and
# now lives in tests/reference/, which comes along with the rest of the tree.
# Only vendored Windows DLLs are dead weight, hence "*.dll".
ignore = shutil.ignore_patterns("build*", ".git", "*.o", "*.so", "*~",
"#*#", "*.iso", "*.png", "*.gcno", "*.gcda",
"*.dll")
#
# **PNGs are ours or theirs, and the difference matters.** This used to drop
# every one of them, which was right when the only PNGs in the tree were
# SDL_image's and libpng's test corpora -- 39 MB that nothing here reads.
# docs/images/ changed that: docs_examples asserts every `screenshot=` block
# has its figure, so dropping them made the *baseline* fail and no mutation
# run could start at all. Keep the project's thirteen; still drop the
# dependencies' thousands.
patterns = shutil.ignore_patterns("build*", ".git", "*.o", "*.so", "*~",
"#*#", "*.iso", "*.gcno", "*.gcda",
"*.dll")
depsdir = os.path.join(os.path.abspath(src), "deps")
def ignore(directory, names):
skip = set(patterns(directory, names))
if os.path.abspath(directory).startswith(depsdir):
skip.update(n for n in names if n.endswith(".png"))
return skip
shutil.copytree(src, dst, ignore=ignore, symlinks=True)