Skip to content

Support Rust language#989

Merged
j178 merged 6 commits intoj178:masterfrom
lmmx:rust-language-support
Dec 1, 2025
Merged

Support Rust language#989
j178 merged 6 commits intoj178:masterfrom
lmmx:rust-language-support

Conversation

@lmmx
Copy link
Collaborator

@lmmx lmmx commented Oct 28, 2025

  • chore(wip): initial scaffold for Rust language support
  • chore(wip): add version parsing like golang's
  • fix(matches): reject channel is more semantically correct than accept any channel
  • feat: implement rust installer
  • feat(deps): install rust deps with cargo add/install
  • feat(wip): implement run with filesystem path extraction [not correct]
  • feat: reimplement run() using stored version as rustup toolchain specifier
    • Python stores and uses the original request string (e.g. "stable")
    • Prek stores the resolved semver version (e.g. "1.70.0") after installation
    • Both functionally equivalent with rustup (one uses channel name, other uses specific version number)
  • test: add some tests (working 🎉)
  • fix: fill in default version for newly downloaded Rust
  • style(clippy): lint
  • fix(windows): suppress clippy return type error on overloaded signature
  • fix(rust): use installed rustup binary path instead of relying on PATH
  • fix(wip): attempt to pass toolchain (still not set)
  • fix(rust): query version for cached Rust installations using RUSTUP_TOOLCHAIN
  • fix: add rustc_bin to path (setup now works in bare env 🎉)
  • fix(rust): check for rustup at installation location instead of system PATH
  • test(snapshot): update snapshot for language version test

Container testing

Click to show instructions/notes

  • Build prek first then run container with prek binary mounted
  • Use Ubuntu 24.04 as 22.04 has GLIBC that is too old (so would need to target musl linux)
cargo build && docker run -it --rm -v $(pwd)/target/debug/prek:/usr/local/bin/prek ubuntu:24.04 bash

or to rebuild it in release mode (slower)

cargo build --release && docker run -it --rm -v $(pwd)/target/release/prek:/usr/local/bin/prek ubuntu:24.04 bash

Then in container:

apt-get update && apt-get install -y git curl

mkdir test-project && cd test-project
git init && git config user.email "[email protected]" && git config user.name "Test" && git commit --allow-empty -m "Initial commit"

cat > .pre-commit-config.yaml <<EOF
repos:
  - repo: local
    hooks:
      - id: rust-test
        name: rust-test
        language: rust
        entry: rustc --version
        language_version: stable
        always_run: true
        pass_filenames: false
EOF

git add .
prek run

This tests prek's ability to download and install Rust from scratch with a toolchain name (rather than explicit version number).

@lmmx lmmx force-pushed the rust-language-support branch from 9c06a6d to b306063 Compare October 28, 2025 22:04
@codecov
Copy link

codecov bot commented Oct 28, 2025

Codecov Report

❌ Patch coverage is 89.18297% with 94 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.70%. Comparing base (8e74998) to head (044310f).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/languages/rust/installer.rs 77.15% 61 Missing ⚠️
src/languages/rust/rust.rs 94.53% 21 Missing ⚠️
src/languages/mod.rs 68.75% 5 Missing ⚠️
src/languages/rust/version.rs 98.38% 3 Missing ⚠️
src/languages/version.rs 66.66% 3 Missing ⚠️
src/store.rs 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #989      +/-   ##
==========================================
+ Coverage   89.66%   89.70%   +0.03%     
==========================================
  Files          74       77       +3     
  Lines       13761    14599     +838     
==========================================
+ Hits        12339    13096     +757     
- Misses       1422     1503      +81     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link

github-actions bot commented Oct 28, 2025

📦 Cargo Bloat Comparison

Binary size change: +1.23% (16.2 MiB → 16.4 MiB)

Expand for cargo-bloat output

Head Branch Results

 File  .text     Size          Crate Name
 0.6%   1.3% 101.3KiB          prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.6%   1.3%  99.7KiB           prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.7%  54.6KiB           prek prek::archive::unpack::{{closure}}
 0.3%   0.7%  53.0KiB             h2 h2::proto::connection::Connection<T,P,B>::poll
 0.3%   0.6%  48.5KiB           prek prek::run::{{closure}}
 0.2%   0.5%  40.0KiB           prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.2%   0.5%  39.2KiB          prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.2%   0.5%  37.3KiB regex_automata regex_automata::meta::strategy::new
 0.2%   0.5%  35.2KiB           prek prek::workspace::Workspace::discover
 0.2%   0.4%  30.1KiB           prek prek::cli::run::run::run::{{closure}}
 0.2%   0.4%  28.8KiB           prek prek::languages::node::installer::NodeInstaller::install::{{closure}}
 0.2%   0.4%  28.1KiB             h2 h2::proto::connection::DynConnection<B>::recv_frame
 0.2%   0.4%  27.6KiB           prek prek::identify::by_extension::{{closure}}
 0.2%   0.3%  26.1KiB           prek <prek::languages::rust::rust::Rust as prek::languages::LanguageImpl>::install::{{closure}}
 0.1%   0.3%  25.1KiB           prek prek::main
 0.1%   0.3%  24.4KiB     hyper_util hyper_util::client::legacy::client::Client<C,B>::send_request::{{closure}}
 0.1%   0.3%  24.4KiB           std? <core::marker::PhantomData<T> as serde_core::de::DeserializeSeed>::deserialize
 0.1%   0.3%  24.3KiB     hyper_util hyper_util::client::legacy::client::Client<C,B>::connect_to::{{closure}}::{{closure}}::{{closure}}
 0.1%   0.3%  24.2KiB           prek prek::hook::HookBuilder::build::{{closure}}
 0.1%   0.3%  23.9KiB          hyper hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_loop
40.6%  88.7%   6.7MiB                And 10377 smaller methods. Use -n N to show more.
45.8% 100.0%   7.5MiB                .text section size, the file size is 16.4MiB

Base Branch Results

 File  .text     Size          Crate Name
 0.6%   1.3% 101.3KiB          prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.5%   1.2%  90.3KiB           prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.7%  54.6KiB           prek prek::archive::unpack::{{closure}}
 0.3%   0.7%  53.0KiB             h2 h2::proto::connection::Connection<T,P,B>::poll
 0.3%   0.6%  48.5KiB           prek prek::run::{{closure}}
 0.2%   0.5%  39.2KiB          prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.2%   0.5%  37.3KiB regex_automata regex_automata::meta::strategy::new
 0.2%   0.5%  35.2KiB           prek prek::workspace::Workspace::discover
 0.2%   0.4%  30.1KiB           prek prek::cli::run::run::run::{{closure}}
 0.2%   0.4%  29.4KiB           prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.2%   0.4%  28.8KiB           prek prek::languages::node::installer::NodeInstaller::install::{{closure}}
 0.2%   0.4%  28.1KiB             h2 h2::proto::connection::DynConnection<B>::recv_frame
 0.2%   0.4%  27.6KiB           prek prek::identify::by_extension::{{closure}}
 0.2%   0.3%  25.1KiB           prek prek::main
 0.1%   0.3%  24.4KiB     hyper_util hyper_util::client::legacy::client::Client<C,B>::send_request::{{closure}}
 0.1%   0.3%  24.4KiB           std? <core::marker::PhantomData<T> as serde_core::de::DeserializeSeed>::deserialize
 0.1%   0.3%  24.3KiB     hyper_util hyper_util::client::legacy::client::Client<C,B>::connect_to::{{closure}}::{{closure}}::{{closure}}
 0.1%   0.3%  24.1KiB           prek prek::hook::HookBuilder::build::{{closure}}
 0.1%   0.3%  23.9KiB          hyper hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_loop
 0.1%   0.3%  23.9KiB        globset globset::GlobSetBuilder::build
40.5%  88.8%   6.6MiB                And 10238 smaller methods. Use -n N to show more.
45.6% 100.0%   7.4MiB                .text section size, the file size is 16.2MiB

@github-actions

This comment was marked as outdated.

@lmmx lmmx force-pushed the rust-language-support branch 2 times, most recently from ffd11de to beab6c1 Compare October 28, 2025 23:08
@lmmx lmmx marked this pull request as ready for review October 29, 2025 02:47
@lmmx lmmx changed the title [DRAFT] Rust language support (WIP) Rust language support Oct 29, 2025
@lmmx

This comment was marked as resolved.

@lmmx lmmx force-pushed the rust-language-support branch from e74a5a9 to a5b5261 Compare October 29, 2025 09:58
@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

So we are rolling, I included a very simple demo to run it in a Docker container too in #989 if anyone wants to test in particular scenarios of interest

The first thing that comes to mind for me is that the error message when you don't have rustup on your machine is not very helpful. The CI has rustup pre-installed, if you don't have it you now get:

error: Failed to install hook `rust-test`
  caused by: Failed to install rust
  caused by: run command `install toolchain` failed
  caused by: No such file or directory (os error 2)

Perhaps we could give a hint (hey, you might want to go get rustup)? Maybe drop a link to our/their docs?

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

Now we get a little further by using the installed rustup binary path instead of relying on PATH.

When rustup is downloaded and installed under CARGO_HOME/bin, use the full path to that binary for toolchain installation instead of assuming rustup is in PATH. That fixes this flat out failure in clean envs without a system rustup.

Initialized empty Git repository in /test-project/.git/
[master (root-commit) d6d1b39] Initial commit
error: Failed to install hook `rust-test`
  caused by: Failed to install rust
  caused by: command `rustc version` exited with an error:

[status]
exit status: 1

[stderr]
error: rustup could not choose a version of rustc to run, because one wasn't specified explicitly, and no default is configured.
help: run 'rustup default stable' to download the latest stable release of Rust and set it as your default toolchain.

Instead we get an issue that rustup was not configured, i.e. we need to set the RUSTUP_TOOLCHAIN env var when running rustc --version in fill_version()...

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

Trace in the container shows still not managing to set the rust version specifier (still unfilled at 0.0.0)

TRACE Found matching installed rust name=stable
TRACE Found installed rust rust=/root/.cache/prek/tools/rust/stable/bin/[email protected]
TRACE Released lock path=/root/.cache/prek/tools/rust/.lock
Click to show full trace

root@5cd5e0832f53:/test-project# prek run --log-file out.log
rust-test................................................................error: Failed to run hook `rust-test`
  caused by: run command `rust hook` failed
  caused by: No such file or directory (os error 2)
root@5cd5e0832f53:/test-project# cat out.log 
2025-10-29T11:05:49.837162Z DEBUG prek: 0.2.12+82 (6298b6422 2025-10-29)
2025-10-29T11:05:49.837226Z DEBUG Args: ["prek", "run", "--log-file", "out.log"]
2025-10-29T11:05:49.838062Z DEBUG Git root: /test-project
2025-10-29T11:05:49.838093Z TRACE Executing `/usr/bin/git ls-files --unmerged`
2025-10-29T11:05:49.838892Z DEBUG Found workspace root at `/test-project`
2025-10-29T11:05:49.838936Z TRACE Include selectors: ``
2025-10-29T11:05:49.838952Z TRACE Skip selectors: ``
2025-10-29T11:05:49.839099Z DEBUG discover{root="/test-project" config=None refresh=false}: Loaded workspace from cache
2025-10-29T11:05:49.839146Z DEBUG discover{root="/test-project" config=None refresh=false}: Loading project configuration path=.pre-commit-config.yaml
2025-10-29T11:05:49.839418Z TRACE discover{root="/test-project" config=None refresh=false}: close time.busy=398µs time.idle=9.38µs
2025-10-29T11:05:49.839478Z TRACE Executing `/usr/bin/git diff --exit-code --name-only -z /test-project/.pre-commit-config.yaml`
2025-10-29T11:05:49.840507Z TRACE Checking lock resource="store" path=/root/.cache/prek/.lock
2025-10-29T11:05:49.840549Z DEBUG Acquired lock resource="store"
2025-10-29T11:05:49.840730Z DEBUG Hooks going to run: ["rust-test"]
2025-10-29T11:05:49.841166Z DEBUG No matching environment found for hook `rust-test`, installing...
2025-10-29T11:05:49.841352Z TRACE Checking lock resource="rust" path=/root/.cache/prek/tools/rust/.lock
2025-10-29T11:05:49.841380Z DEBUG Acquired lock resource="rust"
2025-10-29T11:05:49.841444Z TRACE Found matching installed rust name=stable
2025-10-29T11:05:49.841469Z TRACE Found installed rust rust=/root/.cache/prek/tools/rust/stable/bin/[email protected]
2025-10-29T11:05:49.841493Z TRACE Released lock path=/root/.cache/prek/tools/rust/.lock
2025-10-29T11:05:49.841754Z DEBUG Installed hook `rust-test` in `/root/.cache/prek/hooks/rust-9Q4382XpTXuc3b6VIOAi`
2025-10-29T11:05:49.841827Z TRACE Released lock path=/root/.cache/prek/.lock
2025-10-29T11:05:49.841866Z TRACE Executing `/usr/bin/git diff --diff-filter=A --name-only -z -- /test-project`
2025-10-29T11:05:49.842607Z TRACE Executing `/usr/bin/git write-tree`
2025-10-29T11:05:49.843324Z TRACE Executing `/usr/bin/git diff-index --binary --exit-code 5dfbb7d39992eee87c32ee9c4d8d355653d23f98 -- /test-project`
2025-10-29T11:05:49.844153Z DEBUG Working tree is clean
2025-10-29T11:05:49.844182Z TRACE Executing `/usr/bin/git rev-parse --git-dir`
2025-10-29T11:05:49.844845Z TRACE Executing `cd /test-project && /usr/bin/git diff --cached --name-only --diff-filter=ACMRTUXB -z`
2025-10-29T11:05:49.845736Z DEBUG Staged files: 1
2025-10-29T11:05:49.845776Z TRACE Executing `/usr/bin/git diff -- /test-project`
2025-10-29T11:05:49.847297Z TRACE Files for project `.` after filtered: 1
2025-10-29T11:05:49.847700Z TRACE Files for hook `rust-test` after filtered: 1
2025-10-29T11:05:49.847783Z TRACE Resolved command: rustc
2025-10-29T11:05:49.847814Z TRACE Running rust-test total_files=0 concurrency=20
2025-10-29T11:05:49.847911Z TRACE Executing `cd /test-project && rustc --version`

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

Progress! Installation now queries version for cached toolchains

TRACE Found matching installed rust name=stable
TRACE Found installed rust rust=/root/.cache/prek/tools/rust/stable/bin/[email protected]
TRACE Executing `/root/.cache/prek/tools/rust/stable/bin/rustc --version`
TRACE Released lock path=/root/.cache/prek/tools/rust/.lock

Version is being queried:

Executing /root/.cache/prek/tools/rust/stable/bin/rustc --version

32f710e:

fix(rust): query version for cached Rust installations using RUSTUP_TOOLCHAIN

When reusing a cached Rust installation, extract the toolchain name from
the installation path and call fill_version_with_toolchain() to query the
actual version. This ensures the version is populated correctly instead of
remaining at the default 0.0.0, which would cause runtime errors when
RUSTUP_TOOLCHAIN is set to "0.0.0" during hook execution.

Installation succeeds but then execution still fails:

TRACE Resolved command: rustc
TRACE Running rust-test total_files=0 concurrency=20
TRACE Executing `cd /test-project && rustc --version`

then no more trace but hook fail in main output

root@1f947719483b:/test-project# prek run --log-file out.log
rust-test................................................................error: Failed to run hook `rust-test`
  caused by: run command `rust hook` failed
  caused by: No such file or directory (os error 2)
Click to show full trace

root@1f947719483b:/test-project# cat out.log 
2025-10-29T11:16:53.062358Z DEBUG prek: 0.2.12+83 (d3a3e10ae 2025-10-29)
2025-10-29T11:16:53.062420Z DEBUG Args: ["prek", "run", "--log-file", "out.log"]
2025-10-29T11:16:53.063329Z DEBUG Git root: /test-project
2025-10-29T11:16:53.063360Z TRACE Executing `/usr/bin/git ls-files --unmerged`
2025-10-29T11:16:53.064137Z DEBUG Found workspace root at `/test-project`
2025-10-29T11:16:53.064188Z TRACE Include selectors: ``
2025-10-29T11:16:53.064203Z TRACE Skip selectors: ``
2025-10-29T11:16:53.064390Z DEBUG discover{root="/test-project" config=None refresh=false}: Loaded workspace from cache
2025-10-29T11:16:53.064448Z DEBUG discover{root="/test-project" config=None refresh=false}: Loading project configuration path=.pre-commit-config.yaml
2025-10-29T11:16:53.064792Z TRACE discover{root="/test-project" config=None refresh=false}: close time.busy=499µs time.idle=9.11µs
2025-10-29T11:16:53.064856Z TRACE Executing `/usr/bin/git diff --exit-code --name-only -z /test-project/.pre-commit-config.yaml`
2025-10-29T11:16:53.065834Z TRACE Checking lock resource="store" path=/root/.cache/prek/.lock
2025-10-29T11:16:53.065909Z DEBUG Acquired lock resource="store"
2025-10-29T11:16:53.066067Z DEBUG Hooks going to run: ["rust-test"]
2025-10-29T11:16:53.066351Z DEBUG No matching environment found for hook `rust-test`, installing...
2025-10-29T11:16:53.066548Z TRACE Checking lock resource="rust" path=/root/.cache/prek/tools/rust/.lock
2025-10-29T11:16:53.066575Z DEBUG Acquired lock resource="rust"
2025-10-29T11:16:53.066776Z TRACE Found matching installed rust name=stable
2025-10-29T11:16:53.066803Z TRACE Found installed rust rust=/root/.cache/prek/tools/rust/stable/bin/[email protected]
2025-10-29T11:16:53.066847Z TRACE Executing `/root/.cache/prek/tools/rust/stable/bin/rustc --version`
2025-10-29T11:16:53.101510Z TRACE Released lock path=/root/.cache/prek/tools/rust/.lock
2025-10-29T11:16:53.102035Z DEBUG Installed hook `rust-test` in `/root/.cache/prek/hooks/rust-XVlw0LbPFjeuxvWF6kqe`
2025-10-29T11:16:53.102197Z TRACE Released lock path=/root/.cache/prek/.lock
2025-10-29T11:16:53.102232Z TRACE Executing `/usr/bin/git diff --diff-filter=A --name-only -z -- /test-project`
2025-10-29T11:16:53.103136Z TRACE Executing `/usr/bin/git write-tree`
2025-10-29T11:16:53.103981Z TRACE Executing `/usr/bin/git diff-index --binary --exit-code 5dfbb7d39992eee87c32ee9c4d8d355653d23f98 -- /test-project`
2025-10-29T11:16:53.104876Z DEBUG Working tree is clean
2025-10-29T11:16:53.104909Z TRACE Executing `/usr/bin/git rev-parse --git-dir`
2025-10-29T11:16:53.105534Z TRACE Executing `cd /test-project && /usr/bin/git diff --cached --name-only --diff-filter=ACMRTUXB -z`
2025-10-29T11:16:53.106431Z DEBUG Staged files: 1
2025-10-29T11:16:53.106480Z TRACE Executing `/usr/bin/git diff -- /test-project`
2025-10-29T11:16:53.108322Z TRACE Files for project `.` after filtered: 1
2025-10-29T11:16:53.108747Z TRACE Files for hook `rust-test` after filtered: 1
2025-10-29T11:16:53.108835Z TRACE Resolved command: rustc
2025-10-29T11:16:53.108864Z TRACE Running rust-test total_files=0 concurrency=20
2025-10-29T11:16:53.108980Z TRACE Executing `cd /test-project && rustc --version`

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

aaand success in the container 🎉

[master (root-commit) c4dd197] Initial commit
rust-test................................................................Passed

I needed to append both rustc and rustc_bin to the PATH, as done for Go:

let new_path = prepend_paths(&[&go_bin, go_root_bin]).context("Failed to join PATH")?;

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

I expected that container success to mean the CI language_version test pass but it didn't

  • When system rustup exists in PATH, we were skipping the download but then trying to use a non-existent local rustup binary
  • Now we check if rustup exists at the expected CARGO_HOME/bin location before attempting a download, so we ensure rustup is always available at the path we use for toolchain installation

This (61298df) now fixes that CI failure where system rustup caused us to skip installation but then the local binary didn't exist for fill_version_with_toolchain() to use.

        PASS [  10.235s] prek::languages node::language_version

@lmmx lmmx force-pushed the rust-language-support branch from e5b4265 to a40c2f1 Compare October 29, 2025 12:29
@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

insta is being difficult 🤨

-  rustc 1.X
+  rustc 1.X 

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

phew, final test failure to solve (this one can be repro'd locally in regular tests)

     Summary [ 205.042s] 282 tests run: 281 passed (2 slow), 1 failed, 1 skipped
        SLOW [ 182.029s] prek::languages rust::additional_dependencies_cli
        SLOW [  85.531s] prek::languages rust::language_version
        FAIL [   0.434s] prek::languages rust::local_with_lib_deps

@lmmx lmmx force-pushed the rust-language-support branch from 2785b5b to 59f9f52 Compare October 29, 2025 16:23
@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

  # Link checker using local hooks with language: rust
  # Pre-commit will automatically install lychee via cargo
  - repo: local
    hooks:
      - id: lychee
        name: lychee (local links only)
        entry: lychee
        language: rust
        additional_dependencies: ["cli:lychee:0.20.1"]
        files: \.(md|rst)$
        exclude: ^web/website/themes/
        args:
          - --no-progress
          # For PRs: whitelist PRQL domains and local files only
          # Pattern matches:
          #   - github.com/PRQL/* and github.com/prql/*
          #   - prql-lang.org/*
          #   - raw.githubusercontent.com/PRQL/* and raw.githubusercontent.com/prql/*
          #   - file://* (local/relative links)
          # All other external links are skipped for faster PR checks
          - --include=^(https://(github\.com/(PRQL|prql)|prql-lang\.org|raw\.githubusercontent\.com/(PRQL|prql))|file://)
      - id: lychee-all
        name: lychee-all (all links)
        entry: lychee
        language: rust
        additional_dependencies: ["cli:lychee:0.20.1"]
        stages: [manual]
        files: \.(md|rst)$
        exclude: ^web/website/themes/
        args: ["--config=.config/lychee.toml", "--no-progress"]

@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

ok it looks it does work with the additional deps, phew 🎉

louis 🌟 ~/lab/prek-experiment/prql $ runpk
lychee (local links only)................................................Passed
louis 🌟 ~/lab/prek-experiment/prql $ runpc
lychee (local links only)................................................Passed
louis 🌟 ~/lab/prek-experiment/prql $ time runpc --verbose
lychee (local links only)................................................Passed
- hook id: lychee
- duration: 5.57s

🔍 7 Total (in 0s) ✅ 3 OK 🚫 0 Errors 👻 4 Excluded
🔍 4 Total (in 0s) ✅ 3 OK 🚫 0 Errors 👻 1 Excluded
🔍 27 Total (in 0s) ✅ 11 OK 🚫 0 Errors 👻 16 Excluded
🔍 11 Total (in 0s) ✅ 6 OK 🚫 0 Errors 👻 5 Excluded
🔍 82 Total (in 0s) ✅ 80 OK 🚫 0 Errors 👻 2 Excluded
🔍 23 Total (in 0s) ✅ 19 OK 🚫 0 Errors 👻 4 Excluded
🔍 63 Total (in 0s) ✅ 26 OK 🚫 0 Errors 👻 37 Excluded
🔍 56 Total (in 0s) ✅ 45 OK 🚫 0 Errors 👻 11 Excluded
🔍 7 Total (in 0s) ✅ 5 OK 🚫 0 Errors 👻 2 Excluded
🔍 9 Total (in 0s) ✅ 5 OK 🚫 0 Errors 👻 4 Excluded
🔍 41 Total (in 0s) ✅ 20 OK 🚫 0 Errors 👻 21 Excluded
🔍 13 Total (in 0s) ✅ 4 OK 🚫 0 Errors 👻 9 Excluded
🔍 51 Total (in 0s) ✅ 30 OK 🚫 0 Errors 👻 21 Excluded
   [WARN ] Error creating request: InvalidPathToUri("/#bindings")
🔍 55 Total (in 0s) ✅ 16 OK 🚫 0 Errors 👻 39 Excluded
🔍 10 Total (in 0s) ✅ 1 OK 🚫 0 Errors 👻 9 Excluded
🔍 51 Total (in 0s) ✅ 17 OK 🚫 0 Errors 👻 34 Excluded
🔍 9 Total (in 0s) ✅ 4 OK 🚫 0 Errors 👻 5 Excluded
🔍 12 Total (in 0s) ✅ 12 OK 🚫 0 Errors


real    0m5.708s
user    0m2.863s
sys     0m0.324s
louis 🌟 ~/lab/prek-experiment/prql $ time runpk --verbose
lychee (local links only)................................................Passed
- hook id: lychee
- duration: 5.00s
  🔍 2 Total (in 0s) ✅ 0 OK 🚫 0 Errors 👻 2 Excluded
  🔍 44 Total (in 1s) ✅ 22 OK 🚫 0 Errors 👻 22 Excluded
  🔍 24 Total (in 0s) ✅ 16 OK 🚫 0 Errors 👻 8 Excluded
  🔍 50 Total (in 1s) ✅ 23 OK 🚫 0 Errors 👻 27 Excluded
  🔍 10 Total (in 1s) ✅ 7 OK 🚫 0 Errors 👻 3 Excluded
  🔍 78 Total (in 0s) ✅ 77 OK 🚫 0 Errors 👻 1 Excluded
  🔍 75 Total (in 1s) ✅ 40 OK 🚫 0 Errors 👻 35 Excluded
  🔍 43 Total (in 0s) ✅ 27 OK 🚫 0 Errors 👻 16 Excluded
     [WARN ] Error creating request: InvalidPathToUri("/#bindings")
  🔍 36 Total (in 0s) ✅ 5 OK 🚫 0 Errors 👻 31 Excluded
  🔍 2 Total (in 1s) ✅ 1 OK 🚫 0 Errors 👻 1 Excluded
  🔍 26 Total (in 1s) ✅ 17 OK 🚫 0 Errors 👻 9 Excluded
  🔍 15 Total (in 0s) ✅ 10 OK 🚫 0 Errors 👻 5 Excluded
  🔍 70 Total (in 4s) ✅ 29 OK 🚫 0 Errors 👻 41 Excluded
  🔍 20 Total (in 0s) ✅ 15 OK 🚫 0 Errors 👻 5 Excluded
  🔍 12 Total (in 0s) ✅ 5 OK 🚫 0 Errors 👻 7 Excluded
  🔍 5 Total (in 0s) ✅ 1 OK 🚫 0 Errors 👻 4 Excluded
  🔍 16 Total (in 0s) ✅ 11 OK 🚫 0 Errors 👻 5 Excluded
  🔍 3 Total (in 0s) ✅ 1 OK 🚫 0 Errors 👻 2 Excluded

real    0m5.026s
user    0m2.768s
sys     0m0.322s

(No speed difference)

Putting this back as draft and will amend that test later

@lmmx lmmx marked this pull request as draft October 29, 2025 16:44
@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

That should do it... 5e543d5 uses a cli hook

This would get much faster with cargo binstall. That's a priority now I think (ongoing PR for this in pre-commit)

edit it says the operation was cancelled (it seems to have timed out after 4m29s spent cargo testing)

Screenshot from 2025-10-29 17-34-17

Unsure if this is the Lua service unavailable or the timeout after "10m0s"... which would be the Windows run... maybe a transient CI failure?

@lmmx lmmx marked this pull request as ready for review October 29, 2025 17:19
@lmmx
Copy link
Collaborator Author

lmmx commented Oct 29, 2025

Arg, going to have to find other cli libs, it looks like it's too slow... The jobs are all timing out at their limit. (I have to head out now, will complete later)

I'd instead switch to a no-dep very small CLI tool (one with just plain main.rs no clap etc would suit). Good to know that it works though!

I'm leaving a request for testers in the Astral Discord where people showed interest in this!

cargo install --git https://github.com/lmmx/prek --branch rust-language-support

@j178
Copy link
Owner

j178 commented Oct 30, 2025

Thanks for all the hard work!

We can create a minimal test repo for Rust at https://github.com/orgs/prek-test-repos/repositories - I sent you an invitation to the org.

For #681, it’d be better to handle that in another PR since this one’s getting pretty big already.

@lmmx

This comment was marked as resolved.

@lmmx

This comment was marked as resolved.

@lmmx
Copy link
Collaborator Author

lmmx commented Nov 30, 2025

For pytest-mimic (the PR with the updated action-validator hook rev), running hooks is now 3x faster with prek than with pre-commit 😎

Benchmark 1: prek
  Time (mean ± σ):      66.1 ms ±   2.0 ms    [User: 57.0 ms, System: 44.2 ms]
  Range (min … max):    63.9 ms …  76.2 ms    39 runs
 
Benchmark 2: pre-commit
  Time (mean ± σ):     194.9 ms ±   2.4 ms    [User: 150.9 ms, System: 54.4 ms]
  Range (min … max):   190.2 ms … 199.7 ms    15 runs
 
Summary
  prek ran
    2.95 ± 0.10 times faster than pre-commit

cloudstack takes a long time to run (9s) 😴 that is still 3x faster than with pre-commit (29s). Life's too short to hyperfine that (would take mins+).

robustmq exitted with non-zero exit code on the first run, so hyperfine didn't want to benchmark it. Not entirely sure what was going wrong there (clang is erroring out) but pre-commit does the same. prek takes 5.6s and pre-commit takes 5.9s - so some speedup. About 5% faster.

shiro runs 25% faster with prek 🎉

Benchmark 1: prek
  Time (mean ± σ):      1.260 s ±  0.017 s    [User: 12.321 s, System: 1.727 s]
  Range (min … max):    1.244 s …  1.301 s    10 runs
 
Benchmark 2: pre-commit
  Time (mean ± σ):      1.598 s ±  0.018 s    [User: 11.916 s, System: 1.985 s]
  Range (min … max):    1.574 s …  1.626 s    10 runs
 
Summary
  prek ran
    1.27 ± 0.02 times faster than pre-commit

@lmmx
Copy link
Collaborator Author

lmmx commented Nov 30, 2025

I was wondering if prek itself could now use a Rust hook, for the typos linter. It doesn't look like that typos-src id hook actually works though (it fails on pre-commit too)...

If I swap the typos hook to id: typos-src (the Rust hook) it gives me an error

error: Failed to install hook `typos-src`
  caused by: No package found for binary 'typos' in workspace /home/louis/.cache/prek/repos/dc5b9ba628059e1c

That doesn't match what pre-commit gives, but pre-commit does error too:

louis 🌟 ~/dev/prek $ runpc
[INFO] Installing environment for https://github.com/crate-ci/typos.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: command: ('/home/louis/.cargo/bin/cargo', 'install', '--bins', '--root', '/home/louis/.cache/pre-commit/repoory1a_u9/rustenv-system', '--path', '.')
return code: 101
stdout: (none)
stderr:
    error: found a virtual manifest at `/home/louis/.cache/pre-commit/repoory1a_u9/Cargo.toml` instead of a package manifest
Check the log at /home/louis/.cache/pre-commit/pre-commit.log

Deleting the caches of both prek/pre-commit did not heal it so I assume it isn't functional.

@lmmx lmmx force-pushed the rust-language-support branch from 875e25e to 536fd59 Compare November 30, 2025 16:09
@lmmx
Copy link
Collaborator Author

lmmx commented Nov 30, 2025

I also wanted to test on some of these 'rust for web' repos, e.g. radix

The initial hook repo clone setup for radix with pre-commit takes an inordinately long time: 3m30s

Unfortunately something is amiss with prek in the Rust hook support here and it is erroring out

error: Failed to install hook `cargo-deny`
  caused by: No package found for binary 'cargo-deny' in workspace /home/louis/.cache/prek/repos/cf7add05aefbce7f

real    0m3.229s
user    0m0.534s
sys     0m0.395s

the issue here is cargo-deny has a root level Cargo.toml that is both a workspace and a package, and the find_package_dir didn't consider that situation...

  • edit fixed in 3fb1802
  • note: this did not change the typos-src situation

hook installation

  • Pre-commit installs the hook repos in 2m37s
  • Prek installs the hook repos in 2m29s

Not significantly faster, but consistent! 👍

after installation

hyperfine -n prek 'prek run -a' -n pre-commit 'pre-commit run -a' -i
  • This one needs -i as it fails on the trunk (they have not been running their own pre-commit hooks!)

The time to run is exactly the same 🙃

Benchmark 1: prek
  Time (mean ± σ):     11.301 s ±  0.121 s    [User: 54.289 s, System: 48.520 s]
  Range (min … max):   11.179 s … 11.511 s    10 runs
 
Benchmark 2: pre-commit
  Time (mean ± σ):     11.421 s ±  0.111 s    [User: 54.387 s, System: 48.558 s]
  Range (min … max):   11.235 s … 11.586 s    10 runs
 
Summary
  prek ran
    1.01 ± 0.01 times faster than pre-commit

@lmmx
Copy link
Collaborator Author

lmmx commented Nov 30, 2025

OK I think this is feature complete and happy to merge now.

We have basic remote hooks in our repo for testing, the caching works, and I've tested with several repos and the only ones where it didn't work it also didn't work with pre-commit.

To cover the various ways that repos can signal they contain packages I've added unit tests (workspace cargo toml, workspace cargo toml with packages, etc) but I don't think these need dedicated remote repo hook tests.

I think this is ready!

Further development

Follow up PRs:

@j178 j178 force-pushed the rust-language-support branch from 71d3cf7 to 02cb9d5 Compare December 1, 2025 12:10
@lmmx lmmx force-pushed the rust-language-support branch from 46d0fda to 9e3547d Compare December 1, 2025 14:17
@j178 j178 changed the title Rust language support Support Rust language Dec 1, 2025
@j178
Copy link
Owner

j178 commented Dec 1, 2025

Thanks @lmmx! I think this is good to merge now. Here are a few TODOs I might want to tackle next:

  1. Reuse the system’s rustup if it’s already installed
  2. Install rustup into $PREK_HOME/tools/rustup so all the Rust hooks can share it
  3. Set RUSTUP_HOME to $PREK_HOME/tools/rustup so all rustup‑managed toolchains are shared across the hooks

@j178 j178 merged commit 6386de2 into j178:master Dec 1, 2025
21 checks passed
@lmmx lmmx deleted the rust-language-support branch December 1, 2025 14:58
@lmmx
Copy link
Collaborator Author

lmmx commented Dec 1, 2025

Great stuff!

I had a go at these extra goals and they ain't as easy as it looks to get right. Attempted here if it's any use for future reference but getting nothing but test failures 👎 https://github.com/lmmx/prek/tree/rust-support-polish

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support rust language

3 participants