From 310e72e8f596dc447be7d50ea272d16bee8013ae Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Sat, 12 Sep 2026 09:31:22 -0400 Subject: [PATCH] perf(hooks): lint through one script so hand runs share its cache Cargo fingerprints a check by the flags it was given, so the hook's `cargo clippy -- -D warnings` and a bare `cargo clippy` were two cached results over the same source, and alternating between them re-checked all 28 workspace crates each way. Both now go through scripts/lint.sh. Co-Authored-By: Claude Opus 5 (1M context) Change-Id: I60e3d73f3c0116900d05b9d503d4cff99c7d3190 --- DEVELOPING.md | 20 +++++++++++++------- prek.toml | 2 +- scripts/lint.sh | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100755 scripts/lint.sh diff --git a/DEVELOPING.md b/DEVELOPING.md index ddf67818..df14e657 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -3,13 +3,19 @@ Run `prek install` once; it wires both the pre-commit and the commit-msg stage, and until someone runs it a commit here is checked by nobody. The pre-commit stage runs `cargo fmt`, `cargo clippy` and `cargo doc` across the whole -workspace, so it is slow — minutes, and longer against a cold `target/` — and -`cargo doc` is wired to `docs/*.md` as well as to the Rust sources, so a -documentation-only commit pays for it too. The commit-msg stage checks that the -subject is a Conventional Commit and stamps the `Change-Id` trailer that stacked -pull requests are matched by; that trailer is what a `--no-verify` commit gives -up along with the checks, and a commit made without one has to be rewritten to -get one. +workspace, so against a cold `target/` it is minutes, and `cargo doc` is wired +to `docs/*.md` as well as to the Rust sources, so a documentation-only commit +pays for it too. Against a warm one it is seconds. + +Keeping it seconds is what `scripts/lint.sh` is for: lint by hand with that +rather than a bare `cargo clippy`. Cargo caches a check against the flags it +was given, so the two are separate cached results over the same source, and +alternating between them re-checks every crate in the workspace each way. + +The commit-msg stage checks that the subject is a Conventional Commit and +stamps the `Change-Id` trailer that stacked pull requests are matched by; that +trailer is what a `--no-verify` commit gives up along with the checks, and a +commit made without one has to be rewritten to get one. The test suite runs from `scripts/ci.sh []`: it runs the hooks over every file rather than a staged set, replays the commit-msg stage over every commit in diff --git a/prek.toml b/prek.toml index 887f7dc7..d6313dbb 100644 --- a/prek.toml +++ b/prek.toml @@ -51,7 +51,7 @@ hooks = [ # hand-apply a diff rustfmt already knows how to write. { id = "cargo-fmt", name = "cargo fmt", entry = "cargo fmt --all", language = "system", types = ["file"], files = '\.rs$', pass_filenames = false, stages = ["pre-commit"] }, # clippy type-checks as it lints, so there is no separate cargo check hook. - { id = "cargo-clippy", name = "cargo clippy", entry = "cargo clippy --workspace --all-targets --all-features -- -D warnings", language = "system", types = ["file"], files = '(\.rs$|Cargo\.(toml|lock)$)', pass_filenames = false, stages = ["pre-commit"] }, + { id = "cargo-clippy", name = "cargo clippy", entry = "scripts/lint.sh", language = "system", types = ["file"], files = '(\.rs$|Cargo\.(toml|lock)$)', pass_filenames = false, stages = ["pre-commit"] }, # Spelled out rather than hidden behind a cargo alias: see the comment in # .cargo/config.toml for why an alias breaks inside a worktree. # The doc build is a check, not just a build: .cargo/config.toml sets diff --git a/scripts/lint.sh b/scripts/lint.sh new file mode 100755 index 00000000..b2327214 --- /dev/null +++ b/scripts/lint.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# The workspace lint run, in the one spelling everything uses. +# +# Cargo fingerprints a check by the flags it was given, so `cargo clippy` and +# `cargo clippy -- -D warnings` are two different cached results over the same +# source. Alternating between them re-checks every workspace crate, which on +# this tree is around a minute each way. Running this instead of a hand-rolled +# clippy keeps one fingerprint, and a check that nothing has changed then costs +# under a second. +# +# The pre-commit hook runs this same script, so the two cannot drift. +set -euo pipefail + +cd "$(dirname "$0")/.." + +exec cargo clippy --workspace --all-targets --all-features "$@" -- -D warnings -- 2.51.2