Full Code of j178/prek for AI

master 9328863e032f cached
256 files
2.3 MB
606.0k tokens
2219 symbols
1 requests
Download .txt
Showing preview only (2,418K chars total). Download the full file or copy to clipboard to get everything.
Repository: j178/prek
Branch: master
Commit: 9328863e032f
Files: 256
Total size: 2.3 MB

Directory structure:
gitextract_9_ydfirn/

├── .config/
│   ├── nextest.toml
│   └── taplo.toml
├── .devcontainer/
│   └── devcontainer.json
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.yaml
│   ├── codecov.yml
│   ├── copilot-instructions.md
│   ├── renovate.json5
│   ├── workflows/
│   │   ├── build-binaries.yml
│   │   ├── build-docker.yml
│   │   ├── ci.yml
│   │   ├── performance.yml
│   │   ├── publish-crates.yml
│   │   ├── publish-docs.yml
│   │   ├── publish-homebrew.yml
│   │   ├── publish-npm.yml
│   │   ├── publish-prek-action.yml
│   │   ├── publish-pypi.yml
│   │   ├── publish-winget.yml
│   │   ├── release.yml
│   │   ├── setup-dev-drive.ps1
│   │   ├── sync-identify.yml
│   │   └── zizmor.yml
│   └── zizmor.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.md
├── clippy.toml
├── crates/
│   ├── prek/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── archive.rs
│   │   │   ├── cleanup.rs
│   │   │   ├── cli/
│   │   │   │   ├── auto_update.rs
│   │   │   │   ├── cache_clean.rs
│   │   │   │   ├── cache_gc.rs
│   │   │   │   ├── cache_size.rs
│   │   │   │   ├── completion.rs
│   │   │   │   ├── hook_impl.rs
│   │   │   │   ├── identify.rs
│   │   │   │   ├── install.rs
│   │   │   │   ├── list.rs
│   │   │   │   ├── list_builtins.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── reporter.rs
│   │   │   │   ├── run/
│   │   │   │   │   ├── filter.rs
│   │   │   │   │   ├── keeper.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── run.rs
│   │   │   │   │   └── selector.rs
│   │   │   │   ├── sample_config.rs
│   │   │   │   ├── self_update.rs
│   │   │   │   ├── try_repo.rs
│   │   │   │   ├── validate.rs
│   │   │   │   └── yaml_to_toml.rs
│   │   │   ├── config.rs
│   │   │   ├── fs.rs
│   │   │   ├── git.rs
│   │   │   ├── hook.rs
│   │   │   ├── hooks/
│   │   │   │   ├── builtin_hooks/
│   │   │   │   │   ├── check_json5.rs
│   │   │   │   │   └── mod.rs
│   │   │   │   ├── meta_hooks.rs
│   │   │   │   ├── mod.rs
│   │   │   │   └── pre_commit_hooks/
│   │   │   │       ├── check_added_large_files.rs
│   │   │   │       ├── check_case_conflict.rs
│   │   │   │       ├── check_executables_have_shebangs.rs
│   │   │   │       ├── check_json.rs
│   │   │   │       ├── check_merge_conflict.rs
│   │   │   │       ├── check_symlinks.rs
│   │   │   │       ├── check_toml.rs
│   │   │   │       ├── check_xml.rs
│   │   │   │       ├── check_yaml.rs
│   │   │   │       ├── detect_private_key.rs
│   │   │   │       ├── fix_byte_order_marker.rs
│   │   │   │       ├── fix_end_of_file.rs
│   │   │   │       ├── fix_trailing_whitespace.rs
│   │   │   │       ├── mixed_line_ending.rs
│   │   │   │       ├── mod.rs
│   │   │   │       └── no_commit_to_branch.rs
│   │   │   ├── http.rs
│   │   │   ├── install_source.rs
│   │   │   ├── languages/
│   │   │   │   ├── bun/
│   │   │   │   │   ├── bun.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── deno/
│   │   │   │   │   ├── deno.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── docker.rs
│   │   │   │   ├── docker_image.rs
│   │   │   │   ├── fail.rs
│   │   │   │   ├── golang/
│   │   │   │   │   ├── golang.rs
│   │   │   │   │   ├── gomod.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── haskell.rs
│   │   │   │   ├── julia.rs
│   │   │   │   ├── lua.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── node/
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── node.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── pygrep/
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── pygrep.rs
│   │   │   │   │   └── script.py
│   │   │   │   ├── python/
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── pep723.rs
│   │   │   │   │   ├── pyproject.rs
│   │   │   │   │   ├── python.rs
│   │   │   │   │   ├── uv.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── ruby/
│   │   │   │   │   ├── gem.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── ruby.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── rust/
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── rust.rs
│   │   │   │   │   ├── rustup.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── script.rs
│   │   │   │   ├── swift.rs
│   │   │   │   ├── system.rs
│   │   │   │   └── version.rs
│   │   │   ├── main.rs
│   │   │   ├── printer.rs
│   │   │   ├── process.rs
│   │   │   ├── profiler.rs
│   │   │   ├── resource_limit.rs
│   │   │   ├── run.rs
│   │   │   ├── schema.rs
│   │   │   ├── snapshots/
│   │   │   │   ├── prek__config__tests__language_version.snap
│   │   │   │   ├── prek__config__tests__meta_hooks-5.snap
│   │   │   │   ├── prek__config__tests__numeric_rev_is_parsed_as_string.snap
│   │   │   │   ├── prek__config__tests__parse_hooks-3.snap
│   │   │   │   ├── prek__config__tests__parse_repos-2.snap
│   │   │   │   ├── prek__config__tests__parse_repos-3.snap
│   │   │   │   ├── prek__config__tests__parse_repos-4.snap
│   │   │   │   ├── prek__config__tests__parse_repos-6.snap
│   │   │   │   ├── prek__config__tests__parse_repos.snap
│   │   │   │   ├── prek__config__tests__read_config_with_merge_keys.snap
│   │   │   │   ├── prek__config__tests__read_config_with_nested_merge_keys.snap
│   │   │   │   ├── prek__config__tests__read_manifest.snap
│   │   │   │   ├── prek__config__tests__read_toml_config.snap
│   │   │   │   └── prek__config__tests__read_yaml_config.snap
│   │   │   ├── store.rs
│   │   │   ├── version.rs
│   │   │   ├── warnings.rs
│   │   │   ├── workspace.rs
│   │   │   └── yaml.rs
│   │   └── tests/
│   │       ├── auto_update.rs
│   │       ├── builtin_hooks.rs
│   │       ├── cache.rs
│   │       ├── common/
│   │       │   └── mod.rs
│   │       ├── fixtures/
│   │       │   ├── go.yaml
│   │       │   ├── issue227.yaml
│   │       │   ├── issue253/
│   │       │   │   ├── biome.json
│   │       │   │   ├── input.json
│   │       │   │   └── issue253.yaml
│   │       │   ├── issue265.yaml
│   │       │   ├── node-dependencies.yaml
│   │       │   ├── node-version.yaml
│   │       │   ├── python-version.yaml
│   │       │   ├── repeated-repos.yaml
│   │       │   ├── uv-pre-commit-config.yaml
│   │       │   └── uv-pre-commit-hooks.yaml
│   │       ├── hook_impl.rs
│   │       ├── identify.rs
│   │       ├── install.rs
│   │       ├── languages/
│   │       │   ├── bun.rs
│   │       │   ├── deno.rs
│   │       │   ├── docker.rs
│   │       │   ├── docker_image.rs
│   │       │   ├── fail.rs
│   │       │   ├── golang.rs
│   │       │   ├── haskell.rs
│   │       │   ├── julia.rs
│   │       │   ├── lua.rs
│   │       │   ├── main.rs
│   │       │   ├── node.rs
│   │       │   ├── pygrep.rs
│   │       │   ├── python.rs
│   │       │   ├── ruby.rs
│   │       │   ├── rust.rs
│   │       │   ├── script.rs
│   │       │   ├── swift.rs
│   │       │   ├── unimplemented.rs
│   │       │   └── unsupported.rs
│   │       ├── list.rs
│   │       ├── list_builtins.rs
│   │       ├── meta_hooks.rs
│   │       ├── run.rs
│   │       ├── sample_config.rs
│   │       ├── skipped_hooks.rs
│   │       ├── try_repo.rs
│   │       ├── validate.rs
│   │       ├── workspace.rs
│   │       └── yaml_to_toml.rs
│   ├── prek-consts/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── env_vars.rs
│   │       └── lib.rs
│   ├── prek-identify/
│   │   ├── Cargo.toml
│   │   ├── gen.py
│   │   └── src/
│   │       ├── lib.rs
│   │       └── tags.rs
│   └── prek-pty/
│       ├── Cargo.toml
│       ├── LICENSE
│       └── src/
│           ├── error.rs
│           ├── lib.rs
│           ├── pty.rs
│           ├── sys.rs
│           └── types.rs
├── dist-workspace.toml
├── docs/
│   ├── assets/
│   │   └── badge-v0.json
│   ├── authoring-hooks.md
│   ├── benchmark.md
│   ├── builtin.md
│   ├── changelog.md
│   ├── cli.md
│   ├── compatibility.md
│   ├── configuration.md
│   ├── debugging.md
│   ├── diff.md
│   ├── faq.md
│   ├── index.md
│   ├── installation.md
│   ├── integrations.md
│   ├── languages.md
│   ├── proposals/
│   │   └── concurrency.md
│   ├── quickstart.md
│   ├── requirements.in
│   ├── requirements.txt
│   └── workspace.md
├── licenses/
│   ├── LICENSE.identify.txt
│   └── LICENSE.pre-commit.txt
├── mise.toml
├── mkdocs.yml
├── prek.schema.json
├── pyproject.toml
├── python/
│   └── prek/
│       ├── __init__.py
│       ├── __main__.py
│       └── _find_prek.py
├── rust-toolchain.toml
└── scripts/
    ├── hyperfine-run-benchmarks.sh
    ├── hyperfine-setup-test-env.sh
    ├── macports/
    │   └── Portfile
    └── update-macports-portfile.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .config/nextest.toml
================================================
[profile.ci-core]
# Exclude language-specific integration tests from the main CI runs (except unimplemented/unsupported/script/fail/pygrep).
default-filter = "not binary_id(prek::languages) or (binary_id(prek::languages) and (test(unimplemented::) or test(unsupported::) or test(script::) or test(fail::) or test(pygrep::)))"
status-level = "skip"
final-status-level = "slow"
failure-output = "immediate"
fail-fast = false
test-threads = 8

[profile.lang-bun]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(bun::)"

[profile.lang-deno]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(deno::)"

[profile.lang-docker]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and (test(docker::) or test(docker_image::))"

[profile.lang-golang]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(golang::)"

[profile.lang-haskell]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(haskell::)"

[profile.lang-julia]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(julia::)"

[profile.lang-lua]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(lua::)"
# LuaRocks can hit a race condition when multiple processes are installing the same package; run Lua tests serially.
threads-required = "num-cpus"

[profile.lang-node]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(node::)"

[profile.lang-python]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(python::)"

[profile.lang-ruby]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(ruby::)"

[profile.lang-rust]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(rust::)"

[profile.lang-swift]
inherits = "ci-core"
default-filter = "binary_id(prek::languages) and test(swift::)"


================================================
FILE: .config/taplo.toml
================================================
[formatting]
align_comments = false


================================================
FILE: .devcontainer/devcontainer.json
================================================
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/rust
{
  "name": "prek",
  // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
  "image": "mcr.microsoft.com/devcontainers/rust:1-1-bookworm",
  "hostRequirements": {
   "cpus": 4,
   "memory": "16gb",
   "storage": "32gb"
  },
  "features": {
    "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
    "ghcr.io/devcontainers/features/github-cli:1": {},
    "ghcr.io/devcontainers-extra/features/mise:1": {},
    "ghcr.io/devcontainers-extra/features/uv:1": {},
  }
  // Use 'mounts' to make the cargo cache persistent in a Docker Volume.
  // "mounts": [
  // 	{
  // 		"source": "devcontainer-cargo-cache-${devcontainerId}",
  // 		"target": "/usr/local/cargo",
  // 		"type": "volume"
  // 	}
  // ]
  // Features to add to the dev container. More info: https://containers.dev/features.
  // "features": {},
  // Use 'forwardPorts' to make a list of ports inside the container available locally.
  // "forwardPorts": [],
  // Use 'postCreateCommand' to run commands after the container is created.
  // "postCreateCommand": "rustc --version",
  // Configure tool-specific properties.
  // "customizations": {},
  // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
  // "remoteUser": "root"
}


================================================
FILE: .gitattributes
================================================
# Ensure consistent line endings across platforms (avoid LF -> CRLF on Windows)
* text=auto eol=lf

prek.schema.json linguist-generated=true
scripts/macports/Portfile linguist-generated=true


================================================
FILE: .github/CODEOWNERS
================================================
* @j178


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yaml
================================================
name: Bug report
description: Create a report to help us improve prek
body:
  - type: textarea
    attributes:
      label: Summary
      description: |
        A clear and concise description of the bug, including a minimal reproducible example.
        If we cannot reproduce the bug, it is unlikely that we will be able to help you.
    validations:
      required: true

  - type: checkboxes
    attributes:
      label: Willing to submit a PR?
      description: |
        If you have time, we welcome pull requests.
      options:
        - label: Yes — I’m willing to open a PR to fix this.

  - type: input
    attributes:
      label: Platform
      description: What operating system and architecture are you using? (see `uname -orsm`)
      placeholder: e.g., macOS 14 arm64, Windows 11 x86_64, Ubuntu 20.04 amd64
    validations:
      required: true

  - type: input
    attributes:
      label: Version
      description: What version of prek are you using? (see `prek -V`)
      placeholder: e.g., prek 0.2.3 (7fe75a86d 2025-09-29)
    validations:
      required: true

  - type: textarea
    attributes:
      label: .pre-commit-config.yaml
      description: |
        Please attach or paste the contents of your `.pre-commit-config.yaml` file if relevant.
      value: |
        ```yaml

        ```
    validations:
      required: true

  - type: textarea
    attributes:
      label: Log file
      description: |
        Please attach or paste the contents of the trace log file located at:
        - Linux/macOS: `~/.cache/prek/prek.log`
        - Windows: `%LOCALAPPDATA%\prek\prek.log`
        If the log file doesn't exist or is empty, please run your command with increased verbosity:
        ```bash
        prek -vvv [your command]
        ```
      value: |
        ```

        ```
    validations:
      required: true


================================================
FILE: .github/codecov.yml
================================================
coverage:
  status:
    project:
      default:
        target: auto
        threshold: 1%
        informational: true
    patch:
      default:
        target: auto
        threshold: 1%
        informational: true

ignore:
  - "tests/**/*"
  - "examples/**/*"
  - "target/**/*"
  - "crates/prek-pty/**/*"
  - "crates/prek-yaml/**/*"


================================================
FILE: .github/copilot-instructions.md
================================================
# Copilot instructions for `prek`

## Code requirements

- Concise, idiomatic Rust (2024 edition).
- Proper error handling (no unwraps, panics, etc. in app code).
- Clear separation of concerns (e.g., config parsing vs. execution).
- Thorough test coverage (unit + integration tests, snapshot testing where appropriate).

## Big picture

- Rust workspace under `crates/*`. The main CLI binary is `crates/prek` (`src/main.rs`).
- `prek` is a Rust reimplementation of `pre-commit`: configuration parsing lives in `crates/prek/src/config.rs`, execution/dispatch is in `crates/prek/src/run.rs`, and integration tests exercise the CLI end-to-end under `crates/prek/tests/`.
- User-facing output is centralized:
    - Warnings go through `warn_user!` / `warn_user_once!` in `crates/prek/src/warnings.rs` (can be disabled via `-q` / `-qq`).
    - Progress/output selection is via `Printer` in `crates/prek/src/printer.rs`.
- Cross-process coordination uses a store under `$PREK_HOME` (see `Store::from_settings` / `Store::lock_async` in `crates/prek/src/store.rs`).

## Developer workflows (preferred)

- Lint/format like CI: `mise run lint` (runs `cargo fmt` + `cargo clippy --all-targets --all-features --workspace -- -D warnings`).
- Run all tests: `mise run test` (workspace, all targets/features).
- Snapshot-first test workflow (insta):
    - Unit/bin tests with review UI: `mise run test-unit -- <filter>` or `mise run test-all-unit`.
    - Integration tests with review UI: `mise run test-integration <test> [filter]` or `mise run test-all-integration`.
    - DO NOT run `cargo test -p prek` while testing, they are slow. Use `cargo test -p prek --lib <unit-test> -- --exact` (or `cargo test -p prek --bin prek <unit-test> -- --exact`) for unit tests and `cargo test -p prek --test <test> -- <filter>` for integration tests.
    - Use `cargo insta review --accept` to accept snapshot changes after running tests locally.

## Project-specific conventions

- Prefer `fs-err` / `fs-err::tokio` over `std::fs` / `tokio::fs` for filesystem operations (see many modules, e.g. `crates/prek/src/store.rs`).
- Prefer `anyhow::Result` for app-level flows and `thiserror` for typed errors when there’s a clear domain (see `crates/prek/src/store.rs`).
- Logging uses `tracing`; default behavior is configured in `crates/prek/src/main.rs` and can be overridden via `RUST_LOG`.
- CLI is defined with `clap` under `crates/prek/src/cli/` (entry in `crates/prek/src/cli/mod.rs`). If adding a command, keep wiring consistent with existing `cli/*` modules.

## Tests and fixtures

- Integration tests use `TestContext` helpers in `crates/prek/tests/common/mod.rs` and snapshot macros like `cmd_snapshot!`.
- Tests often normalize paths with regex filters; prefer using `context.filters()` for stable snapshots.

## Docs + generated artifacts

- Docs are built with Zensical (see `mkdocs.yml`); run locally via `mise run build-docs`.
- CLI reference + JSON schema are generated via `mise run generate` (see tasks in `mise.toml`).

## When changing behavior

- If a change affects user-visible output, update the relevant snapshot(s) under `crates/prek/tests/` (use the `cargo insta` review flow).
- Keep output stable and routed through existing printer/warning macros rather than printing directly.


================================================
FILE: .github/renovate.json5
================================================
{
  $schema: 'https://docs.renovatebot.com/renovate-schema.json',
  extends: [
    'config:recommended',
    // https://docs.renovatebot.com/presets-default/#configmigration
    ':configMigration',
    // https://docs.renovatebot.com/presets-customManagers/#custommanagersgithubactionsversions
    // Update _VERSION environment variables in GitHub Action files.
    'customManagers:githubActionsVersions',
  ],
  schedule: [
    '* 1-3 * * 1'
  ],
  // release.yml is generated by cargo-dist and should not be updated.
  ignorePaths: [
    '.github/workflows/release.yml'
  ],
  prHourlyLimit: 10,
  labels: [
    'internal'
  ],
  semanticCommits: 'disabled',
  // pre-commit is currently in beta testing, must opt in
  'pre-commit': {
    enabled: true
  },
  enabledManagers: [
    'github-actions',
    'pre-commit',
    'cargo',
    'custom.regex',
  ],
  customManagers: [
    // Update `uv` version in `crates/prek/src/languages/python/uv.rs` and CI workflows.
    {
      customType: 'regex',
      managerFilePatterns: [
        '/src/languages/python/uv.rs$/',
        '/.github/workflows/.*\\.yml$/',
      ],
      datasourceTemplate: 'pypi',
      packageNameTemplate: 'uv',
      matchStrings: [
        'const\\s+CUR_UV_VERSION\\s*:\\s*&str\\s*=\\s*"(?<currentValue>\\d+\\.\\d+\\.\\d+)"',
        'UV_VERSION:\\s*"(?<currentValue>\\d+\\.\\d+\\.\\d+)"',
      ]
    },
    // Update major GitHub actions references in documentation.
    {
      customType: 'regex',
      managerFilePatterns: [
        '/README\\.md$/',
        '/^docs/.*\\.md$/'
      ],
      matchStrings: [
        '\\suses: (?<depName>[\\w-]+/[\\w-]+)(?<path>/.*)?@(?<currentValue>.+?)\\s',
      ],
      datasourceTemplate: 'github-tags',
      versioningTemplate: 'regex:^v(?<major>\\d+)$',
    },
    // Minimum supported Rust toolchain version
    {
      customType: "regex",
      managerFilePatterns: ["/(^|/)Cargo\\.toml$/"],
      matchStrings: [
        'rust-version\\s*=\\s*"(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)"',
      ],
      depNameTemplate: "msrv",
      packageNameTemplate: "rust-lang/rust",
      datasourceTemplate: "github-releases",
    },
    // Rust toolchain version
    {
      customType: "regex",
      managerFilePatterns: ["/(^|/)rust-toolchain\\.toml$/"],
      matchStrings: [
        'channel\\s*=\\s*"(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)"',
      ],
      depNameTemplate: "rust",
      packageNameTemplate: "rust-lang/rust",
      datasourceTemplate: "github-releases",
    }
  ],
  packageRules: [
    // Group all GitHub Actions updates together
    {
      groupName: 'GitHub Actions',
      matchManagers: ['github-actions'],
      matchDepTypes: ['action'],
      // Pin GitHub Actions to immutable SHAs
      pinDigests: true
    },
    {
      groupName: 'pre-commit',
      matchManagers: ['pre-commit'],
      matchFileNames: ['.pre-commit-config.yaml']
    },
    // Annotate GitHub Actions SHAs with a SemVer version.
    {
      extends: [
        'helpers:pinGitHubActionDigests'
      ],
      extractVersion: '^(?<version>v?\\d+\\.\\d+\\.\\d+)$',
      versioning: 'regex:^v?(?<major>\\d+)(\\.(?<minor>\\d+)\\.(?<patch>\\d+))?$'
    },
    // Disable updates for GitHub runners: we'd only pin them to a specific version
    // if there was a deliberate reason to do so
    {
      groupName: 'GitHub runners',
      matchManagers: [
        'github-actions'
      ],
      matchDatasources: [
        'github-runners'
      ],
      description: "Disable PRs updating GitHub runners (e.g. 'runs-on: macos-14')",
      enabled: false
    },
    // Disable updates for the msvc-dev-cmd action, the latest version does not work.
    {
      matchManagers: [
        "github-actions"
      ],
      matchDepTypes: [
        "action"
      ],
      matchDepNames: [
        "ilammy/msvc-dev-cmd"
      ],
      enabled: false
    },
    {
      matchManagers: ["custom.regex"],
      matchDepNames: ["rust"],
      commitMessageTopic: "Rust",
    },
    {
      matchManagers: [ 'cargo', 'pre-commit', 'github-actions', 'custom.regex' ],
      minimumReleaseAge: '7 days'
    },
    {
      commitMessageTopic: "MSRV",
      matchManagers: ["custom.regex"],
      matchDepNames: ["msrv"],
      // We have a rolling support policy for the MSRV
      // 2 releases back * 6 weeks per release * 7 days per week + 1
      minimumReleaseAge: "85 days",
      internalChecksFilter: "strict",
      groupName: "MSRV",
    }
  ]
}


================================================
FILE: .github/workflows/build-binaries.yml
================================================
# Build prek on all platforms.
#
# Generates both wheels (for PyPI) and archived binaries (for GitHub releases).
# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a local
# artifacts job within `cargo-dist`.
#
# Adapted from https://github.com/astral-sh/uv/blob/main/.github/workflows/build-binaries.yml

name: "Build binaries"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string
  pull_request:
    paths:
      # When we change pyproject.toml, we want to ensure that the maturin builds still work.
      - pyproject.toml
      # And when we change this workflow itself...
      - .github/workflows/build-binaries.yml

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  CARGO_INCREMENTAL: 0
  CARGO_NET_RETRY: 10
  CARGO_TERM_COLOR: always
  RUSTUP_MAX_RETRIES: 10
  # renovate: datasource=github-releases depName=PyO3/maturin versioning=semver
  MATURIN_VERSION: "v1.12.6"

jobs:
  sdist:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: Build sdist
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          command: sdist
          args: --out dist
      - name: "Upload sdist"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-sdist
          path: dist

  windows:
    runs-on: windows-latest
    strategy:
      matrix:
        platform:
          - target: x86_64-pc-windows-msvc
            arch: x64
          - target: i686-pc-windows-msvc
            arch: x86
          - target: aarch64-pc-windows-msvc
            arch: x64 # not relevant here
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Install NASM"
        # NASM is required for x86/x86-64 Windows targets by aws-lc-sys.
        # On aarch64-pc-windows-msvc, it uses clang-cl instead.
        # See: https://aws.github.io/aws-lc-rs/requirements/windows.html#build-requirements
        if: contains(matrix.platform.target, 'x86') || contains(matrix.platform.target, 'i686')
        run: |
          winget install NASM.NASM --accept-source-agreements --accept-package-agreements
          echo "C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Append
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.platform.target }}
          args: --profile dist --locked --out dist --features self-update
          sccache: 'true'
        env:
          # Disable prebuilt NASM objects so we always compile assembly from source.
          AWS_LC_SYS_PREBUILT_NASM: "0"
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-windows-${{ matrix.platform.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          ARCHIVE_FILE=prek-${{ matrix.platform.target }}.zip
          7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/dist/prek.exe
          sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.platform.target }}
          path: |
            *.zip
            *.sha256

  macos:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: macos-15
            target: x86_64-apple-darwin
          - runner: macos-15
            target: aarch64-apple-darwin
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.platform.target }}
          args: --profile dist --locked --out dist --features self-update
          sccache: 'true'
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-macos-${{ matrix.platform.target }}
          path: dist
      - name: "Archive binary"
        run: |
          TARGET=${{ matrix.platform.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.platform.target }}
          path: |
            *.tar.gz
            *.sha256


  linux:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - { target: "i686-unknown-linux-gnu", cc: "gcc -m32" }
          - { target: "x86_64-unknown-linux-gnu", cc: "gcc" }
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.target }}
          # Generally, we try to build in a target docker container. In this case however, a
          # 32-bit compiler runs out of memory (4GB memory limit for 32-bit), so we cross compile
          # from 64-bit version of the container, breaking the pattern from other builds.
          container: quay.io/pypa/manylinux2014
          args: --profile dist --locked --out dist --features self-update
          # See: https://github.com/sfackler/rust-openssl/issues/2036#issuecomment-1724324145
          before-script-linux: |
            # Install the 32-bit cross target on 64-bit (noop if we're already on 64-bit)
            rustup target add ${{ matrix.target }}
            # If we're running on rhel centos, install needed packages.
            if command -v yum &> /dev/null; then
                yum update -y && yum install -y perl-core openssl openssl-devel pkgconfig libatomic

                # If we're running on i686 we need to symlink libatomic
                # in order to build openssl with -latomic flag.
                if [[ ! -d "/usr/lib64" ]]; then
                    ln -s /usr/lib/libatomic.so.1 /usr/lib/libatomic.so
                else
                    # Support cross-compiling from 64-bit to 32-bit
                    yum install -y glibc-devel.i686 libstdc++-devel.i686
                fi
            else
                # If we're running on debian-based system.
                apt update -y && apt-get install -y libssl-dev openssl pkg-config
            fi
          sccache: 'true'
          manylinux: auto
        env:
          CC: ${{ matrix.cc }}
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-linux-${{ matrix.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          set -euo pipefail

          TARGET=${{ matrix.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.target }}
          path: |
            *.tar.gz
            *.sha256

  linux-arm:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        platform:
          - target: aarch64-unknown-linux-gnu
            arch: aarch64
            # see https://github.com/astral-sh/ruff/issues/3791
            # and https://github.com/gnzlbg/jemallocator/issues/170#issuecomment-1503228963
            maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16
          - target: armv7-unknown-linux-gnueabihf
            arch: armv7
          - target: arm-unknown-linux-musleabihf
            arch: arm
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.platform.target }}
          # On `aarch64`, use `manylinux: 2_28`; otherwise, use `manylinux: auto`.
          manylinux: ${{ matrix.platform.arch == 'aarch64' && '2_28' || 'auto' }}
          docker-options: ${{ matrix.platform.maturin_docker_options }}
          args: --profile dist --locked --out dist --features self-update
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          set -euo pipefail

          TARGET=${{ matrix.platform.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.platform.target }}
          path: |
            *.tar.gz
            *.sha256

  linux-s390x:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        platform:
          - target: s390x-unknown-linux-gnu
            arch: s390x
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.platform.target }}
          manylinux: auto
          args: --profile dist --locked --out dist --features self-update
          rust-toolchain: ${{ matrix.platform.toolchain || null }}
        env:
          CFLAGS_s390x_unknown_linux_gnu: -march=z10
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          set -euo pipefail

          TARGET=${{ matrix.platform.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.platform.target }}
          path: |
            *.tar.gz
            *.sha256

  linux-riscv64:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        platform:
          - target: riscv64gc-unknown-linux-gnu
            arch: riscv64
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.platform.target }}
          manylinux: auto
          args: --profile dist --locked --out dist --features self-update
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          set -euo pipefail

          TARGET=${{ matrix.platform.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.platform.target }}
          path: |
            *.tar.gz
            *.sha256


  musllinux:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target:
          - x86_64-unknown-linux-musl
          - i686-unknown-linux-musl
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.target }}
          manylinux: musllinux_1_1
          args: --profile dist --locked --out dist --features self-update
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-linux-${{ matrix.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          set -euo pipefail

          TARGET=${{ matrix.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.target }}
          path: |
            *.tar.gz
            *.sha256

  musllinux-cross:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        platform:
          - target: aarch64-unknown-linux-musl
            arch: aarch64
            maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16
          - target: armv7-unknown-linux-musleabihf
            arch: armv7
      fail-fast: false
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Build wheels"
        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
        with:
          maturin-version: ${{ env.MATURIN_VERSION }}
          target: ${{ matrix.platform.target }}
          manylinux: musllinux_1_1
          args: --profile dist --locked --out dist --features self-update ${{ matrix.platform.arch == 'aarch64' && '--compatibility 2_17' || ''}}
          docker-options: ${{ matrix.platform.maturin_docker_options }}
          rust-toolchain: ${{ matrix.platform.toolchain || null }}
      - name: "Upload wheels"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist
      - name: "Archive binary"
        shell: bash
        run: |
          set -euo pipefail

          TARGET=${{ matrix.platform.target }}
          ARCHIVE_NAME=prek-$TARGET
          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz

          mkdir -p $ARCHIVE_NAME
          cp target/$TARGET/dist/prek $ARCHIVE_NAME/prek
          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: artifacts-${{ matrix.platform.target }}
          path: |
            *.tar.gz
            *.sha256


================================================
FILE: .github/workflows/build-docker.yml
================================================
# Build and publish a Docker image.
#
# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a local
# artifacts job within `cargo-dist`.
#
# Adapted from https://github.com/astral-sh/ty/blob/main/.github/workflows/build-docker.yml
name: "Build Docker image"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string
  pull_request:
    paths:
      - .github/workflows/build-docker.yml

env:
  PREK_BASE_IMG: ghcr.io/${{ github.repository_owner }}/prek

permissions:
  contents: read
  packages: write # zizmor: ignore[excessive-permissions]

jobs:
  docker-build:
    name: Build Docker image ghcr.io/j178/prek for ${{ matrix.platform }}
    runs-on: ubuntu-latest
    environment:
      name: release
    strategy:
      fail-fast: false
      matrix:
        platform:
          - linux/amd64
          - linux/arm64
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0

      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Check tag consistency
        if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
        env:
          TAG: ${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || 'dry-run' }}
        run: |
          version=$(grep -m 1 "^version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
          if [ "${TAG}" != "v${version}" ]; then
            echo "The input tag does not match the version from pyproject.toml:" >&2
            echo "${TAG}" >&2
            echo "${version}" >&2
            exit 1
          else
            echo "Releasing ${version}"
          fi

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
        env:
          DOCKER_METADATA_ANNOTATIONS_LEVELS: index
        with:
          images: ${{ env.PREK_BASE_IMG }}
          # Defining this makes sure the org.opencontainers.image.version OCI label becomes the actual release version and not the branch name
          tags: |
            type=raw,value=dry-run,enable=${{ inputs.plan == '' || fromJson(inputs.plan).announcement_tag_is_implicit }}
            type=semver,pattern={{ raw }},value=${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || 'dry-run' }},enable=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}

      - name: Normalize Platform Pair (replace / with -)
        run: |
          platform=${{ matrix.platform }}
          echo "PLATFORM_TUPLE=${platform//\//-}" >> "$GITHUB_ENV"

      # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
      - name: Build and push by digest
        id: build
        uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
        with:
          context: .
          platforms: ${{ matrix.platform }}
          cache-from: type=gha,scope=prek-${{ env.PLATFORM_TUPLE }}
          cache-to: type=gha,mode=min,scope=prek-${{ env.PLATFORM_TUPLE }}
          labels: ${{ steps.meta.outputs.labels }}
          outputs: type=image,name=${{ env.PREK_BASE_IMG }},push-by-digest=true,name-canonical=true,push=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}

      - name: Export digests
        env:
          digest: ${{ steps.build.outputs.digest }}
        run: |
          mkdir -p /tmp/digests
          touch "/tmp/digests/${digest#sha256:}"

      - name: Upload digests
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: digests-${{ env.PLATFORM_TUPLE }}
          path: /tmp/digests/*
          if-no-files-found: error
          retention-days: 1

  docker-publish:
    name: Publish Docker image (ghcr.io/j178/prek)
    runs-on: ubuntu-latest
    environment:
      name: release
    needs:
      - docker-build
    permissions:
      contents: read
      packages: write
      id-token: write
      attestations: write
    if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
    steps:
      - name: Download digests
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          path: /tmp/digests
          pattern: digests-*
          merge-multiple: true

      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
        env:
          DOCKER_METADATA_ANNOTATIONS_LEVELS: index
        with:
          images: ${{ env.PREK_BASE_IMG }}
          # Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version
          tags: |
            type=raw,value=${{ fromJson(inputs.plan).announcement_tag }}
            type=semver,pattern=v{{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}

      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
      - name: Create manifest list and push
        working-directory: /tmp/digests
        # The jq command expands the docker/metadata json "tags" array entry to `-t tag1 -t tag2 ...` for each tag in the array
        # The printf will expand the base image with the `<PREK_BASE_IMG>@sha256:<sha256> ...` for each sha256 in the directory
        # The final command becomes `docker buildx imagetools create -t tag1 -t tag2 ... <PREK_BASE_IMG>@sha256:<sha256_1> <PREK_BASE_IMG>@sha256:<sha256_2> ...`
        run: |
          # shellcheck disable=SC2046
          readarray -t lines <<< "$DOCKER_METADATA_OUTPUT_ANNOTATIONS"; annotations=(); for line in "${lines[@]}"; do annotations+=(--annotation "$line"); done

          docker buildx imagetools create \
            "${annotations[@]}" \
            $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            $(printf "${PREK_BASE_IMG}@sha256:%s " *)

      - name: Export manifest digest
        id: manifest-digest
        env:
          IMAGE: ${{ env.PREK_BASE_IMG }}
          VERSION: ${{ steps.meta.outputs.version }}
        run: |
          digest="$(
            docker buildx imagetools inspect \
              "${IMAGE}:${VERSION}" \
              --format '{{json .Manifest}}' \
            | jq -r '.digest'
          )"
          echo "digest=${digest}" >> "$GITHUB_OUTPUT"

      - name: Generate artifact attestation
        uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
        with:
          subject-name: ${{ env.PREK_BASE_IMG }}
          subject-digest: ${{ steps.manifest-digest.outputs.digest }}


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches: [master]
  pull_request:
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

permissions: {}

env:
  # UV_VERSION should not greater than MAX_UV_VERSION in `languages/python/uv`.
  # Otherwise, tests jobs will install their own uv, and it will encounter concurrency issue.
  UV_VERSION: "0.10.9"
  NODE_VERSION: "20"
  BUN_VERSION: "1.3"
  GO_VERSION: "1.24"
  PYTHON_VERSION: "3.12"
  RUBY_VERSION: "3.4"
  LUA_VERSION: "5.4"
  LUAROCKS_VERSION: "3.12.2"
  GHC_VERSION: "9.14.1" # Preinstalled in ubuntu-24.04 runner image
  CABAL_VERSION: "3.16.1.0"
  JULIA_VERSION: "1.12.4"
  DENO_VERSION: "2"

  # Cargo env vars
  CARGO_INCREMENTAL: 0
  CARGO_NET_RETRY: 10
  CARGO_TERM_COLOR: always
  RUSTUP_MAX_RETRIES: 10

jobs:
  plan:
    runs-on: ubuntu-latest
    outputs:
      test-code: ${{ !contains(github.event.pull_request.labels.*.name, 'test:skip') && (steps.changed.outputs.any_code_changed == 'true' || github.ref == 'refs/heads/master') }}
      save-rust-cache: ${{ github.ref == 'refs/heads/master' || steps.changed.outputs.cache_changed == 'true' }}
      # Run benchmarks if Rust code or benchmark-related files changed
      run-bench: ${{ !contains(github.event.pull_request.labels.*.name, 'test:skip') && (steps.changed.outputs.rust_code_changed == 'true' || steps.changed.outputs.bench_related_changed == 'true' || github.ref == 'refs/heads/master') }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: "Determine changed files"
        id: changed
        shell: bash
        run: |
          CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha || 'origin/master' }}...HEAD)

          ANY_CODE_CHANGED=false
          CACHE_CHANGED=false
          RUST_CODE_CHANGED=false
          BENCH_RELATED_CHANGED=false

          while IFS= read -r file; do
            # Check if cache-relevant files changed (Cargo files, toolchain, workflows)
            if [[ "${file}" == "Cargo.lock" || "${file}" == "Cargo.toml" || "${file}" == "rust-toolchain.toml" || "${file}" == ".cargo/config.toml" || "${file}" =~ ^crates/.*/Cargo\.toml$ || "${file}" =~ ^\.github/workflows/.*\.yml$ ]]; then
              echo "Detected cache-relevant change: ${file}"
              CACHE_CHANGED=true
            fi

            # Check if Rust code changed (for benchmarks)
            if [[ "${file}" =~ \.rs$ ]] || [[ "${file}" =~ Cargo\.toml$ ]] || [[ "${file}" == "Cargo.lock" ]] || [[ "${file}" == "rust-toolchain.toml" ]] || [[ "${file}" =~ ^\.cargo/ ]]; then
              echo "Detected Rust code change: ${file}"
              RUST_CODE_CHANGED=true
            fi

            if [[ "${file}" == ".github/workflows/performance.yml" ]] || [[ "${file}" =~ ^scripts/hyperfine-.*\.sh$ ]]; then
              echo "Detected benchmark-related change: ${file}"
              BENCH_RELATED_CHANGED=true
            fi

            if [[ "${file}" =~ ^docs/ ]]; then
              echo "Skipping ${file} (matches docs/ pattern)"
              continue
            fi
            if [[ "${file}" =~ ^mkdocs.*\.yml$ ]]; then
              echo "Skipping ${file} (matches mkdocs*.yml pattern)"
              continue
            fi
            if [[ "${file}" =~ \.md$ ]]; then
              echo "Skipping ${file} (matches *.md pattern)"
              continue
            fi

            echo "Detected code change in: ${file}"
            ANY_CODE_CHANGED=true

          done <<< "${CHANGED_FILES}"
          echo "any_code_changed=${ANY_CODE_CHANGED}" >> "${GITHUB_OUTPUT}"
          echo "cache_changed=${CACHE_CHANGED}" >> "${GITHUB_OUTPUT}"
          echo "rust_code_changed=${RUST_CODE_CHANGED}" >> "${GITHUB_OUTPUT}"
          echo "bench_related_changed=${BENCH_RELATED_CHANGED}" >> "${GITHUB_OUTPUT}"

  lint:
    name: "lint"
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Install Rustfmt"
        run: rustup component add rustfmt
      - name: "rustfmt"
        run: cargo fmt --all --check
      - name: Run prek checks
        uses: j178/prek-action@79f765515bd648eb4d6bb1b17277b7cb22cb6468 # v2.0.0
        env:
          PREK_SKIP: cargo-fmt,cargo-clippy

  check-release:
    name: "check release"
    needs: plan
    timeout-minutes: 10
    runs-on: ubuntu-latest
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Install dist
        shell: bash
        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh"

      - name: Run dist plan
        run: |
          dist plan --output-format=json > plan-dist-manifest.json
          echo "dist plan completed successfully"
          cat plan-dist-manifest.json

  cargo-clippy-linux:
    name: "cargo clippy | ubuntu"
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Install Rust toolchain"
        run: rustup component add clippy
      - name: "Clippy"
        run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings

  cargo-clippy-windows:
    name: "cargo clippy | windows"
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 15
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Create Dev Drive
        run: ${{ github.workspace }}/.github/workflows/setup-dev-drive.ps1

      # actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
      - name: Copy Git Repo to Dev Drive
        run: |
          Copy-Item -Path "${{ github.workspace }}" -Destination "$Env:PREK_WORKSPACE" -Recurse

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          workspaces: ${{ env.PREK_WORKSPACE }}
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Install Rust toolchain"
        run: rustup component add clippy

      - name: "Clippy"
        working-directory: ${{ env.PREK_WORKSPACE }}
        run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings

  cargo-shear:
    name: "cargo shear"
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Install cargo shear"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-shear
      - run: cargo shear

  cargo-test-without-uv:
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 5
    runs-on: ubuntu-latest
    name: "cargo test | without uv"
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Install Rust toolchain"
        run: rustup component add llvm-tools-preview

      - name: "Install cargo nextest"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-nextest

      - name: "Install cargo-llvm-cov"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-llvm-cov

      - name: "Cargo test without uv"
        run: |
          echo "::group::Test install uv with auto select"
          cargo llvm-cov nextest \
            --profile ci-core \
            --cargo-profile fast-build \
            --no-report \
            -E 'binary_id(prek::run) and test(run_basic)'
          echo "::endgroup::"

          for source in github pypi aliyun pip invalid; do
            echo "::group::Test install uv from $source"
            export PREK_UV_SOURCE=$source
            cargo llvm-cov nextest \
              --profile ci-core \
              --cargo-profile fast-build \
              --no-report \
              -E 'binary_id(prek::run) and test(run_basic)'
            echo "::endgroup::"
          done

          cargo llvm-cov report --profile fast-build --lcov --output-path lcov.info

      - name: "Upload coverage reports to Codecov"
        uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: lcov.info

  cargo-test:
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: ${{ matrix.os }}
    name: "cargo test | ${{ matrix.os }}"
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
        if: ${{ matrix.os == 'ubuntu-latest' }}
      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Install Rust toolchain"
        run: rustup component add llvm-tools-preview

      - name: "Install cargo nextest"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-nextest

      - name: "Install cargo-llvm-cov"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-llvm-cov

      - name: "Install uv"
        uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
        with:
          version: ${{ env.UV_VERSION }}

      - name: "Install Python"
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: "Cargo test"
        run: |
          cargo llvm-cov nextest \
            --lcov \
            --output-path lcov.info \
            --workspace \
            --cargo-profile fast-build \
            --profile ci-core \
            --features schemars

      - name: "Upload coverage reports to Codecov"
        uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: lcov.info

  cargo-test-windows:
    name: "cargo test | windows"
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    runs-on: windows-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Create Dev Drive
        run: ${{ github.workspace }}/.github/workflows/setup-dev-drive.ps1

      # actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
      - name: Copy Git Repo to Dev Drive
        run: |
          Copy-Item -Path "${{ github.workspace }}" -Destination "$Env:PREK_WORKSPACE" -Recurse

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          workspaces: ${{ env.PREK_WORKSPACE }}
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Install Rust toolchain"
        run: rustup component add llvm-tools-preview

      - name: "Install cargo nextest"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-nextest

      - name: "Install cargo-llvm-cov"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-llvm-cov

      - name: "Install uv"
        uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
        with:
          version: ${{ env.UV_VERSION }}
          cache-local-path: ${{ env.DEV_DRIVE }}/uv-cache

      - name: "Install Python"
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # windows only

      - name: "Cargo test"
        working-directory: ${{ env.PREK_WORKSPACE }}
        shell: pwsh
        run: |
          # Remove msys64 from PATH for Rust compilation
          $env:PATH = ($env:PATH -split ';' | Where-Object { $_ -notmatch '\\msys64\\' }) -join ';'

          cargo llvm-cov nextest `
            --lcov `
            --output-path lcov.info `
            --workspace `
            --cargo-profile fast-build `
            --features schemars `
            --profile ci-core

          if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

      - name: "Upload coverage reports to Codecov"
        uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: ${{ env.PREK_WORKSPACE }}/lcov.info

  language-tests:
    name: "language tests | ${{ matrix.language }} | ${{ matrix.os }}"
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 15
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest
        language:
          - bun
          - deno
          - docker
          - golang
          - haskell
          - julia
          - lua
          - node
          - python
          - ruby
          - rust
          - swift
        exclude:
          # Docker is only available on ubuntu-latest
          - os: macos-latest
            language: docker
          - os: windows-latest
            language: docker
          # Swift is preinstalled on ubuntu and macOS; Windows requires setup which is slow
          - os: windows-latest
            language: swift
          # GHC is not preinstalled on macOS, and installing it takes a long time
          - os: macos-latest
            language: haskell
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
        if: ${{ matrix.os == 'ubuntu-latest' }}

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Install Rust toolchain"
        run: rustup component add llvm-tools-preview

      - name: "Install cargo nextest"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-nextest

      - name: "Install cargo-llvm-cov"
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-llvm-cov

      - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # windows only
        if: ${{ matrix.os == 'windows-latest' }}

      - name: "Install uv"
        if: ${{ matrix.language == 'python' }}
        uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
        with:
          version: ${{ env.UV_VERSION }}

      - name: "Install Python"
        if: ${{ matrix.language == 'python' }}
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: "Install Node.js"
        if: ${{ matrix.language == 'node' }}
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm
          # Dummy dependency path to satisfy required input while enabling caching
          cache-dependency-path: LICENSE

      - name: "Install Go"
        if: ${{ matrix.language == 'golang' }}
        uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
        with:
          go-version: ${{ env.GO_VERSION }}
          # Dummy dependency path to satisfy required input while enabling caching
          cache-dependency-path: LICENSE

      - name: "Install Lua"
        if: ${{ matrix.language == 'lua' }}
        uses: leafo/gh-actions-lua@8c9e175e7a3d77e21f809eefbee34a19b858641b # v12
        with:
          luaVersion: ${{ env.LUA_VERSION }}

      - name: "Install LuaRocks"
        if: ${{ matrix.language == 'lua' }}
        uses: luarocks/gh-actions-luarocks@7c85eeff60655651b444126f2a78be784e836a0a #v6
        with:
          luaRocksVersion: ${{ env.LUAROCKS_VERSION }}

      - name: "Install Ruby"
        if: ${{ matrix.language == 'ruby' }}
        uses: ruby/setup-ruby@6ca151fd1bfcfd6fe0c4eb6837eb0584d0134a0c # v1.290.0
        with:
          ruby-version: ${{ env.RUBY_VERSION }}

      - name: "Install Bun"
        if: ${{ matrix.language == 'bun' }}
        uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
        with:
          bun-version: ${{ env.BUN_VERSION }}

      - name: "Install Deno"
        if: ${{ matrix.language == 'deno' }}
        uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
        with:
          deno-version: ${{ env.DENO_VERSION }}

      - name: "Install GHC and Cabal"
        if: ${{ matrix.language == 'haskell' }}
        uses: haskell-actions/setup@f9150cb1d140e9a9271700670baa38991e6fa25c # v2.10.3
        with:
          ghc-version: ${{ env.GHC_VERSION }}
          cabal-version: ${{ env.CABAL_VERSION }}

      - name: "Install Julia"
        if: ${{ matrix.language == 'julia' }}
        uses: julia-actions/setup-julia@4c0cb0fce8556fdb04a90347310e5db8b1f98fb9 # v2.7.0
        with:
          version: ${{ env.JULIA_VERSION }}

      - name: "Run language tests"
        if: ${{ matrix.os != 'windows-latest' }}
        env:
          # Ruby auto_download test queries the GitHub Releases API; without a
          # token, shared runners quickly hit the 60 req/hour rate limit.
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          cargo llvm-cov nextest \
            --lcov \
            --output-path lcov.info \
            --workspace \
            --cargo-profile fast-build \
            --features schemars \
            --profile lang-${{ matrix.language }}

      - name: "Run language tests (windows)"
        if: ${{ matrix.os == 'windows-latest' }}
        shell: pwsh
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Remove msys64 from PATH for Rust compilation
          $env:PATH = ($env:PATH -split ';' | Where-Object { $_ -notmatch '\\msys64\\' }) -join ';'

          cargo llvm-cov nextest `
            --lcov `
            --output-path lcov.info `
            --workspace `
            --cargo-profile fast-build `
            --features schemars `
            --profile lang-${{ matrix.language }}

          if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

      - name: "Upload coverage reports to Codecov"
        uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: lcov.info

  performance:
    needs: plan
    if: ${{ needs.plan.outputs.run-bench == 'true' }}
    uses: ./.github/workflows/performance.yml
    with:
      save-rust-cache: ${{ needs.plan.outputs.save-rust-cache }}

  ecosystem-cpython:
    name: "ecosystem | cpython"
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Checkout python/cpython
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          repository: python/cpython
          ref: f3759d21dd5e6510361d7409a1df53f35ebd9a58
          path: cpython
          fetch-depth: 1
          persist-credentials: false

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: Run prek on cpython
        working-directory: cpython
        run: cargo run -p prek -- --all-files

  build-binary-msrv:
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    name: "build binary | msrv"
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: "Read MSRV from Cargo.toml"
        id: msrv
        run: |
          MSRV=$(grep -m1 'rust-version' Cargo.toml | sed 's/.*"\([^"]*\)".*/\1/')
          echo "value=$MSRV" >> "$GITHUB_OUTPUT"
      - name: "Install Rust toolchain"
        run: rustup default ${MSRV}
        env:
          MSRV: ${{ steps.msrv.outputs.value }}
      - name: "Install mold"
        uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}
      - run: cargo +${MSRV} build --profile no-debug --bin prek
        env:
          MSRV: ${{ steps.msrv.outputs.value }}
      - run: ./target/no-debug/prek --version

  build-binary-linux-libc:
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: ubuntu-latest
    name: "build binary | linux libc"
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Build"
        run: cargo build --profile no-debug --bin prek

      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: prek-linux-libc-${{ github.sha }}
          path: |
            ./target/no-debug/prek
          retention-days: 1

  build-binary-macos-aarch64:
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: macos-latest
    name: "build binary | macos aarch64"
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Build"
        run: cargo build --profile no-debug --bin prek

      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: prek-macos-aarch64-${{ github.sha }}
          path: |
            ./target/no-debug/prek
          retention-days: 1

  build-binary-windows-x86_64:
    needs: plan
    if: ${{ needs.plan.outputs.test-code == 'true' }}
    timeout-minutes: 10
    runs-on: windows-latest
    name: "build binary | windows x86_64"
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Setup Dev Drive
        run: ${{ github.workspace }}/.github/workflows/setup-dev-drive.ps1

      # actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
      - name: Copy Git Repo to Dev Drive
        run: |
          Copy-Item -Path "${{ github.workspace }}" -Destination "$Env:PREK_WORKSPACE" -Recurse

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          workspaces: ${{ env.PREK_WORKSPACE }}
          save-if: ${{ needs.plan.outputs.save-rust-cache == 'true' }}

      - name: "Build"
        working-directory: ${{ env.PREK_WORKSPACE }}
        run: cargo build --profile no-debug --bin prek

      - name: "Upload binary"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: prek-windows-x86_64-${{ github.sha }}
          path: |
            ${{ env.PREK_WORKSPACE }}/target/no-debug/prek.exe
          retention-days: 1


================================================
FILE: .github/workflows/performance.yml
================================================
name: Performance

on:
  workflow_call:
    inputs:
      save-rust-cache:
        required: false
        type: string
        default: "true"

permissions: {}

env:
  # Cargo env vars
  CARGO_INCREMENTAL: 0
  CARGO_NET_RETRY: 10
  CARGO_TERM_COLOR: always
  RUSTUP_MAX_RETRIES: 10

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  bloat-check:
    runs-on: ubuntu-latest
    name: "bloat check"
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
          fetch-depth: 0
      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ inputs.save-rust-cache == 'true' }}
      - uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: cargo-bloat

      - name: Build head branch
        id: bloat_head
        run: |
          # Build head branch
          cargo bloat --release | tee bloat_head.txt >&1

      - name: Checkout base
        run: |
          git checkout ${{ github.event.pull_request.base.sha }}

      - name: Build base branch
        id: bloat_base
        run: |
          # Build base branch
          cargo bloat --release | tee bloat_base.txt >&1

      - name: Compare bloat results
        shell: python
        run: |
          import re
          from pathlib import Path

          def parse_size(text):
              match = re.search(r'\.text section size.*?([\d.]+)\s*([KMGT]i?B)', text)
              if not match:
                  raise ValueError("Could not find .text section size")
              value, unit = float(match.group(1)), match.group(2)
              multipliers = {'B': 1, 'KiB': 1024, 'MiB': 1024**2, 'GiB': 1024**3, 'TiB': 1024**4}
              size = value * multipliers.get(unit, 1)
              return size, f"{value} {unit}"

          head_text = Path('bloat_head.txt').read_text()
          base_text = Path('bloat_base.txt').read_text()

          head_bytes, head_size = parse_size(head_text)
          base_bytes, base_size = parse_size(base_text)

          pct_change = ((head_bytes - base_bytes) / base_bytes) * 100
          pct_display = f"{pct_change:+.2f}%"
          comparison = f"""\
          ### 📦 Cargo Bloat Comparison
          **Binary size change:** {pct_display} ({base_size} → {head_size})

          <details>
            <summary>Expand for cargo-bloat output</summary>

          #### Head Branch Results
          ```
          {head_text}
          ```

          #### Base Branch Results
          ```
          {base_text}
          ```
          </details>
          """

          Path("bloat-comparison.txt").write_text(comparison)

      - name: Upload bloat results
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          # NOTE: https://github.com/j178/prek-ci-bot uses this artifact name to post comments on PRs.
          # Make sure to update the bot if you rename the artifact.
          name: bloat-check-results
          path: bloat-comparison.txt

  hyperfine-benchmark:
    runs-on: ubuntu-latest
    name: "hyperfine benchmark"
    timeout-minutes: 10
    env:
      HYPERFINE_BENCHMARK_WORKSPACE: /tmp/prek-bench
      HYPERFINE_BIN_DIR: ${{ github.workspace }}/.hyperfine-bin
      HYPERFINE_RESULTS_FILE: ${{ github.workspace }}/hyperfine-benchmark.md
      HYPERFINE_HEAD_BINARY: prek-head
      HYPERFINE_BASE_BINARY: prek-base
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Add hyperfine bin dir to PATH
        run: |
          mkdir -p "$HYPERFINE_BIN_DIR"
          echo "$HYPERFINE_BIN_DIR" >> "$GITHUB_PATH"

      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ inputs.save-rust-cache == 'true' }}

      - id: base-binary-cache
        uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
        with:
          path: ${{ env.HYPERFINE_BIN_DIR }}/${{ env.HYPERFINE_BASE_BINARY }}
          key: prek-hyperfine-base-${{ github.event.pull_request.base.sha }}-${{ hashFiles('Cargo.lock') }}-${{ runner.os }}-${{ runner.arch }}

      - name: Build base version
        if: ${{ steps.base-binary-cache.outputs.cache-hit != 'true' }}
        env:
          BASE_VERSION: ${{ github.event.pull_request.base.sha }}
        run: |
          git checkout ${{ github.event.pull_request.base.sha }}
          cargo build --profile profiling && mv target/profiling/prek "$HYPERFINE_BIN_DIR/$HYPERFINE_BASE_BINARY"
          git checkout ${{ github.sha }}

      - name: Build head version
        run: |
          cargo build --profile profiling && mv target/profiling/prek "$HYPERFINE_BIN_DIR/$HYPERFINE_HEAD_BINARY"

      - name: Install hyperfine
        uses: taiki-e/install-action@64c5c20c872907b6f7cd50994ac189e7274160f2 # v2.68.26
        with:
          tool: hyperfine

      - name: Setup test environment for builtin hooks
        run: scripts/hyperfine-setup-test-env.sh

      - name: Run benchmarks
        run: scripts/hyperfine-run-benchmarks.sh

      - name: Upload benchmark results
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          # NOTE: https://github.com/j178/prek-ci-bot uses this artifact name to post comments on PRs.
          # Make sure to update the bot if you rename the artifact.
          name: hyperfine-benchmark-results
          path: ${{ env.HYPERFINE_RESULTS_FILE }}


================================================
FILE: .github/workflows/publish-crates.yml
================================================
name: "Publish to crates.io"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string

jobs:
  publish:
    name: Upload to crates.io
    runs-on: ubuntu-latest
    environment:
      name: release
    permissions:
      # For crates.io's trusted publishing.
      id-token: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
        with:
          save-if: ${{ github.ref == 'refs/heads/master' }}
      - name: "Install Rust toolchain"
        run: rustup show
      - uses: rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec # v1.0.3
        id: auth
      - name: "Publish to crates.io"
        run: cargo publish --workspace
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}


================================================
FILE: .github/workflows/publish-docs.yml
================================================
name: Deploy Documentation

on:
  workflow_dispatch:
    inputs:
      ref:
        description: "The commit SHA, tag, or branch to publish. Uses the default branch if not specified."
        default: ""
        type: string
  workflow_call:
    inputs:
      plan:
        required: true
        type: string

concurrency:
  group: "pages"
  cancel-in-progress: false

permissions: {}

env:
  UV_VERSION: "0.10.9"
  # Match version used to compile `docs/requirements.txt`
  PYTHON_VERSION: "3.14"

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
        with:
          version: ${{ env.UV_VERSION }}
          python-version: ${{ env.PYTHON_VERSION }}
          cache-dependency-glob: |
            **/docs/requirements.txt

      - name: Build documentation
        run: |
          uvx --with-requirements docs/requirements.txt zensical build
          uvx --with-requirements docs/requirements.txt llmstxt-standalone build

      - name: Upload artifact
        uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4
        with:
          path: ./site

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    permissions:
      contents: read
      pages: write
      id-token: write
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/master'
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5


================================================
FILE: .github/workflows/publish-homebrew.yml
================================================
name: "Publish Homebrew formula"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string
    secrets:
      HOMEBREW_TAP_TOKEN:
        required: true

jobs:
  publish:
    name: Publish Homebrew formula
    runs-on: ubuntu-latest
    environment:
      name: release
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      PLAN: ${{ inputs.plan }}
      GITHUB_USER: "axo bot"
      GITHUB_EMAIL: "admin+bot@axo.dev"
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: true
          repository: "j178/homebrew-tap"
          token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
      - name: Fetch homebrew formulae
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          pattern: artifacts-*
          path: Formula/
          merge-multiple: true
      - name: Commit formula files
        run: |
          git config --global user.name "${GITHUB_USER}"
          git config --global user.email "${GITHUB_EMAIL}"

          for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith(".rb")] | any)'); do
            filename=$(echo "$release" | jq '.artifacts[] | select(endswith(".rb"))' --raw-output)
            name=$(echo "$filename" | sed "s/\.rb$//")
            version=$(echo "$release" | jq .app_version --raw-output)

            export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
            brew update
            # Avoid reformatting user-provided metadata such as homepage and description.
            brew style --except-cops FormulaAudit/Homepage,FormulaAudit/Desc,FormulaAuditStrict --fix "Formula/${filename}" || true

            git add "Formula/${filename}"
            git commit -m "${name} ${version}"
          done
          git push


================================================
FILE: .github/workflows/publish-npm.yml
================================================
name: "Publish to npmjs registry"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string

jobs:
  publish:
    name: Upload to npmjs registry
    runs-on: ubuntu-latest
    environment:
      name: release
    permissions:
      # For npm's trusted publishing.
      id-token: write
      packages: write
    env:
      PLAN: ${{ inputs.plan }}
    steps:
      - name: Fetch npm packages
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          pattern: artifacts-build-global
          path: npm/
          merge-multiple: true
      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: "24.x"
          registry-url: "https://registry.npmjs.org"
      - name: Update npm
        run: npm install -g npm@latest
      - run: |
          for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith("-npm-package.tar.gz")] | any)'); do
            pkg=$(echo "$release" | jq '.artifacts[] | select(endswith("-npm-package.tar.gz"))' --raw-output)
            prerelease=$(echo "$PLAN" | jq ".announcement_is_prerelease")
            if [ "$prerelease" = "true" ]; then
              npm publish --tag beta --provenance --access public "./npm/${pkg}"
            else
              npm publish --provenance --access public "./npm/${pkg}"
            fi
          done


================================================
FILE: .github/workflows/publish-prek-action.yml
================================================
name: "Publish prek-action known versions"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string
    secrets:
      PREK_ACTION_TOKEN:
        required: true

permissions: {}

jobs:
  publish:
    name: Publish prek-action known versions
    runs-on: ubuntu-latest
    environment:
      name: release
    env:
      PLAN: ${{ inputs.plan }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          repository: j178/prek-action
          ref: main
          token: ${{ secrets.PREK_ACTION_TOKEN }}
          persist-credentials: false

      - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 24
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Update known versions
        id: refresh
        env:
          GITHUB_TOKEN: ${{ secrets.PREK_ACTION_TOKEN }}
        run: npm run update-known-versions

      - name: Check whether known version files changed
        id: changes
        run: |
          if git diff --quiet -- version-manifest.json src/known-checksums.ts; then
            echo "known_versions_changed=false" >> "$GITHUB_OUTPUT"
          else
            echo "known_versions_changed=true" >> "$GITHUB_OUTPUT"
          fi

      - name: Run tests
        if: steps.changes.outputs.known_versions_changed == 'true'
        run: npm test

      - name: Rebuild dist
        if: steps.changes.outputs.known_versions_changed == 'true'
        run: npm run bundle

      - name: Create pull request
        id: cpr
        if: steps.changes.outputs.known_versions_changed == 'true'
        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
        with:
          token: ${{ secrets.PREK_ACTION_TOKEN }}
          add-paths: |
            version-manifest.json
            src/known-checksums.ts
            dist/index.cjs
            dist/post/index.cjs
          branch: automation/update-known-versions
          base: main
          commit-message: ${{ steps.refresh.outputs.pr_title }}
          title: ${{ steps.refresh.outputs.pr_title }}
          body: |
            Automated update from the prek release workflow.

            Added releases:
            ${{ steps.refresh.outputs.added_versions_markdown }}

      - name: Merge pull request
        if: steps.cpr.outputs.pull-request-number != ''
        env:
          GH_TOKEN: ${{ secrets.PREK_ACTION_TOKEN }}
          PR_NUMBER: ${{ steps.cpr.outputs.pull-request-number }}
        shell: bash
        run: |
          sleep 10
          gh pr merge --squash --repo j178/prek-action "$PR_NUMBER"


================================================
FILE: .github/workflows/publish-pypi.yml
================================================
name: "Publish to PyPI"

on:
  workflow_call:
    inputs:
      plan:
        required: true
        type: string

jobs:
  publish:
    name: Upload to PyPI
    runs-on: ubuntu-latest
    environment:
      name: release
    permissions:
      # For PyPI's trusted publishing.
      id-token: write
    steps:
      - name: "Install uv"
        uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
      - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          pattern: wheels-*
          path: wheels
          merge-multiple: true
      - name: Publish to PyPi
        run: uv publish -v wheels/*


================================================
FILE: .github/workflows/publish-winget.yml
================================================
name: "Publish to winget"

on:
  workflow_dispatch:
    inputs:
      tag:
        description: "The release tag to publish (e.g., vX.Y.Z)."
        required: true
        type: string
  workflow_call:
    inputs:
      plan:
        required: true
        type: string
    secrets:
      WINGET_TOKEN:
        required: true

permissions: {}

jobs:
  winget:
    name: Publish to winget
    runs-on: ubuntu-latest
    environment:
      name: release
    if: >-
      ${{
        inputs.plan == ''
        || !fromJson(inputs.plan).announcement_is_prerelease
      }}
    steps:
      - name: Determine release tag
        id: tag
        env:
          INPUT_TAG: ${{ inputs.tag }}
          PLAN_TAG: ${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || '' }}
        run: |
          if [ -n "$INPUT_TAG" ]; then
            echo "value=$INPUT_TAG" >> "$GITHUB_OUTPUT"
          else
            echo "value=$PLAN_TAG" >> "$GITHUB_OUTPUT"
          fi
        shell: bash

      - name: Publish to winget
        uses: vedantmgoyal9/winget-releaser@4ffc7888bffd451b357355dc214d43bb9f23917e # v2
        with:
          identifier: j178.Prek
          release-tag: ${{ steps.tag.outputs.value }}
          installers-regex: 'prek-.*windows.*\.zip$'
          token: ${{ secrets.WINGET_TOKEN }}
          fork-user: prek-bot


================================================
FILE: .github/workflows/release.yml
================================================
# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
#
# Copyright 2022-2024, axodotdev
# SPDX-License-Identifier: MIT or Apache-2.0
#
# CI that:
#
# * checks for a Git Tag that looks like a release
# * builds artifacts with dist (archives, installers, hashes)
# * uploads those artifacts to temporary workflow zip
# * on success, uploads the artifacts to a GitHub Release
#
# Note that the GitHub Release will be created with a generated
# title/body based on your changelogs.

name: Release
permissions:
  "contents": "write"

# This task will run whenever you workflow_dispatch with a tag that looks like a version
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
#
# If PACKAGE_NAME is specified, then the announcement will be for that
# package (erroring out if it doesn't have the given version or isn't dist-able).
#
# If PACKAGE_NAME isn't specified, then the announcement will be for all
# (dist-able) packages in the workspace with that version (this mode is
# intended for workspaces with only one dist-able package, or with all dist-able
# packages versioned/released in lockstep).
#
# If you push multiple tags at once, separate instances of this workflow will
# spin up, creating an independent announcement for each one. However, GitHub
# will hard limit this to 3 tags per commit, as it will assume more tags is a
# mistake.
#
# If there's a prerelease-style suffix to the version, then the release(s)
# will be marked as a prerelease.
on:
  workflow_dispatch:
    inputs:
      tag:
        description: Release Tag
        required: true
        default: dry-run
        type: string

jobs:
  # Run 'dist plan' (or host) to determine what tasks we need to do
  plan:
    runs-on: "ubuntu-latest"
    outputs:
      val: ${{ steps.plan.outputs.manifest }}
      tag: ${{ (inputs.tag != 'dry-run' && inputs.tag) || '' }}
      tag-flag: ${{ inputs.tag && inputs.tag != 'dry-run' && format('--tag={0}', inputs.tag) || '' }}
      publishing: ${{ inputs.tag && inputs.tag != 'dry-run' }}
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false
          submodules: recursive
      - name: Install dist
        # we specify bash to get pipefail; it guards against the `curl` command
        # failing. otherwise `sh` won't catch that `curl` returned non-0
        shell: bash
        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh"
      - name: Cache dist
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        with:
          name: cargo-dist-cache
          path: ~/.cargo/bin/dist
      # sure would be cool if github gave us proper conditionals...
      # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
      # functionality based on whether this is a pull_request, and whether it's from a fork.
      # (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
      # but also really annoying to build CI around when it needs secrets to work right.)
      - id: plan
        run: |
          dist ${{ (inputs.tag && inputs.tag != 'dry-run' && format('host --steps=create --tag={0}', inputs.tag)) || 'plan' }} --output-format=json > plan-dist-manifest.json
          echo "dist ran successfully"
          cat plan-dist-manifest.json
          echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
      - name: "Upload dist-manifest.json"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        with:
          name: artifacts-plan-dist-manifest
          path: plan-dist-manifest.json

  custom-build-binaries:
    needs:
      - plan
    if: ${{ needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload' || inputs.tag == 'dry-run' }}
    uses: ./.github/workflows/build-binaries.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit

  custom-build-docker:
    needs:
      - plan
    if: ${{ needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload' || inputs.tag == 'dry-run' }}
    uses: ./.github/workflows/build-docker.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit
    permissions:
      "attestations": "write"
      "contents": "read"
      "id-token": "write"
      "packages": "write"

  # Build and package all the platform-agnostic(ish) things
  build-global-artifacts:
    needs:
      - plan
      - custom-build-binaries
      - custom-build-docker
    runs-on: "ubuntu-latest"
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false
          submodules: recursive
      - name: Install cached dist
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
        with:
          name: cargo-dist-cache
          path: ~/.cargo/bin/
      - run: chmod +x ~/.cargo/bin/dist
      # Get all the local artifacts for the global tasks to use (for e.g. checksums)
      - name: Fetch local artifacts
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
        with:
          pattern: artifacts-*
          path: target/distrib/
          merge-multiple: true
      - id: cargo-dist
        shell: bash
        run: |
          dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
          echo "dist ran successfully"

          # Parse out what we just built and upload it to scratch storage
          echo "paths<<EOF" >> "$GITHUB_OUTPUT"
          jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
          echo "EOF" >> "$GITHUB_OUTPUT"

          cp dist-manifest.json "$BUILD_MANIFEST_NAME"
      - name: "Upload artifacts"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        with:
          name: artifacts-build-global
          path: |
            ${{ steps.cargo-dist.outputs.paths }}
            ${{ env.BUILD_MANIFEST_NAME }}
  # Determines if we should publish/announce
  host:
    needs:
      - plan
      - custom-build-binaries
      - custom-build-docker
      - build-global-artifacts
    # Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine)
    if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.custom-build-binaries.result == 'skipped' || needs.custom-build-binaries.result == 'success') && (needs.custom-build-docker.result == 'skipped' || needs.custom-build-docker.result == 'success') }}
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    runs-on: "ubuntu-latest"
    outputs:
      val: ${{ steps.host.outputs.manifest }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false
          submodules: recursive
      - name: Install cached dist
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
        with:
          name: cargo-dist-cache
          path: ~/.cargo/bin/
      - run: chmod +x ~/.cargo/bin/dist
      # Fetch artifacts from scratch-storage
      - name: Fetch artifacts
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
        with:
          pattern: artifacts-*
          path: target/distrib/
          merge-multiple: true
      # This is a harmless no-op for GitHub Releases, hosting for that happens in "announce"
      - id: host
        shell: bash
        run: |
          dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
          echo "artifacts uploaded and released successfully"
          cat dist-manifest.json
          echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
      - name: "Upload dist-manifest.json"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        with:
          # Overwrite the previous copy
          name: artifacts-dist-manifest
          path: dist-manifest.json

  custom-publish-crates:
    needs:
      - plan
      - host
    if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
    uses: ./.github/workflows/publish-crates.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit
    # publish jobs get escalated permissions
    permissions:
      "id-token": "write"

  custom-publish-pypi:
    needs:
      - plan
      - host
    if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
    uses: ./.github/workflows/publish-pypi.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit
    # publish jobs get escalated permissions
    permissions:
      "id-token": "write"

  custom-publish-npm:
    needs:
      - plan
      - host
    if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
    uses: ./.github/workflows/publish-npm.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit
    # publish jobs get escalated permissions
    permissions:
      "id-token": "write"

  # Create a GitHub Release while uploading all files to it
  announce:
    needs:
      - plan
      - host
      - custom-publish-crates
      - custom-publish-pypi
      - custom-publish-npm
    # use "always() && ..." to allow us to wait for all publish jobs while
    # still allowing individual publish jobs to skip themselves (for prereleases).
    # "host" however must run to completion, no skipping allowed!
    if: ${{ always() && needs.host.result == 'success' && (needs.custom-publish-crates.result == 'skipped' || needs.custom-publish-crates.result == 'success') && (needs.custom-publish-pypi.result == 'skipped' || needs.custom-publish-pypi.result == 'success') && (needs.custom-publish-npm.result == 'skipped' || needs.custom-publish-npm.result == 'success') }}
    runs-on: "ubuntu-latest"
    permissions:
      "attestations": "write"
      "contents": "write"
      "id-token": "write"
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false
          submodules: recursive
      # Create a GitHub Release while uploading all files to it
      - name: "Download GitHub Artifacts"
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
        with:
          pattern: artifacts-*
          path: artifacts
          merge-multiple: true
      - name: Cleanup
        run: |
          # Remove the granular manifests
          rm -f artifacts/*-dist-manifest.json
      - name: Attest
        uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32
        with:
          subject-path: |
            artifacts/*
      - name: Create GitHub Release
        env:
          PRERELEASE_FLAG: "${{ fromJson(needs.host.outputs.val).announcement_is_prerelease && '--prerelease' || '' }}"
          ANNOUNCEMENT_TITLE: "${{ fromJson(needs.host.outputs.val).announcement_title }}"
          ANNOUNCEMENT_BODY: "${{ fromJson(needs.host.outputs.val).announcement_github_body }}"
          RELEASE_COMMIT: "${{ github.sha }}"
        run: |
          # Write and read notes from a file to avoid quoting breaking things
          echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt

          gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*

  custom-publish-docs:
    needs:
      - plan
      - announce
    uses: ./.github/workflows/publish-docs.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit
    permissions:
      "contents": "read"
      "id-token": "write"
      "pages": "write"

  custom-publish-homebrew:
    needs:
      - plan
      - announce
    uses: ./.github/workflows/publish-homebrew.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit

  custom-publish-prek-action:
    needs:
      - plan
      - announce
    uses: ./.github/workflows/publish-prek-action.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit

  custom-publish-winget:
    needs:
      - plan
      - announce
    uses: ./.github/workflows/publish-winget.yml
    with:
      plan: ${{ needs.plan.outputs.val }}
    secrets: inherit


================================================
FILE: .github/workflows/setup-dev-drive.ps1
================================================
# This creates a 10GB dev drive, and exports all required environment
# variables so that rustup, prek and others all use the dev drive as much
# as possible.
# $Volume = New-VHD -Path C:/prek_dev_drive.vhdx -SizeBytes 10GB |
# 					Mount-VHD -Passthru |
# 					Initialize-Disk -Passthru |
# 					New-Partition -AssignDriveLetter -UseMaximumSize |
# 					Format-Volume -FileSystem ReFS -Confirm:$false -Force
#
# Write-Output $Volume

$Drive = "D:"
$Tmp = "$($Drive)\prek-tmp"

# Create the directory ahead of time in an attempt to avoid race-conditions
New-Item $Tmp -ItemType Directory

# Move Cargo to the dev drive
New-Item -Path "$($Drive)/.cargo/bin" -ItemType Directory -Force
if (Test-Path "C:/Users/runneradmin/.cargo") {
    Copy-Item -Path "C:/Users/runneradmin/.cargo/*" -Destination "$($Drive)/.cargo/" -Recurse -Force
}

Write-Output `
	"DEV_DRIVE=$($Drive)" `
	"TMP=$($Tmp)" `
	"TEMP=$($Tmp)" `
	"PREK_INTERNAL__TEST_DIR=$($Tmp)" `
	"RUSTUP_HOME=$($Drive)/.rustup" `
	"CARGO_HOME=$($Drive)/.cargo" `
	"PREK_WORKSPACE=$($Drive)/prek" `
    "PATH=$($Drive)/.cargo/bin;$env:PATH" `
	>> $env:GITHUB_ENV


================================================
FILE: .github/workflows/sync-identify.yml
================================================
name: "Sync pre-commit identify tags"
on:
  workflow_dispatch:
  schedule:
    - cron: "0 0 * * *"

permissions: {}

jobs:
  sync:
    if: github.repository == 'j178/prek'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0
        with:
          version: "latest"
          enable-cache: true
      - name: "Sync identify tags"
        run: uv run --upgrade gen.py
        working-directory: ./crates/prek-identify

      - name: "Create Pull Request"
        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
        with:
          commit-message: "Sync latest identify tags"
          add-paths: |
            crates/prek-identify/src/tags.rs
            crates/prek-identify/gen.py.lock
          branch: "sync-identify-tags"
          title: "Sync latest identify tags"
          body: "Automated update for identify tags."
          base: "master"
          draft: true


================================================
FILE: .github/workflows/zizmor.yml
================================================
name: Run zizmor

on:
  push:
    branches: ["master"]
  pull_request:
    branches: ["**"]

permissions: {}

jobs:
  zizmor:
    name: Run zizmor
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Run zizmor
        uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2


================================================
FILE: .github/zizmor.yml
================================================
# Configuration for the zizmor static analysis tool, run via pre-commit in CI
# https://woodruffw.github.io/zizmor/configuration/

# release.yml is generated by cargo-dist, ignore its findings there.
rules:
  template-injection:
    ignore:
      - release.yml
  excessive-permissions:
    ignore:
      - release.yml
  secrets-inherit:
    ignore:
      - release.yml
  secrets-outside-env:
    ignore:
      - ci.yml # CODECOV_TOKEN is not important


================================================
FILE: .gitignore
================================================
/target

.cache
__pycache__/
site/

# Insta snapshots.
*.pending-snap

# JetBrains IDE
.idea

# Vscode IDE
.vscode

# macOS
**/.DS_Store

# profiling flamegraphs
*.flamegraph.svg


================================================
FILE: .pre-commit-config.yaml
================================================
fail_fast: true
default_install_hook_types: [pre-push]
exclude:
  glob: '**/snapshots/**'

repos:
  - repo: builtin
    hooks:
      - id: trailing-whitespace
        exclude:
          glob: CHANGELOG.md
      - id: mixed-line-ending
      - id: check-yaml
      - id: check-toml
      - id: end-of-file-fixer

  - repo: https://github.com/crate-ci/typos
    rev: v1.44.0
    hooks:
      - id: typos

  - repo: https://github.com/executablebooks/mdformat
    rev: '1.0.0'
    hooks:
      - id: mdformat
        language: python  # ensures that Renovate can update additional_dependencies
        args: [--number, --compact-tables, --align-semantic-breaks-in-lists]
        additional_dependencies:
          - mdformat-mkdocs==5.1.4
          - mdformat-simple-breaks==0.1.0

  - repo: https://github.com/python-jsonschema/check-jsonschema
    rev: 0.37.0
    hooks:
      - id: check-metaschema
        files:
          glob: prek.schema.json
      - id: check-github-workflows
      - id: check-renovate
        additional_dependencies: ['json5']

  - repo: local
    hooks:
      - id: taplo-fmt
        name: taplo fmt
        entry: taplo fmt --config .config/taplo.toml
        language: python
        additional_dependencies: ["taplo==0.9.3"]
        types: [toml]

  - repo: local
    hooks:
      - id: cargo-fmt
        name: cargo fmt
        entry: cargo fmt --
        language: system
        types: [rust]
        pass_filenames: false # This makes it a lot faster

      - id: cargo-clippy
        name: cargo clippy
        language: system
        types: [rust]
        pass_filenames: false
        entry: cargo clippy --all-targets --all-features -- -D warnings


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## 0.3.6

Released on 2026-03-16.

### Enhancements

- Allow selectors for hook ids containing colons ([#1782](https://github.com/j178/prek/pull/1782))
- Rename `prek install-hooks` to `prek prepare-hooks` and `prek install --install-hooks` to `prek install --prepare-hooks` ([#1766](https://github.com/j178/prek/pull/1766))
- Retry auth-failed repo clones with terminal prompts enabled ([#1761](https://github.com/j178/prek/pull/1761))

### Performance

- Optimize `detect_private_key` by chunked reading and using aho-corasick ([#1791](https://github.com/j178/prek/pull/1791))
- Optimize `fix_byte_order_marker` by shifting file contents in place ([#1790](https://github.com/j178/prek/pull/1790))

### Bug fixes

- Align stage defaulting behavior with pre-commit ([#1788](https://github.com/j178/prek/pull/1788))
- Make sure child output is drained in the PTY subprocess ([#1768](https://github.com/j178/prek/pull/1768))
- fix(golang): use `GOTOOLCHAIN=local` when probing system go ([#1797](https://github.com/j178/prek/pull/1797))

### Documentation

- Disambiguate “hook” terminology by renaming "Git hooks" to "Git shims" ([#1776](https://github.com/j178/prek/pull/1776))
- Document compatibility with pre-commit ([#1767](https://github.com/j178/prek/pull/1767))
- Update configuration.md with TOML 1.1 notes ([#1764](https://github.com/j178/prek/pull/1764))

### Other changes

- Sync latest identify tags ([#1798](https://github.com/j178/prek/pull/1798))

### Contributors

- @github-actions
- @j178
- @pcastellazzi
- @deadnews
- @copilot-swe-agent

## 0.3.5

Released on 2026-03-09.

### Enhancements

- Add automatic Ruby download support using rv binaries ([#1668](https://github.com/j178/prek/pull/1668))
- Adjust open file limit on process startup ([#1705](https://github.com/j178/prek/pull/1705))
- Allow parallel gem retry ([#1732](https://github.com/j178/prek/pull/1732))
- Enable system-proxy feature on reqwest ([#1738](https://github.com/j178/prek/pull/1738))
- Expose `--git-dir` to force hook installation target ([#1723](https://github.com/j178/prek/pull/1723))
- Pass `--quiet`, `--verbose`, and `--no-progress` through `prek install` into generated hook scripts ([#1753](https://github.com/j178/prek/pull/1753))
- Respect `core.sharedRepository` for hook permissions ([#1755](https://github.com/j178/prek/pull/1755))
- Support legacy mode hook script ([#1706](https://github.com/j178/prek/pull/1706))
- rust: support `cli:` git dependency 4th segment package disambiguation ([#1747](https://github.com/j178/prek/pull/1747))

### Bug fixes

- Fix Python `__main__.py` entry ([#1741](https://github.com/j178/prek/pull/1741))
- python: strip `UV_SYSTEM_PYTHON` from `uv venv` and `pip install` commands ([#1756](https://github.com/j178/prek/pull/1756))

### Other changes

- Sync latest identify tags ([#1733](https://github.com/j178/prek/pull/1733))

### Contributors

- @Dev-iL
- @tennox
- @shaanmajid
- @is-alnilam
- @github-actions
- @j178

## 0.3.4

Released on 2026-02-28.

### Enhancements

- Allow `pass_filenames` to accept a positive integer ([#1698](https://github.com/j178/prek/pull/1698))
- Install and compile gems in parallel ([#1674](https://github.com/j178/prek/pull/1674))
- Sync identify file-type mappings with pre-commit identify ([#1660](https://github.com/j178/prek/pull/1660))
- Use `--locked` for Rust `cargo install` commands ([#1661](https://github.com/j178/prek/pull/1661))
- Add `PREK_MAX_CONCURRENCY` environment variable for configuring maximum concurrency ([#1697](https://github.com/j178/prek/pull/1697))
- Add `PREK_LOG_TRUNCATE_LIMIT` environment variable for configuring log truncation ([#1679](https://github.com/j178/prek/pull/1679))
- Add support for `python -m prek` ([#1686](https://github.com/j178/prek/pull/1686))

### Bug fixes

- Skip invalid Rust toolchains instead of failing ([#1699](https://github.com/j178/prek/pull/1699))

### Performance

- Bitset-based TagSet refactor: precompute tag masks and speed up hook type filtering ([#1665](https://github.com/j178/prek/pull/1665))

### Documentation

- Document `winget install j178.Prek` ([#1670](https://github.com/j178/prek/pull/1670))

### Contributors

- @uplsh580
- @Svecco
- @dbast
- @drichardson
- @JP-Ellis
- @j178
- @is-alnilam
- @copilot-swe-agent

## 0.3.3

Released on 2026-02-15.

### Enhancements

- Read Python version specifier from hook repo `pyproject.toml` ([#1596](https://github.com/j178/prek/pull/1596))
- Add `#:schema` directives to generated prek.toml ([#1597](https://github.com/j178/prek/pull/1597))
- Add `prek util list-builtins` command ([#1600](https://github.com/j178/prek/pull/1600))
- Expand install source detection to `mise`, `uv tool`, `pipx`, and `asdf` ([#1605](https://github.com/j178/prek/pull/1605), [#1607](https://github.com/j178/prek/pull/1607))
- Add progress bar to `cache clean` and show removal summary ([#1616](https://github.com/j178/prek/pull/1616))
- Make `yaml-to-toml` CONFIG argument optional ([#1593](https://github.com/j178/prek/pull/1593))
- `prek uninstall` removes legacy scripts too ([#1622](https://github.com/j178/prek/pull/1622))

### Bug fixes

- Fix underflow when formatting summary output ([#1626](https://github.com/j178/prek/pull/1626))
- Match `files/exclude` filter against relative path of nested project ([#1624](https://github.com/j178/prek/pull/1624))
- Select `musllinux` wheel tag for uv on musl-based distros ([#1628](https://github.com/j178/prek/pull/1628))

### Documentation

- Clarify `prek list` description ([#1604](https://github.com/j178/prek/pull/1604))

### Contributors

- @ichoosetoaccept
- @shaanmajid
- @soraxas
- @9999years
- @j178

## 0.3.2

Released on 2026-02-06.

### Highlights

- **`prek.toml` is here!**

    You can now use `prek.toml` as an alternative to `.pre-commit-config.yaml` for configuring prek. `prek.toml` mirrors the structure of `.pre-commit-config.yaml`, but TOML is less error-prone. Your existing `.pre-commit-config.yaml` will continue to work, but for new users and new projects, `prek.toml` may make more sense. If you want to switch, run `prek util yaml-to-toml` to convert YAML configs to `prek.toml`. See [configuration docs](configuration.md) for details.

    For example, this config:

    ```yaml
    repos:
      - repo: https://github.com/pre-commit/pre-commit-hooks
        rev: v6.0.0
        hooks:
          - id: check-yaml
    ```

    Can be written as `prek.toml` like this:

    ```toml
    [[repos]]
    repo = "https://github.com/pre-commit/pre-commit-hooks"
    rev = "v6.0.0"
    hooks = [ { id = "check-yaml" } ]
    ```

- **`serde-yaml` has been replaced with `serde-saphyr`**

    We replaced the long-deprecated `serde-yaml` crate with [`serde-saphyr`](https://crates.io/crates/serde-saphyr) for YAML parsing. It is written in safe Rust and has better error messages, performance, and security. This lets us provide precise location information for configuration parsing errors, which should make it easier to fix config issues.

    For example, this invalid config:

    ```yaml
    repos:
      - repo: https://github.com/crate-ci/typos
        hooks:
          - id: typos
    ```

    Before:

    ```console
    $ prek run
    error: Failed to parse `.pre-commit-config.yaml`
      caused by: Invalid remote repo: missing field `rev`
    ```

    Now:

    ```console
    $ prek run
    error: Failed to parse `.pre-commit-config.yaml`
    caused by: error: line 2 column 5: missing field `rev` at line 2, column 5
    --> <input>:2:5
      |
    1 | repos:
    2 |   - repo: https://github.com/crate-ci/typos
      |     ^ missing field `rev` at line 2, column 5
    3 |     hooks:
    4 |       - id: typos
      |
    ```

- **`prek util` subcommands**

    We added a new `prek util` top-level command for miscellaneous utilities that don't fit into other categories. The first two utilities are:

    - `prek util identify`: shows the identification tags of files that prek uses for file filtering, which can be useful for debugging and writing `types/types_or/exclude_types` filters.
    - `prek util yaml-to-toml`: converts `.pre-commit-config.yaml` to `prek.toml`.

    We also moved `prek init-template-dir` under `prek util` for better organization. The old `prek init-template-dir` command is still available (hidden) as an alias for backward compatibility.

### Enhancements

- Add `prek util identify` subcommand ([#1554](https://github.com/j178/prek/pull/1554))
- Add `prek util yaml-to-toml` to convert `.pre-commit-config.yaml` to `prek.toml` ([#1584](https://github.com/j178/prek/pull/1584))
- Detect install source for actionable upgrade hints ([#1540](https://github.com/j178/prek/pull/1540))
- Detect prek installed by the standalone installer ([#1545](https://github.com/j178/prek/pull/1545))
- Implement `serialize_yaml_scalar` using `serde-saphyr` ([#1534](https://github.com/j178/prek/pull/1534))
- Improve max cli arguments length calculation ([#1518](https://github.com/j178/prek/pull/1518))
- Move `identify` and `init-template-dir` under the `prek util` top-level command ([#1574](https://github.com/j178/prek/pull/1574))
- Replace serde-yaml with serde-saphyr (again) ([#1520](https://github.com/j178/prek/pull/1520))
- Show precise location for config parsing error ([#1530](https://github.com/j178/prek/pull/1530))
- Support `Julia` language ([#1519](https://github.com/j178/prek/pull/1519))
- Support `prek.toml` ([#1271](https://github.com/j178/prek/pull/1271))
- Added `PREK_QUIET` environment variable support ([#1513](https://github.com/j178/prek/pull/1513))
- Remove upper bound constraint of uv version ([#1588](https://github.com/j178/prek/pull/1588))

### Bug fixes

- Do not make the child a session leader ([#1586](https://github.com/j178/prek/pull/1586))
- Fix FilePattern schema to accept plain strings ([#1564](https://github.com/j178/prek/pull/1564))
- Use semver fallback sort when tag timestamps are equal ([#1579](https://github.com/j178/prek/pull/1579))

### Documentation

- Add `OpenClaw` to the list of users ([#1517](https://github.com/j178/prek/pull/1517))
- Add `cachix/devenv`, `apache/lucene`, `copper-project/copper-rs` as projects using prek ([#1531](https://github.com/j178/prek/pull/1531), [#1514](https://github.com/j178/prek/pull/1514), [#1569](https://github.com/j178/prek/pull/1569))
- Add document about authoring remote hooks ([#1571](https://github.com/j178/prek/pull/1571))
- Add `llms.txt` generation for LLM-friendly documentation ([#1553](https://github.com/j178/prek/pull/1553))
- Document using `--refresh` to pick up `.prekignore` changes ([#1575](https://github.com/j178/prek/pull/1575))
- Fix PowerShell completion instruction syntax ([#1568](https://github.com/j178/prek/pull/1568))
- Update quick start to use `prek.toml` ([#1576](https://github.com/j178/prek/pull/1576))

### Other changes

- Include `prek.toml` in run hint for config filename ([#1578](https://github.com/j178/prek/pull/1578))

### Contributors

- @fatelei
- @domenkozar
- @makeecat
- @fllesser
- @j178
- @copilot-swe-agent
- @oopscompiled
- @rmuir
- @shaanmajid

## 0.3.1

Released on 2026-01-31.

### Enhancements

- Add `language: swift` support ([#1463](https://github.com/j178/prek/pull/1463))
- Add `language: haskell` support ([#1484](https://github.com/j178/prek/pull/1484))
- Extract go version constraint from `go.mod` ([#1457](https://github.com/j178/prek/pull/1457))
- Warn when config file exists but fails to parse ([#1487](https://github.com/j178/prek/pull/1487))
- Add GitHub artifact attestations to release and build-docker workflow ([#1494](https://github.com/j178/prek/pull/1494), [#1497](https://github.com/j178/prek/pull/1497))
- Allow `GIT_CONFIG_PARAMETERS` for private repository authentication ([#1472](https://github.com/j178/prek/pull/1472))
- Show progress bar when running builtin hooks ([#1504](https://github.com/j178/prek/pull/1504))

### Bug fixes

- Cap ARG_MAX at `1<<19` for safety ([#1506](https://github.com/j178/prek/pull/1506))
- Don't check Python executable path in health check ([#1496](https://github.com/j178/prek/pull/1496))

### Documentation

- Include `CocoIndex` as a project using prek ([#1477](https://github.com/j178/prek/pull/1477))
- Add commands for artifact verification using GitHub Attestations ([#1500](https://github.com/j178/prek/pull/1500))

### Contributors

- @halms
- @Haleshot
- @simono
- @tisonkun
- @fllesser
- @j178
- @shaanmajid

## 0.3.0

Released on 2026-01-22.

### Highlights

- `prek cache gc` (also available via `prek gc` for pre-commit compatibility) is finally here! You can now run `prek cache gc` to clean up unused repos, hook envs and tool versions from prek cache.
- `language: bun` is now supported, making it possible to write and run hooks with [Bun](https://bun.sh/).

### Enhancements

- Implement `prek cache gc` ([#1410](https://github.com/j178/prek/pull/1410))

    - Bootstrap tracking configs from workspace cache ([#1417](https://github.com/j178/prek/pull/1417))
    - Show total size `prek cache gc` removed ([#1418](https://github.com/j178/prek/pull/1418))
    - Show accurate repo and hook details in `prek cache gc -v` ([#1420](https://github.com/j178/prek/pull/1420))
    - `prek cache gc` remove specific unused tool versions ([#1422](https://github.com/j178/prek/pull/1422))
    - Fix unused tool versions not removed in `prek cache gc` ([#1436](https://github.com/j178/prek/pull/1436))

- Add `language: bun` support ([#1411](https://github.com/j178/prek/pull/1411))

    - Use `git ls-remote --tags` to list bun versions ([#1439](https://github.com/j178/prek/pull/1439))

- Accept `--stage` as an alias for `--hook-stage` in `prek run` ([#1398](https://github.com/j178/prek/pull/1398))

- Expand `~` tilde in `PREK_HOME` ([#1431](https://github.com/j178/prek/pull/1431))

- Support refs to trees ([#1449](https://github.com/j178/prek/pull/1449))

### Bug fixes

- Avoid file lock warning for in-process contention ([#1406](https://github.com/j178/prek/pull/1406))
- Resolve relative repo paths from config file directory ([#1443](https://github.com/j178/prek/pull/1443))
- fix: use `split()` instead of `resolve(None)` for builtin hook argument parsing ([#1415](https://github.com/j178/prek/pull/1415))

### Documentation

- Add `simple-icons` and `ast-grep` to the users of prek ([#1403](https://github.com/j178/prek/pull/1403))
- Improve JSON schema for `repo` field ([#1432](https://github.com/j178/prek/pull/1432))
- Improve JSON schema for builtin and meta hooks ([#1427](https://github.com/j178/prek/pull/1427))
- Add pronunciation entry to FAQ ([#1442](https://github.com/j178/prek/pull/1442))
- Add commitizen to the list of projects using prek ([#1413](https://github.com/j178/prek/pull/1413))
- Move docs to zensical ([#1421](https://github.com/j178/prek/pull/1421))

### Other Changes

- Refactor config layout ([#1407](https://github.com/j178/prek/pull/1407))

### Contributors

- @shaanmajid
- @KevinGimbel
- @jtamagnan
- @jmeickle-theaiinstitute
- @YazdanRa
- @j178
- @mschoettle
- @tisonkun

## 0.2.30

Released on 2026-01-18.

### Enhancements

- Build binaries using minimal-size profile ([#1376](https://github.com/j178/prek/pull/1376))
- Check for duplicate keys in `check-json5` builtin hook ([#1387](https://github.com/j178/prek/pull/1387))
- Preserve quoting style in `auto-update` ([#1379](https://github.com/j178/prek/pull/1379))
- Show warning if file lock acquiring blocks for long time ([#1353](https://github.com/j178/prek/pull/1353))
- Singleflight Python health checks with cached interpreter info ([#1381](https://github.com/j178/prek/pull/1381))

### Bug fixes

- Do not resolve entry for docker_image ([#1386](https://github.com/j178/prek/pull/1386))
- Fix command lookup on Windows ([#1383](https://github.com/j178/prek/pull/1383))

### Documentation

- Document language support details ([#1380](https://github.com/j178/prek/pull/1380))
- Document that `check-json5` now rejects duplicate keys ([#1391](https://github.com/j178/prek/pull/1391))

### Contributors

- @j178

## 0.2.29

Released on 2026-01-16.

### Highlights

`files` / `exclude` now support globs (including glob lists), making config filters much easier to read and maintain than heavily-escaped regex.

Before (regex):

```yaml
files: "^(src/.*\\.rs$|crates/[^/]+/src/.*\\.rs$)"
```

After (glob list):

```yaml
files:
  glob:
    - src/**/*.rs
    - crates/**/src/**/*.rs
```

### Enhancements

- Add `check-json5` as builtin hooks ([#1367](https://github.com/j178/prek/pull/1367))
- Add glob list support for file patterns (`files` and `exclude`) ([#1197](https://github.com/j178/prek/pull/1197))

### Bug fixes

- Fix missing commit hash from version info ([#1352](https://github.com/j178/prek/pull/1352))
- Remove git env vars from `uv pip install` subprocess ([#1355](https://github.com/j178/prek/pull/1355))
- Set `TERM=dumb` under PTY to prevent capability-probe hangs ([#1363](https://github.com/j178/prek/pull/1363))

### Documentation

- Add `home-assistant/core` to the users of prek ([#1350](https://github.com/j178/prek/pull/1350))
- Document builtin hooks ([#1370](https://github.com/j178/prek/pull/1370))
- Explain project configuration scope ([#1373](https://github.com/j178/prek/pull/1373))

### Contributors

- @Goldziher
- @yihong0618
- @j178
- @shaanmajid
- @ulgens

## 0.2.28

Released on 2026-01-13.

### Enhancements

- Avoid running `git diff` for skipped hooks ([#1335](https://github.com/j178/prek/pull/1335))
- More accurate command line length limit calculation ([#1348](https://github.com/j178/prek/pull/1348))
- Raise platform command line length upper limit ([#1347](https://github.com/j178/prek/pull/1347))
- Use `/bin/sh` in generated git hook scripts ([#1333](https://github.com/j178/prek/pull/1333))

### Bug fixes

- Avoid rewriting if config is up-to-date ([#1346](https://github.com/j178/prek/pull/1346))

### Documentation

- Add `ty` to the users of prek ([#1342](https://github.com/j178/prek/pull/1342))
- Add `ruff` to the users of prek ([#1334](https://github.com/j178/prek/pull/1334))
- Complete configuration document ([#1338](https://github.com/j178/prek/pull/1338))
- Document UV environment variable inheritance in prek ([#1339](https://github.com/j178/prek/pull/1339))

### Contributors

- @copilot-swe-agent
- @MatthewMckee4
- @yihong0618
- @j178

## 0.2.27

Released on 2026-01-07.

### Highlights

`python/cpython` is now [using](https://github.com/j178/prek/pull/1308) prek. That’s the highlight of this release!

### Enhancements

- Add hook-level `env` option to set environment variables for hooks (#1279) ([#1285](https://github.com/j178/prek/pull/1285))
- Support apple's `container` for docker language ([#1306](https://github.com/j178/prek/pull/1306))
- Skip cookiecutter template directories like `{{cookiecutter.project_slug}}` during project discovery ([#1316](https://github.com/j178/prek/pull/1316))
- Use global `CONCURRENCY` for repo clone ([#1292](https://github.com/j178/prek/pull/1292))
- untar: disallow external symlinks ([#1314](https://github.com/j178/prek/pull/1314))

### Bug fixes

- Exit with success if no hooks match the hook stage ([#1317](https://github.com/j178/prek/pull/1317))
- Fix Go template string to detect rootless podman ([#1302](https://github.com/j178/prek/pull/1302))
- Panic on overly long filenames instead of silently dropping files ([#1287](https://github.com/j178/prek/pull/1287))

### Other changes

- Add `python/cpython` to users ([#1308](https://github.com/j178/prek/pull/1308))
- Add `MoonshotAI/kimi-cli` to users ([#1286](https://github.com/j178/prek/pull/1286))
- Drop powerpc64 wheels ([#1319](https://github.com/j178/prek/pull/1319))

### Contributors

- @ulgens
- @loganaden
- @danielparks
- @branchv
- @j178
- @yihong0618
- @mocknen
- @copilot-swe-agent
- @ZhuoZhuoCrayon

## 0.2.25

Released on 2025-12-27.

### Performance

- Use `git cat-file -e` in check if a rev exists ([#1277](https://github.com/j178/prek/pull/1277))

### Bug fixes

- Fix `priority` not applied for remote hooks ([#1281](https://github.com/j178/prek/pull/1281))
- Report config file parsing error in `auto-update` ([#1274](https://github.com/j178/prek/pull/1274))
- Unset `GIT_DIR` for auto-update ([#1269](https://github.com/j178/prek/pull/1269))

### Contributors

- @j178
- @branchv

## 0.2.24

Released on 2025-12-23.

### Enhancements

- Build and publish docker image to `ghcr.io/j178/prek` ([#1253](https://github.com/j178/prek/pull/1253))
- Support git urls for rust dependencies ([#1256](https://github.com/j178/prek/pull/1256))

### Bug fixes

- Ensure running `uv pip install` inside the remote repo path ([#1262](https://github.com/j178/prek/pull/1262))
- Fix `check-added-large-files` for traced files ([#1260](https://github.com/j178/prek/pull/1260))
- Respect `GIT_DIR` set by git ([#1258](https://github.com/j178/prek/pull/1258))

### Documentation

- Add docker integration docs ([#1254](https://github.com/j178/prek/pull/1254))
- Clarify `priority` scope across repos ([#1251](https://github.com/j178/prek/pull/1251))
- Improve documentation for configurations ([#1247](https://github.com/j178/prek/pull/1247))
- Render changelog in document site ([#1248](https://github.com/j178/prek/pull/1248))

### Contributors

- @j178
- @branchv

## 0.2.23

Released on 2025-12-20.

### Highlights

🚀 This release introduces priority-based parallel hook execution: prek can run multiple hooks in parallel when they share the same `priority`, which can be a huge speed-up for many configs. See configuration docs for [`priority`](https://prek.j178.dev/configuration/#priority).

### Enhancements

- Allow uv reading user-level or system-level configuration files ([#1227](https://github.com/j178/prek/pull/1227))
- Implement `check-case-conflict` as builtin hook ([#888](https://github.com/j178/prek/pull/888))
- Implement `priority` based parallel execution ([#1232](https://github.com/j178/prek/pull/1232))

### Bug fixes

- Fix `check-executable-have-shebangs` "command line too long" error on Windows ([#1236](https://github.com/j178/prek/pull/1236))

### Documentation

- Add FastAPI to the list of projects using prek ([#1241](https://github.com/j178/prek/pull/1241))
- Document hook_types flag and default_install_hook_types behavior ([#1225](https://github.com/j178/prek/pull/1225))
- Improve documentation for `priority` ([#1245](https://github.com/j178/prek/pull/1245))
- Mention prek can be installed via`taiki-e/install-action@prek` ([#1234](https://github.com/j178/prek/pull/1234))

### Contributors

- @j178
- @copilot-swe-agent
- @lmmx

## 0.2.22

Released on 2025-12-13.

### Highlights

In this release, prek adds support for the `--cooldown-days` option in the `prek auto-update` command.
This option allows users to skip releases that are newer than a specified number of days.
It is useful to mitigate open source supply chain risks by avoiding very recent releases that may not have been widely adopted or vetted yet.
Big thanks to @lmmx for driving this feature!

### Enhancements

- Support`--cooldown-days` in `prek auto-update` ([#1172](https://github.com/j178/prek/pull/1172))
    - Prefer tag creation timestamp in `--cooldown-days` ([#1221](https://github.com/j178/prek/pull/1221))
- Use `cargo install` for packages in workspace ([#1207](https://github.com/j178/prek/pull/1207))

### Bug fixes

- Set `CARGO_HOME` for `cargo metadata` ([#1209](https://github.com/j178/prek/pull/1209))

### Contributors

- @j178
- @lmmx

## 0.2.21

Released on 2025-12-09.

### Bug fixes

- Fallback to use remote repo package root instead of erroring ([#1203](https://github.com/j178/prek/pull/1203))
- Prepend toolchain bin directory to PATH when calling cargo ([#1204](https://github.com/j178/prek/pull/1204))
- Use `cargo` from installed toolchain ([#1202](https://github.com/j178/prek/pull/1202))

### Contributors

- @j178

## 0.2.20

Released on 2025-12-08.

### Highlights

In this release:

- Rust hooks are now fully supported with automatic toolchain management, including package discovery in virtual workspaces. Big thanks to @lmmx for driving this.
- Added a `prek cache size` subcommand so you can quickly see how much cache space prek is using. Thanks @MatthewMckee4!
- Nested workspaces are easier to reason about: set `orphan: true` on a project to isolate it from parents so its files are processed only once.

Want to show your project runs on prek? Add our README badge to your docs or repo homepage: [![prek](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json)](https://github.com/j178/prek)

### Enhancements

- Support Rust language ([#989](https://github.com/j178/prek/pull/989))
    - Refactor Rust toolchain management ([#1198](https://github.com/j178/prek/pull/1198))
    - Add support for finding packages in virtual workspaces ([#1180](https://github.com/j178/prek/pull/1180))
- Add `prek cache size` command ([#1183](https://github.com/j178/prek/pull/1183))
- Support orphan projects ([#1129](https://github.com/j178/prek/pull/1129))
- Fallback to `manual` stage for hooks specified directly in command line ([#1185](https://github.com/j178/prek/pull/1185))
- Make go module cache read-writeable (thus deletable) ([#1164](https://github.com/j178/prek/pull/1164))
- Provide more information when validating configs and manifests ([#1182](https://github.com/j178/prek/pull/1182))
- Improve error message for invalid number of arguments to hook-impl ([#1196](https://github.com/j178/prek/pull/1196))

### Bug fixes

- Disable git terminal prompts ([#1193](https://github.com/j178/prek/pull/1193))
- Prevent `post-checkout` deadlock when cloning repos ([#1192](https://github.com/j178/prek/pull/1192))
- Prevent color output when redirecting stdout to a file ([#1159](https://github.com/j178/prek/pull/1159))

### Documentation

- Add MacPorts to installation methods ([#1157](https://github.com/j178/prek/pull/1157))
- Add a FAQ page explaining `prek install --install--hooks` ([#1162](https://github.com/j178/prek/pull/1162))

### Other changes

- Add `prek: enabled` repo badge ([#1171](https://github.com/j178/prek/pull/1171))
- Add favicon for docs website ([#1187](https://github.com/j178/prek/pull/1187))

### Contributors

- @MatthewMckee4
- @lmmx
- @j178
- @joshmarkovic
- @frazar
- @jmelahman
- @drainpixie

## 0.2.19

Released on 2025-11-26.

### Performance

- Simplify `fix_byte_order_marker` hook ([#1136](https://github.com/j178/prek/pull/1136))
- Simplify `trailing-whitespace` hook to improve performance ([#1135](https://github.com/j178/prek/pull/1135))

### Bug fixes

- Close stdin for hook subcommands ([#1155](https://github.com/j178/prek/pull/1155))
- Fix parsing Python interpreter info containing non-UTF8 chars ([#1141](https://github.com/j178/prek/pull/1141))

### Contributors

- @chilin0525
- @nblock
- @j178

## 0.2.18

Released on 2025-11-21.

### Highlights

In this release, prek adds a new special repo type `repo: builtin` that lets you use built‑in hooks.
It basically gives you another way to use the existing built‑in fast path for pre‑commit‑hooks, but without needing to point to an external repo.
Since prek doesn’t have to clone anything or set up a virtual environment, `repo: builtin` hooks work even in air‑gapped environments.

For more details, see: https://prek.j178.dev/builtin/

### Enhancements

- Add support `repo: builtin` ([#1118](https://github.com/j178/prek/pull/1118))
- Enable virtual terminal processing on Windows ([#1123](https://github.com/j178/prek/pull/1123))

### Bug fixes

- Do not recurse into submodules during workspace discovery ([#1121](https://github.com/j178/prek/pull/1121))
- Do not dim the hook output ([#1126](https://github.com/j178/prek/pull/1126))
- Further reduce max cli length for cmd.exe on Windows ([#1131](https://github.com/j178/prek/pull/1131))
- Revert "Disallow hook-level `minimum_prek_version` (#1101)" ([#1120](https://github.com/j178/prek/pull/1120))

### Other changes

- docs: refer airflow as Apache Airflow ([#1116](https://github.com/j178/prek/pull/1116))

### Contributors

- @j178
- @Lee-W

## 0.2.17

Released on 2025-11-18.

### Bug fixes

- Revert back to use `serde_yaml` again ([#1112](https://github.com/j178/prek/pull/1112))

### Contributors

- @j178

## 0.2.16

Released on 2025-11-18.

### Bug fixes

- Disallow hook-level `minimum_prek_version` ([#1101](https://github.com/j178/prek/pull/1101))
- Do not require a project in `prek init-template-dir` ([#1109](https://github.com/j178/prek/pull/1109))
- Make sure `uv pip install` uses the Python from virtualenv ([#1108](https://github.com/j178/prek/pull/1108))
- Restore using `serde_yaml` in `check-yaml` hook ([#1106](https://github.com/j178/prek/pull/1106))

### Contributors

- @j178

## 0.2.15

Released on 2025-11-17.

### Highlights

prek is now available on crates.io! You can build prek from source via `cargo install prek` or `cargo binstall prek`, for more details see [Installation](https://prek.j178.dev/installation/#build-from-source).

### Enhancements

- Clean up hook environments when install fails ([#1085](https://github.com/j178/prek/pull/1085))
- Prepare for publishing prek to crates.io ([#1088](https://github.com/j178/prek/pull/1088))
- Replace `serde-yaml` with `serde_saphyr` ([#1087](https://github.com/j178/prek/pull/1087))
- Warn unexpected keys in repo and hook level ([#1096](https://github.com/j178/prek/pull/1096))

### Bug fixes

- Fix `prek init-template-dir` fails in non-git repo ([#1093](https://github.com/j178/prek/pull/1093))

### Contributors

- @j178

## 0.2.14

Released on 2025-11-14.

### Enhancements

- Support `PREK_CONTAINER_RUNTIME=podman` to override container runtime ([#1033](https://github.com/j178/prek/pull/1033))
- Support rootless container runtime ([#1018](https://github.com/j178/prek/issues/1018))
- Support `language: unsupported` and `language: unsupported_script` introduced in pre-commit v4.4 ([#1073](https://github.com/j178/prek/pull/1073))
- Tweak to regex used for mountinfo ([#1037](https://github.com/j178/prek/pull/1037))

### Bug fixes

- Fix `--files` argument - files referencing other projects aren’t being filtered ([#1064](https://github.com/j178/prek/pull/1064))
- Unset `objectFormat` in `git init` ([#1048](https://github.com/j178/prek/pull/1048))

### Documentation

- Add scoop to installation ([#1067](https://github.com/j178/prek/pull/1067))
- Document workspace file visibility constraints ([#1071](https://github.com/j178/prek/pull/1071))
- Add `iceberg-python`, `msgspec` and `humanize` to "who is using prek" ([#1039](https://github.com/j178/prek/pull/1039), [#1042](https://github.com/j178/prek/pull/1042), [#1063](https://github.com/j178/prek/pull/1063))

### Other changes

- Add a hint to install when running inside a sub-project ([#1045](https://github.com/j178/prek/pull/1045))
- Add a hint to use `--refresh` when no configuration found ([#1046](https://github.com/j178/prek/pull/1046))
- Run uv pip install from the current directory ([#1069](https://github.com/j178/prek/pull/1069))

### Contributors

- @zzstoatzz
- @st1971
- @yihong0618
- @j178
- @copilot-swe-agent
- @idlsoft

## 0.2.13

Released on 2025-11-04.

### Enhancements

- Add Ruby support (no download support yet) ([#993](https://github.com/j178/prek/pull/993))
- Implement `check-executables-have-shebangs` as builtin-hook ([#924](https://github.com/j178/prek/pull/924))
- Improve container id detection ([#1031](https://github.com/j178/prek/pull/1031))

### Performance

- Optimize hot paths: reduce allocations ([#997](https://github.com/j178/prek/pull/997))
- Refactor `identify` using smallvec ([#982](https://github.com/j178/prek/pull/982))

### Bug fixes

- Fix YAML with nested merge keys ([#1020](https://github.com/j178/prek/pull/1020))
- Treat every file as executable on Windows to keep compatibility with pre-commit ([#980](https://github.com/j178/prek/pull/980))

### Documentation

- Document that .gitignore is respected by default during workspace discovery ([#983](https://github.com/j178/prek/pull/983))
- Update project stability status ([#1005](https://github.com/j178/prek/pull/1005))
- Add FastMCP to "who is using prek" ([#1034](https://github.com/j178/prek/pull/1034))
- Add attrs to "who is using prek" ([#981](https://github.com/j178/prek/pull/981))

### Contributors

- @my1e5
- @j178
- @zzstoatzz
- @lmmx
- @feliblo
- @yihong0618
- @st1971
- @is-alnilam

## 0.2.12

Released on 2025-10-27.

### Enhancements

- Add a warning for unimplemented hooks ([#976](https://github.com/j178/prek/pull/976))
- Allow using system trusted store by `PREK_NATIVE_TLS` ([#959](https://github.com/j178/prek/pull/959))

### Bug fixes

- Do not check for `script` subprocess status ([#964](https://github.com/j178/prek/pull/964))
- Fix compatibility with older luarocks ([#967](https://github.com/j178/prek/pull/967))
- Fix local relative path in `try-repo` ([#975](https://github.com/j178/prek/pull/975))

### Documentation

- Update language support status ([#970](https://github.com/j178/prek/pull/970))

### Contributors

- @yihong0618
- @st1971
- @j178

## 0.2.11

Released on 2025-10-24.

### Enhancements

- Support `language: lua` hooks ([#954](https://github.com/j178/prek/pull/954))
- Support `language_version: system` ([#949](https://github.com/j178/prek/pull/949))
- Implement `no-commit-to-branch` as builtin hook ([#930](https://github.com/j178/prek/pull/930))
- Improve styling for stashing error message ([#953](https://github.com/j178/prek/pull/953))
- Support nix-shell style shebang ([#929](https://github.com/j178/prek/pull/929))

### Documentation

- Add a page about "Quick start" ([#934](https://github.com/j178/prek/pull/934))
- Add kreuzberg to "who is using prek" ([#936](https://github.com/j178/prek/pull/936))
- Clarify minimum mise version required to use `mise use prek` ([#931](https://github.com/j178/prek/pull/931))

### Contributors

- @fllesser
- @j178

## 0.2.10

Released on 2025-10-18.

### Enhancements

- Add `--fail-fast` CLI flag to stop after first hook failure ([#908](https://github.com/j178/prek/pull/908))
- Add collision detection for hook env directories ([#914](https://github.com/j178/prek/pull/914))
- Error out if not projects found ([#913](https://github.com/j178/prek/pull/913))
- Implement `check-xml` as builtin hook ([#894](https://github.com/j178/prek/pull/894))
- Implement `check-merge-conflict` as builtin hook ([#885](https://github.com/j178/prek/pull/885))
- Use line-by-line reading in `check-merge-conflict` ([#910](https://github.com/j178/prek/pull/910))

### Bug fixes

- Fix pygrep hook env health check ([#921](https://github.com/j178/prek/pull/921))
- Group `pygrep` with `python` when installing pygrep hooks ([#920](https://github.com/j178/prek/pull/920))
- Ignore `.` prefixed directory when searching managed Python for pygrep ([#919](https://github.com/j178/prek/pull/919))

### Documentation

- Add contribution guide ([#912](https://github.com/j178/prek/pull/912))

### Other changes

### Contributors

- @AdityasWorks
- @j178
- @kenwoodjw
- @lmmx

## 0.2.9

Released on 2025-10-16.

### Enhancements

- Lazily check hook env health ([#897](https://github.com/j178/prek/pull/897))
- Implement `check-symlinks` as builtin hook ([#895](https://github.com/j178/prek/pull/895))
- Implement `detect-private-key` as builtin hook ([#893](https://github.com/j178/prek/pull/893))

### Bug fixes

- Download files to scratch directory to avoid cross-filesystem rename ([#889](https://github.com/j178/prek/pull/889))
- Fix golang hook install local dependencies ([#902](https://github.com/j178/prek/pull/902))
- Ignore the user-set `UV_MANAGED_PYTHON` ([#900](https://github.com/j178/prek/pull/900))

### Other changes

- Add package metadata for cargo-binstall ([#882](https://github.com/j178/prek/pull/882))

### Contributors

- @j178
- @lmmx

## 0.2.8

Released on 2025-10-14.

*This is a re-release of 0.2.6 that fixes an issue where publishing to npmjs.com failed.*

### Enhancements

- Publish prek to npmjs.com ([#819](https://github.com/j178/prek/pull/819))
- Support YAML merge keys in `.pre-commit-config.yaml` ([#871](https://github.com/j178/prek/pull/871))

### Bug fixes

- Use relative path with `--cd` in the generated hook script ([#868](https://github.com/j178/prek/pull/868))
- Fix autoupdate `rev` rendering for "float-like" version numbers ([#867](https://github.com/j178/prek/pull/867))

### Documentation

- Add Nix and Conda installation details ([#874](https://github.com/j178/prek/pull/874))

### Contributors

- @mondeja
- @j178
- @bbannier
- @yihong0618
- @colindean

## 0.2.5

Released on 2025-10-10.

### Enhancements

- Implement `prek try-repo` ([#797](https://github.com/j178/prek/pull/797))
- Add fallback mechanism for prek executable in git hooks ([#850](https://github.com/j178/prek/pull/850))
- Ignore config error if the directory is skipped ([#860](https://github.com/j178/prek/pull/860))

### Bug fixes

- Fix panic when parse config failed ([#859](https://github.com/j178/prek/pull/859))

### Other changes

- Add a Dockerfile ([#852](https://github.com/j178/prek/pull/852))

### Contributors

- @j178
- @luizvbo

## 0.2.4

Released on 2025-10-07.

### Enhancements

- Add support for `.prekignore` to ignore directories from project discovery ([#826](https://github.com/j178/prek/pull/826))
- Make `prek auto-update --jobs` default to 0 (which uses max available parallelism) ([#833](https://github.com/j178/prek/pull/833))
- Improve install message when installing for a subproject ([#847](https://github.com/j178/prek/pull/847))

### Bug fixes

- Convert extension to lowercase before checking file tags ([#839](https://github.com/j178/prek/pull/839))
- Support pass multiple files like `prek run --files a b c d` ([#828](https://github.com/j178/prek/pull/828))

### Documentation

- Add requests-cache to "Who is using prek" ([#824](https://github.com/j178/prek/pull/824))

### Contributors

- @SigureMo
- @j178

## 0.2.3

Released on 2025-09-29.

### Enhancements

- Add `--dry-run` to `prek auto-update` ([#806](https://github.com/j178/prek/pull/806))
- Add a global `--log-file` flag to specify the log file path ([#817](https://github.com/j178/prek/pull/817))
- Implement hook health check ([#798](https://github.com/j178/prek/pull/798))
- Show error message in quiet mode ([#807](https://github.com/j178/prek/pull/807))

### Bug fixes

- Write `fail` entry into output directly ([#811](https://github.com/j178/prek/pull/811))

### Documentation

- Update docs about uv in prek ([#810](https://github.com/j178/prek/pull/810))

### Other changes

- Add a security policy for reporting vulnerabilities ([#804](https://github.com/j178/prek/pull/804))

### Contributors

- @mondeja
- @j178

## 0.2.2

Released on 2025-09-26.

### Enhancements

- Add `prek cache dir`, move `prek gc` and `prek clean` under `prek cache` ([#795](https://github.com/j178/prek/pull/795))
- Add a hint when hooks failed in CI ([#800](https://github.com/j178/prek/pull/800))
- Add support for specifying `PREK_UV_SOURCE` ([#766](https://github.com/j178/prek/pull/766))
- Run docker container with `--init` ([#791](https://github.com/j178/prek/pull/791))
- Support `--allow-multiple-documents` for `check-yaml` ([#790](https://github.com/j178/prek/pull/790))

### Bug fixes

- Fix interpreter identification ([#801](https://github.com/j178/prek/pull/801))

### Documentation

- Add PaperQA2 to "Who is using prek" ([#793](https://github.com/j178/prek/pull/793))
- Clarify built-in hooks activation conditions and behavior ([#781](https://github.com/j178/prek/pull/781))
- Deduplicate docs between README and MkDocs site ([#792](https://github.com/j178/prek/pull/792))
- Mention `j178/prek-action` in docs ([#753](https://github.com/j178/prek/pull/753))

### Other Changes

- Bump `pre-commit-hooks` in sample-config to v6.0.0 ([#761](https://github.com/j178/prek/pull/761))
- Improve arg parsing for builtin hooks ([#789](https://github.com/j178/prek/pull/789))

### Contributors

- @mondeja
- @akx
- @bxb100
- @j178
- @onerandomusername

## 0.2.1

### Enhancements

- auto-update: prefer tags that are most similar to the current version ([#719](https://github.com/j178/prek/pull/719))

### Bug fixes

- Fix `git --no-pager diff` command syntax upon failures ([#746](https://github.com/j178/prek/pull/746))
- Clean working tree of current workspace only ([#747](https://github.com/j178/prek/pull/747))
- Use concurrent read and write in `git check-attr` ([#731](https://github.com/j178/prek/pull/731))

### Documentation

- Fix typo in language-version to language_version ([#727](https://github.com/j178/prek/pull/727))
- Update benchmarks ([#728](https://github.com/j178/prek/pull/728))

### Contributors

- @j178
- @matthiask
- @AdrianDC
- @onerandomusername

## 0.2.0

This is a huge milestone release that introduces **Workspace Mode** — first‑class monorepo support.

`prek` now allows you to manage multiple projects with their own `.pre-commit-config.yaml` within a single repository.
It auto‑discovers nested projects, runs hooks in project scope, and provides flexible selectors to target specific projects and hooks.
This makes `prek` a powerful tool for managing pre-commit hooks in complex repository structures.

For more details, see [Workspace Mode](https://prek.j178.dev/workspace/). If you encounter any issues, please report them at [Issues](https://github.com/j178/prek/issues).

**Note**: If you ran `prek install` in a repo before, you gonna need to run `prek install` again to replace the old git hook scripts for the workspace mode to work.

Special thanks to @potiuk for all the help and feedback in designing and testing this feature!

For detailed changes between 0.1.6 and 0.2.0, see [0.2.0-alpha.2](https://github.com/j178/prek/releases/v0.2.0-alpha.2), [0.2.0-alpha.3](https://github.com/j178/prek/releases/v0.2.0-alpha.3), [0.2.0-alpha.4](https://github.com/j178/prek/releases/v0.2.0-alpha.4), and [0.2.0-alpha.5](https://github.com/j178/prek/releases/v0.2.0-alpha.5).

### Enhancements

- Fix parsing of tag describe for prerelease versions ([#714](https://github.com/j178/prek/pull/714))
- Truncate log file each time ([#717](https://github.com/j178/prek/pull/717))

### Performance

- Enable more aggressive optimizations for release ([#724](https://github.com/j178/prek/pull/724))
- Speed up check_toml ([#713](https://github.com/j178/prek/pull/713))

### Bug fixes

- Fix hook-impl don't run hooks when specified allow missing config ([#716](https://github.com/j178/prek/pull/716))
- fix: support py38 for pygrep ([#723](https://github.com/j178/prek/pull/723))

### Other changes

- Fix installation on fish and with missing tags ([#721](https://github.com/j178/prek/pull/721))

### Contributors

- @onerandomusername
- @kushudai
- @j178

## 0.2.0a5

### Enhancements

- Add built in byte-order-marker fixer ([#700](https://github.com/j178/prek/pull/700))
- Use bigger buffer for fixing trailing whitespace ([#705](https://github.com/j178/prek/pull/705))

### Bug fixes

- Fix `trailing-whitespace` & `mixed-line-ending` write file path ([#708](https://github.com/j178/prek/pull/708))
- Fix file path handling for meta hooks in workspace mode ([#699](https://github.com/j178/prek/pull/699))

### Documentation

- Add docs about configuration ([#703](https://github.com/j178/prek/pull/703))
- Add docs about debugging ([#702](https://github.com/j178/prek/pull/702))
- Generate cli reference ([#707](https://github.com/j178/prek/pull/707))

### Contributors

- @kushudai
- @j178

## 0.2.0a4

### Enhancements

- Bring back `.pre-commit-config.yml` support ([#676](https://github.com/j178/prek/pull/676))
- Ignore config file from hidden directory ([#677](https://github.com/j178/prek/pull/677))
- Support selectors in `prek install/install-hooks/hook-impl` ([#683](https://github.com/j178/prek/pull/683))

### Bug fixes

- Do not set GOROOT for system install Go when running go hooks ([#694](https://github.com/j178/prek/pull/694))
- Fix `check_toml` and `check_yaml` in workspace mode ([#688](https://github.com/j178/prek/pull/688))

### Documentation

- Add docs about TODOs ([#679](https://github.com/j178/prek/pull/679))
- Add docs about builtin hooks ([#678](https://github.com/j178/prek/pull/678))

### Other changes

- docs(manifest): Correctly specify metadata for all packages ([#687](https://github.com/j178/prek/pull/687))
- refactor(cli): Clean up usage of clap ([#689](https://github.com/j178/prek/pull/689))

### Contributors

- @j178
- @epage
- @aravindan888

## 0.2.0a3

### Enhancements

- Add a warning to `hook-impl` when the script needs reinstall ([#647](https://github.com/j178/prek/pull/647))

### Documentation

- Add a notice to rerun `prek install` when upgrading to 0.2.0 ([#646](https://github.com/j178/prek/pull/646))

### Contributors

- @j178

## 0.2.0-alpha.2

*This is a re-release of [0.2.0-alpha.1](https://github.com/j178/prek/releases/tag/v0.2.0-alpha.1), fixed an issue that prereleases are not published to PyPI.*

This is a huge milestone release that introduces **Workspace Mode** — first‑class monorepo support.

`prek` now allows you to manage multiple projects with their own `.pre-commit-config.yaml` within a single repository. It auto‑discovers nested projects, runs hooks in project scope, and provides flexible selectors to target specific projects and hooks. This makes `prek` a powerful tool for managing pre-commit hooks in complex repository structures.

**Note**: If you ran `prek install` in a repo before, you gonna need to run `prek install` again to replace the old git hook scripts for the workspace mode to work.

For more details, see [Workspace Mode](https://prek.j178.dev/workspace/). If you encounter any issues, please report them at [Issues](https://github.com/j178/prek/issues).

Special thanks to @potiuk for all the help and feedback in designing and testing this feature!

### Enhancements

- Support multiple `.pre-commit-config.yaml` in a workspace (monorepo mode) ([#583](https://github.com/j178/prek/pull/583))
- Implement project and hook selector ([#623](https://github.com/j178/prek/pull/623))
- Add `prek run --cd <dir>` to change directory before running ([#581](https://github.com/j178/prek/pull/581))
- Support `prek list` in workspace mode ([#586](https://github.com/j178/prek/pull/586))
- Support `prek install|install-hooks|hook-impl|init-template-dir` in workspace mode ([#595](https://github.com/j178/prek/pull/595))
- Implement `auto-update` in workspace mode ([#605](https://github.com/j178/prek/pull/605))
- Implement selector completion in workspace mode ([#639](https://github.com/j178/prek/pull/639))
- Simplify `auto-update` implementation ([#608](https://github.com/j178/prek/pull/608))
- Add a `--dry-run` flag to `prek run` ([#622](https://github.com/j178/prek/pull/622))
- Cache workspace discovery result ([#636](https://github.com/j178/prek/pull/636))
- Fix local script hook entry path in workspace mode ([#603](https://github.com/j178/prek/pull/603))
- Fix `hook-impl` allow missing config ([#600](https://github.com/j178/prek/pull/600))
- Fix docker mount in workspace mode ([#638](https://github.com/j178/prek/pull/638))
- Show project line when project is not root ([#637](https://github.com/j178/prek/pull/637))

### Documentation

- Publish docs to `https://prek.j178.dev` ([#627](https://github.com/j178/prek/pull/627))
- Improve workspace docs about skips rule ([#615](https://github.com/j178/prek/pull/615))
- Add an full example and update docs ([#582](https://github.com/j178/prek/pull/582))

### Other changes

- Docs: `.pre-commit-config.yml` support has been removed ([#630](https://github.com/j178/prek/pull/630))
- Enable publishing prereleases ([#641](https://github.com/j178/prek/pull/641))

### Contributors

- [@luizvbo](https://github.com/luizvbo)
- [@j178](https://github.com/j178)
- [@hugovk](https://github.com/hugovk)

## 0.1.6

### Enhancements

- Improve hook install concurrency ([#611](https://github.com/j178/prek/pull/611))
- Parse JSON from slice ([#604](https://github.com/j178/prek/pull/604))

### Bug fixes

- Reuse hook env only for exactly same dependencies ([#609](https://github.com/j178/prek/pull/609))
- Workaround checkout file failure on Windows ([#616](https://github.com/j178/prek/pull/616))

## 0.1.5

### Enhancements

- Implement `pre-push` hook type ([#598](https://github.com/j178/prek/pull/598))
- Implement `pre-commit-hooks:check_yaml` as builtin hook ([#557](https://github.com/j178/prek/pull/557))
- Implement `pre-commit-hooks:check-toml` as builtin hook ([#564](https://github.com/j178/prek/pull/564))
- Add validation for file type tags ([#565](https://github.com/j178/prek/pull/565))
- Ignore NotFound error in extracting metadata log ([#597](https://github.com/j178/prek/pull/597))

### Documentation

- Update project status ([#578](https://github.com/j178/prek/pull/578))

### Other changes

- Bump tracing-subscriber to 0.3.20 ([#567](https://github.com/j178/prek/pull/567))
- Remove color from trace log ([#580](https://github.com/j178/prek/pull/580))

## 0.1.4

### Enhancements

- Improve docker image labels ([#551](https://github.com/j178/prek/pull/551))

### Performance

- Avoid unnecessary allocation in `run_by_batch` ([#549](https://github.com/j178/prek/pull/549))
- Cache current docker container mounts ([#552](https://github.com/j178/prek/pull/552))

### Bug fixes

- Fix `trailing-whitespace` cannot handle file contains invalid utf-8 data ([#544](https://github.com/j178/prek/pull/544))
- Fix trailing-whitespace eol trimming ([#546](https://github.com/j178/prek/pull/546))
- Fix trailing-whitespace markdown eol trimming ([#547](https://github.com/j178/prek/pull/547))

### Documentation

- Add authlib to `Who are using prek` ([#550](https://github.com/j178/prek/pull/550))

## 0.1.3

### Enhancements

- Support PEP 723 scripts for Python hooks ([#529](https://github.com/j178/prek/pull/529))

### Bug fixes

- Fix Python hook stderr are not captured ([#530](https://github.com/j178/prek/pull/530))

### Other changes

- Add an error context when reading manifest failed ([#527](https://github.com/j178/prek/pull/527))
- Add a renovate rule to bump bundled uv version ([#528](https://github.com/j178/prek/pull/528))
- Disable semantic commits for renovate PRs ([#538](https://github.com/j178/prek/pull/538))

## 0.1.2

### Enhancements

- Add check for missing hooks in new revision ([#521](https://github.com/j178/prek/pull/521))

### Bug fixes

- Fix `language: script` entry join issue ([#525](https://github.com/j178/prek/pull/525))

### Other changes

- Add OpenLineage to prek users ([#523](https://github.com/j178/prek/pull/523))

## 0.1.1

### Breaking changes

- Drop support `.yml` config file ([#493](https://github.com/j178/prek/pull/493))

### Enhancements

- Add moving rev warning ([#488](https://github.com/j178/prek/pull/488))
- Implement `prek auto-update` ([#511](https://github.com/j178/prek/pull/511))
- Support local path as a `repo` url ([#513](https://github.com/j178/prek/pull/513))

### Bug fixes

- Fix recursion limit when checking deeply nested json ([#507](https://github.com/j178/prek/pull/507))
- Fix rename tempfile across device ([#508](https://github.com/j178/prek/pull/508))
- Fix build on s390x ([#518](https://github.com/j178/prek/pull/518))

### Other changes

- docs: install prek with mise ([#510](https://github.com/j178/prek/pull/510))

## 0.0.29

### Enhancements

- Build wheels for more platforms ([#489](https://github.com/j178/prek/pull/489))

### Bug fixes

- Fix `git commit -a` does not pick up staged files correctly ([#487](https://github.com/j178/prek/pull/487))

## 0.0.28

### Bug fixes

- Fix `inde.lock file exists` error when running `git commit -p` or `git commit -a` ([#482](https://github.com/j178/prek/pull/482))
- Various fixes to `init-templdate-dir` and directory related bug ([#484](https://github.com/j178/prek/pull/484))

## 0.0.27

### Enhancements

- Clone repo temporarily into scratch directory ([#478](https://github.com/j178/prek/pull/478))
- Don’t show the progress bar if there’s no need for cloning or installing hooks ([#477](https://github.com/j178/prek/pull/477))
- Support `language_version: lts` for node ([#473](https://github.com/j178/prek/pull/473))

### Bug fixes

- Adjust `sample-config` file path before writing ([#474](https://github.com/j178/prek/pull/474))
- Resolve script shebang before running ([#475](https://github.com/j178/prek/pull/475))

## 0.0.26

### Enhancements

- Disable `prek self update` for package managers ([#468](https://github.com/j178/prek/pull/468))
- Download uv from github releases directly ([#464](https://github.com/j178/prek/pull/464))
- Find `uv` alongside the `prek` binary ([#466](https://github.com/j178/prek/pull/466))
- Run hooks with pty if color enabled ([#471](https://github.com/j178/prek/pull/471))
- Warn unexpected keys in config ([#463](https://github.com/j178/prek/pull/463))

### Bug fixes

- Canonicalize prek executable path ([#467](https://github.com/j178/prek/pull/467))

### Documentation

- Add "Who are using prek" to README ([#458](https://github.com/j178/prek/pull/458))

## 0.0.25

### Enhancements

- Add check for `minimum_prek_version` ([#437](https://github.com/j178/prefligit/pull/437))
- Make `--to-ref` default to HEAD if `--from-ref` is specified ([#426](https://github.com/j178/prefligit/pull/426))
- Support downloading uv from pypi and mirrors ([#449](https://github.com/j178/prefligit/pull/449))
- Write trace log to `$PREK_HOME/prek.log` ([#447](https://github.com/j178/prefligit/pull/447))
- Implement `mixed_line_ending` as builtin hook ([#444](https://github.com/j178/prefligit/pull/444))
- Support `--output-format=json` in `prek list` ([#446](https://github.com/j178/prefligit/pull/446))
- Add context message to install error ([#455](https://github.com/j178/prefligit/pull/455))
- Add warning for non-existent hook id ([#450](https://github.com/j178/prefligit/pull/450))

### Performance

- Refactor `fix_trailing_whitespace` ([#411](https://github.com/j178/prefligit/pull/411))

### Bug fixes

- Calculate more accurate max cli length ([#442](https://github.com/j178/prefligit/pull/442))
- Fix uv install on Windows ([#453](https://github.com/j178/prefligit/pull/453))
- Static link `liblzma` ([#445](https://github.com/j178/prefligit/pull/445))

## 0.0.24

### Enhancements

- Add dynamic completion of hook ids ([#380](https://github.com/j178/prek/pull/380))
- Implement `prek list` to list available hooks ([#424](https://github.com/j178/prek/pull/424))
- Implement `pygrep` language support ([#383](https://github.com/j178/prek/pull/383))
- Support `prek run` multiple hooks ([#423](https://github.com/j178/prek/pull/423))
- Implement `check_json` as builtin hook ([#416](https://github.com/j178/prek/pull/416))

### Performance

- Avoid reading whole file into memory in `fix_end_of_file` and make it consistent with `pre-commit-hooks` ([#399](https://github.com/j178/prek/pull/399))

### Bug fixes

- Do not set `GOROOT` and `GOPATH` for system found go ([#415](https://github.com/j178/prek/pull/415))

### Documentation

- Use `brew install j178/tap/prek` for now ([#420](https://github.com/j178/prek/pull/420))
- chore: logo rebranded, Update README.md ([#408](https://github.com/j178/prek/pull/408))

## 0.0.23

### Breaking changes

In this release, we've renamed the project to `prek` from `prefligit`. It's shorter so easier to type, and it avoids typosquatting with `preflight`.

This means that the command-line name is now `prek`, and the PyPI package is now listed as [`prek`](https://pypi.org/project/prek/).
And the Homebrew will be updated to `prek` as well.

And previously, the cache directory was `~/.cache/prefligit`, now it is `~/.cache/prek`.
You'd have to delete the old cache directory manually, or run `prefligit clean` to clean it up.

Then uninstall the old `prefligit` and install the new `prek` from scratch.

### Enhancements

- Relax uv version check range ([#396](https://github.com/j178/prefligit/pull/396))

### Bug fixes

- Fix `script` command path ([#398](https://github.com/j178/prefligit/pull/398))
- Fix meta hook `check_useless_excludes` ([#401](https://github.com/j178/prefligit/pull/401))

### Other changes

- Rename to `prek` from `prefligit` ([#402](https://github.com/j178/prefligit/pull/402))

## 0.0.22

### Enhancements

- Add value hint to `prefligit run` flags ([#373](https://github.com/j178/prefligit/pull/373))
- Check minimum supported version for uv found from system ([#352](https://github.com/j178/prefligit/pull/352))

### Bug fixes

- Fix `check_added_large_files` parameter name ([#389](https://github.com/j178/prefligit/pull/389))
- Fix `npm install` on Windows ([#374](https://github.com/j178/prefligit/pull/374))
- Fix docker mount options ([#377](https://github.com/j178/prefligit/pull/377))
- Fix identify tags for `Pipfile.lock` ([#391](https://github.com/j178/prefligit/pull/391))
- Fix identifying symlinks ([#378](https://github.com/j178/prefligit/pull/378))
- Set `GOROOT` when installing golang hook ([#381](https://github.com/j178/prefligit/pull/381))

### Other changes

- Add devcontainer config ([#379](https://github.com/j178/prefligit/pull/379))
- Bump rust toolchain to 1.89 ([#386](https://github.com/j178/prefligit/pull/386))

## 0.0.21

### Enhancements

- Add `--directory` to `prefligit run` ([#358](https://github.com/j178/prefligit/pull/358))
- Implement `tags_from_interpreter` ([#362](https://github.com/j178/prefligit/pull/362))
- Set GOBIN to `<hook-env>/bin`, set GOPATH to `$PREGLIGIT_HOME/cache/go` ([#369](https://github.com/j178/prefligit/pull/369))

### Performance

- Make Partitions iterator produce slice instead of Vec ([#361](https://github.com/j178/prefligit/pull/361))
- Use `rustc_hash` ([#359](https://github.com/j178/prefligit/pull/359))

### Bug fixes

- Add `node` to PATH when running `npm` ([#371](https://github.com/j178/prefligit/pull/371))
- Fix bug that default hook stage should be pre-commit ([#367](https://github.com/j178/prefligit/pull/367))
- Fix cache dir permission before clean ([#368](https://github.com/j178/prefligit/pull/368))

### Other changes

- Move `Project` into `workspace` module ([#364](https://github.com/j178/prefligit/pull/364))

## 0.0.20

### Enhancements

- Support golang hooks and golang toolchain management ([#355](https://github.com/j178/prefligit/pull/355))
- Add `--last-commit` flag to `prefligit run` ([#351](https://github.com/j178/prefligit/pull/351))

### Bug fixes

- Fix bug that directories are ignored ([#350](https://github.com/j178/prefligit/pull/350))
- Use `git ls-remote` to fetch go releases ([#356](https://github.com/j178/prefligit/pull/356))

### Documentation

- Add migration section to README ([#354](https://github.com/j178/prefligit/pull/354))

## 0.0.19

### Enhancements

- Improve node support ([#346](https://github.com/j178/prefligit/pull/346))
- Manage uv cache dir ([#345](https://github.com/j178/prefligit/pull/345))

### Bug fixes

- Add `--install-links` to `npm install` ([#347](https://github.com/j178/prefligit/pull/347))
- Fix large file check to use staged_get instead of intent_add ([#332](https://github.com/j178/prefligit/pull/332))

## 0.0.18

### Enhancements

- Impl `FromStr` for language request ([#338](https://github.com/j178/prefligit/pull/338))

### Performance

- Use DFS to find connected components in hook dependencies ([#341](https://github.com/j178/prefligit/pull/341))
- Use more `Arc<T>` over `Box<T>` ([#333](https://github.com/j178/prefligit/pull/333))

### Bug fixes

- Fix node path match, add tests ([#339](https://github.com/j178/prefligit/pull/339))
- Skipped hook name should be taken into account for columns ([#335](https://github.com/j178/prefligit/pull/335))

### Documentation

- Add benchmarks ([#342](https://github.com/j178/prefligit/pull/342))
- Update docs ([#337](https://github.com/j178/prefligit/pull/337))

## 0.0.17

### Enhancements

- Add `sample-config --file` to write sample config to file ([#313](https://github.com/j178/prefligit/pull/313))
- Cache computed `dependencies` on hook ([#319](https://github.com/j178/prefligit/pull/319))
- Cache the found path to uv ([#323](https://github.com/j178/prefligit/pull/323))
- Improve `sample-config` writing file ([#314](https://github.com/j178/prefligit/pull/314))
- Reimplement find matching env logic ([#327](https://github.com/j178/prefligit/pull/327))

### Bug fixes

- Fix issue that `entry` of `pygrep` is not shell commands ([#316](https://github.com/j178/prefligit/pull/316))
- Support `python311` as a valid language version ([#321](https://github.com/j178/prefligit/pull/321))

### Other changes

- Bump cargo-dist to 0.29.0 ([#322](https://github.com/j178/prefligit/pull/322))
- Update DIFF.md ([#318](https://github.com/j178/prefligit/pull/318))

## 0.0.16

### Enhancements

- Improve error message for hook ([#308](https://github.com/j178/prefligit/pull/308))
- Improve error message for hook installation and run ([#310](https://github.com/j178/prefligit/pull/310))
- Improve hook invalid error message ([#307](https://github.com/j178/prefligit/pull/307))
- Parse `entry` when constructing hook ([#306](https://github.com/j178/prefligit/pull/306))
- Rename `autoupdate` to `auto-update`, `init-templatedir` to `init-template-dir` ([#302](https://github.com/j178/prefligit/pull/302))

### Bug fixes

- Fix `end-of-file-fixer` replaces `\r\n` with `\n` ([#311](https://github.com/j178/prefligit/pull/311))

## 0.0.15

In this release, `language: node` hooks are fully supported now (finally)!.
Give it a try and let us know if you run into any issues!

### Enhancements

- Support `nodejs` language hook ([#298](https://github.com/j178/prefligit/pull/298))
- Show unimplemented message earlier ([#296](https://github.com/j178/prefligit/pull/296))
- Simplify npm installing dependencies ([#299](https://github.com/j178/prefligit/pull/299))

### Documentation

- Update readme ([#300](https://github.com/j178/prefligit/pull/300))

## 0.0.14

### Enhancements

- Show unimplemented status instead of panic ([#290](https://github.com/j178/prefligit/pull/290))
- Try default uv managed python first, fallback to download ([#291](https://github.com/j178/prefligit/pull/291))

### Other changes

- Update Rust crate fancy-regex to 0.16.0 ([#286](https://github.com/j178/prefligit/pull/286))
- Update Rust crate indicatif to 0.18.0 ([#287](https://github.com/j178/prefligit/pull/287))
- Update Rust crate pprof to 0.15.0 ([#288](https://github.com/j178/prefligit/pull/288))
- Update Rust crate serde_json to v1.0.142 ([#285](https://github.com/j178/prefligit/pull/285))
- Update astral-sh/setup-uv action to v6 ([#289](https://github.com/j178/prefligit/pull/289))

## 0.0.13

### Enhancements

- Add `PREFLIGIT_NO_FAST_PATH` to disable Rust fast path ([#272](https://github.com/j178/prefligit/pull/272))
- Improve subprocess error message ([#276](https://github.com/j178/prefligit/pull/276))
- Remove `LanguagePreference` and improve language check ([#277](https://github.com/j178/prefligit/pull/277))
- Support downloading requested Python version automatically ([#281](https://github.com/j178/prefligit/pull/281))
- Implement language specific version parsing ([#273](https://github.com/j178/prefligit/pull/273))

### Bug fixes

- Fix python version matching ([#275](https://github.com/j178/prefligit/pull/275))
- Show progress bar in verbose mode ([#278](https://github.com/j178/prefligit/pull/278))

## 0.0.12

### Bug fixes

- Ignore `config not staged` error for config outside the repo ([#270](https://github.com/j178/prefligit/pull/270))

### Other changes

- Add test fixture files ([#266](https://github.com/j178/prefligit/pull/266))
- Use `sync_all` over `flush` ([#269](https://github.com/j178/prefligit/pull/269))

## 0.0.11

### Enhancements

- Support reading `.pre-commit-config.yml` as well ([#213](https://github.com/j178/prefligit/pull/213))
- Refactor language version resolution and hook install dir ([#221](https://github.com/j178/prefligit/pull/221))
- Implement `prefligit install-hooks` command ([#258](https://github.com/j178/prefligit/pull/258))
- Implement `pre-commit-hooks:end-of-file-fixer` hook ([#255](https://github.com/j178/prefligit/pull/255))
- Implement `pre-commit-hooks:check_added_large_files` hook ([#219](https://github.com/j178/prefligit/pull/219))
- Implement `script` language hooks ([#252](https://github.com/j178/prefligit/pull/252))
- Implement node.js installer ([#152](https://github.com/j178/prefligit/pull/152))
- Use `-v` to show only verbose message, `-vv` show debug log, `-vvv` show trace log ([#211](https://github.com/j178/prefligit/pull/211))
- Write `.prefligit-repo.json` inside cloned repo ([#225](https://github.com/j178/prefligit/pull/225))
- Add language name to 'not yet implemented' messages ([#251](https://github.com/j178/prefligit/pull/251))

### Bug fixes

- Do not install if no additional dependencies for local python hook ([#195](https://github.com/j178/prefligit/pull/195))
- Ensure flushing log file ([#261](https://github.com/j178/prefligit/pull/261))
- Fix zip deflate ([#194](https://github.com/j178/prefligit/pull/194))

### Other changes

- Bump to Rust 1.88 and `cargo update` ([#254](https://github.com/j178/prefligit/pull/254))
- Upgrade to Rust 2024 edition ([#196](https://github.com/j178/prefligit/pull/196))
- Bump uv version ([#260](https://github.com/j178/prefligit/pull/260))
- Simplify archive extraction implementation ([#193](https://github.com/j178/prefligit/pull/193))
- Use `astral-sh/rs-async-zip` ([#259](https://github.com/j178/prefligit/pull/259))
- Use `ubuntu-latest` for release action ([#216](https://github.com/j178/prefligit/pull/216))
- Use async closure ([#200](https://github.com/j178/prefligit/pull/200))

## 0.0.10

### Breaking changes

**Warning**: This release changed the store layout, it's recommended to delete the old store and install from scratch.

To delete the old store, run:

```sh
rm -rf ~/.cache/prefligit
```

### Enhancements

- Restructure store folders layout ([#181](https://github.com/j178/prefligit/pull/181))
- Fallback some env vars to to pre-commit ([#175](https://github.com/j178/prefligit/pull/175))
- Save patches to `$PREFLIGIT_HOME/patches` ([#182](https://github.com/j178/prefligit/pull/182))

### Bug fixes

- Fix removing git env vars ([#176](https://github.com/j178/prefligit/pull/176))
- Fix typo in Cargo.toml ([#160](https://github.com/j178/prefligit/pull/160))

### Other changes

- Do not publish to crates.io ([#191](https://github.com/j178/prefligit/pull/191))
- Bump cargo-dist to v0.28.0 ([#170](https://github.com/j178/prefligit/pull/170))
- Bump uv version to 0.6.0 ([#184](https://github.com/j178/prefligit/pull/184))
- Configure Renovate ([#168](https://github.com/j178/prefligit/pull/168))
- Format sample config output ([#172](https://github.com/j178/prefligit/pull/172))
- Make env vars a shareable crate ([#171](https://github.com/j178/prefligit/pull/171))
- Reduce String alloc ([#166](https://github.com/j178/prefligit/pull/166))
- Skip common git flags in command trace log ([#162](https://github.com/j178/prefligit/pull/162))
- Update Rust crate clap to v4.5.29 ([#173](https://github.com/j178/prefligit/pull/173))
- Update Rust crate which to v7.0.2 ([#163](https://github.com/j178/prefligit/pull/163))
- Update astral-sh/setup-uv action to v5 ([#164](https://github.com/j178/prefligit/pull/164))
- Upgrade Rust to 1.84 and upgrade dependencies ([#161](https://github.com/j178/prefligit/pull/161))

## 0.0.9

Due to a mistake in the release process, this release is skipped.

## 0.0.8

### Enhancements

- Move home dir to `~/.cache/prefligit` ([#154](https://github.com/j178/prefligit/pull/154))
- Implement trailing-whitespace in Rust ([#137](https://github.com/j178/prefligit/pull/137))
- Limit hook install concurrency ([#145](https://github.com/j178/prefligit/pull/145))
- Simplify language default version implementation ([#150](https://github.com/j178/prefligit/pull/150))
- Support install uv from pypi ([#149](https://github.com/j178/prefligit/pull/149))
- Add executing command to error message ([#141](https://github.com/j178/prefligit/pull/141))

### Bug fixes

- Use hook `args` in fast path ([#139](https://github.com/j178/prefligit/pull/139))

### Other changes

- Remove hook install_key ([#153](https://github.com/j178/prefligit/pull/153))
- Remove pyvenv.cfg patch ([#156](https://github.com/j178/prefligit/pull/156))
- Try to use D drive on Windows CI ([#157](https://github.com/j178/prefligit/pull/157))
- Tweak trailing-whitespace-fixer ([#140](https://github.com/j178/prefligit/pull/140))
- Upgrade dist to v0.27.0 ([#158](https://github.com/j178/prefligit/pull/158))
- Uv install python into tools path ([#151](https://github.com/j178/prefligit/pull/151))

## 0.0.7

### Enhancements

- Add progress bar for hook init and install ([#122](https://github.com/j178/prefligit/pull/122))
- Add color to command help ([#131](https://github.com/j178/prefligit/pull/131))
- Add commit info to version display ([#130](https://github.com/j178/prefligit/pull/130))
- Support meta hooks reading ([#134](https://github.com/j178/prefligit/pull/134))
- Implement meta hooks ([#135](https://github.com/j178/prefligit/pull/135))

### Bug fixes

- Fix same repo clone multiple times ([#125](https://github.com/j178/prefligit/pull/125))
- Fix logging level after renaming ([#119](https://github.com/j178/prefligit/pull/119))
- Fix version tag distance ([#132](https://github.com/j178/prefligit/pull/132))

### Other changes

- Disable uv cache on Windows ([#127](https://github.com/j178/prefligit/pull/127))
- Impl Eq and Hash for ConfigRemoteRepo ([#126](https://github.com/j178/prefligit/pull/126))
- Make `pass_env_vars` runs on Windows ([#133](https://github.com/j178/prefligit/pull/133))
- Run cargo update ([#129](https://github.com/j178/prefligit/pull/129))
- Update Readme ([#128](https://github.com/j178/prefligit/pull/128))

## 0.0.6

### Breaking changes

In this release, we’ve renamed the project to `prefligit` (a deliberate misspelling of preflight) to prevent confusion with the existing pre-commit tool. For further information, refer to issue #73.

- The command-line name is now `prefligit`. We suggest uninstalling any previous version of `pre-commit-rs` and installing `prefligit` from scratch.
- The PyPI package is now listed as [`prefligit`](https://pypi.org/project/prefligit/).
- The Cargo package is also now [`prefligit`](https://crates.io/crates/prefligit).
- The Homebrew formula has been updated to `prefligit`.

### Enhancements

- Support `docker_image` language ([#113](https://github.com/j178/pre-commit-rs/pull/113))
- Support `init-templatedir` subcommand ([#101](https://github.com/j178/pre-commit-rs/pull/101))
- Implement get filenames from merge conflicts ([#103](https://github.com/j178/pre-commit-rs/pull/103))

### Bug fixes

- Fix `prefligit install --hook-type` name ([#102](https://github.com/j178/pre-commit-rs/pull/102))

### Other changes

- Apply color option to log ([#100](https://github.com/j178/pre-commit-rs/pull/100))
- Improve tests ([#106](https://github.com/j178/pre-commit-rs/pull/106))
- Remove intermedia Language enum ([#107](https://github.com/j178/pre-commit-rs/pull/107))
- Run `cargo clippy` in the dev drive workspace ([#115](https://github.com/j178/pre-commit-rs/pull/115))

## 0.0.5

### Enhancements

v0.0.4 release process was broken, so this release is a actually a re-release of v0.0.4.

- Improve subprocess trace and error output ([#92](https://github.com/j178/pre-commit-rs/pull/92))
- Stash working tree before running hooks ([#96](https://github.com/j178/pre-commit-rs/pull/96))
- Add color to command trace ([#94](https://github.com/j178/pre-commit-rs/pull/94))
- Improve hook output display ([#79](https://github.com/j178/pre-commit-rs/pull/79))
- Improve uv installation ([#78](https://github.com/j178/pre-commit-rs/pull/78))
- Support docker language ([#67](https://github.com/j178/pre-commit-rs/pull/67))

## 0.0.4

### Enhancements

- Improve subprocess trace and error output ([#92](https://github.com/j178/pre-commit-rs/pull/92))
- Stash working tree before running hooks ([#96](https://github.com/j178/pre-commit-rs/pull/96))
- Add color to command trace ([#94](https://github.com/j178/pre-commit-rs/pull/94))
- Improve hook output display ([#79](https://github.com/j178/pre-commit-rs/pull/79))
- Improve uv installation ([#78](https://github.com/j178/pre-commit-rs/pull/78))
- Support docker language ([#67](https://github.com/j178/pre-commit-rs/pull/67))

## 0.0.3

### Bug fixes

- Check uv installed after acquired lock ([#72](https://github.com/j178/pre-commit-rs/pull/72))

### Other changes

- Add copyright of the original pre-commit to LICENSE ([#74](https://github.com/j178/pre-commit-rs/pull/74))
- Add profiler ([#71](https://github.com/j178/pre-commit-rs/pull/71))
- Publish to PyPI ([#70](https://github.com/j178/pre-commit-rs/pull/70))
- Publish to crates.io ([#75](https://github.com/j178/pre-commit-rs/pull/75))
- Rename pypi package to `pre-commit-rusty` ([#76](https://github.com/j178/pre-commit-rs/pull/76))

## 0.0.2

### Enhancements

- Add `pre-commit self update` ([#68](https://github.com/j178/pre-commit-rs/pull/68))
- Auto install uv ([#66](https://github.com/j178/pre-commit-rs/pull/66))
- Generate shell completion ([#20](https://github.com/j178/pre-commit-rs/pull/20))
- Implement `pre-commit clean` ([#24](https://github.com/j178/pre-commit-rs/pull/24))
- Implement `pre-commit install` ([#28](https://github.com/j178/pre-commit-rs/pull/28))
- Implement `pre-commit sample-config` ([#37](https://github.com/j178/pre-commit-rs/pull/37))
- Implement `pre-commit uninstall` ([#36](https://github.com/j178/pre-commit-rs/pull/36))
- Implement `pre-commit validate-config` ([#25](https://github.com/j178/pre-commit-rs/pull/25))
- Implement `pre-commit validate-manifest` ([#26](https://github.com/j178/pre-commit-rs/pull/26))
- Implement basic `pre-commit hook-impl` ([#63](https://github.com/j178/pre-commit-rs/pull/63))
- Partition filenames and delegate to multiple subprocesses ([#7](https://github.com/j178/pre-commit-rs/pull/7))
- Refactor xargs ([#8](https://github.com/j178/pre-commit-rs/pull/8))
- Skip empty config argument ([#64](https://github.com/j178/pre-commit-rs/pull/64))
- Use `fancy-regex` ([#62](https://github.com/j178/pre-commit-rs/pull/62))
- feat: add fail language support ([#60](https://github.com/j178/pre-commit-rs/pull/60))

### Bug Fixes

- Fix stage operate_on_files ([#65](https://github.com/j178/pre-commit-rs/pull/65))


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to prek

Thanks for your interest in improving **prek**! This guide walks through the development environment, our snapshot-based testing workflow, and the helper tasks defined in `mise.toml` to keep everything smooth.

## 1. Set up the Rust development environment

1. **Install Rust with `rustup`** (recommended)

    Install `rustup` from <https://rustup.rs> if you do not already have it. Then install the toolchain pinned in `rust-toolchain.toml` (currently Rust 1.90):

    ```bash
    rustup show
    ```

    Finally, add the common developer components:

    ```bash
    rustup component add rustfmt clippy
    ```

2. **Install project helper tools**

    Install [`mise`](https://mise.jdx.dev/) to manage project-specific tools and tasks, then run `mise install` in the repository root to download the tool versions declared in `mise.toml` (for example `cargo-insta`, `cargo-nextest`, and the language toolchains used in integration tests).

3. (Optional) **Bootstrap git hooks**

    ```bash
    prek install
    ```

    This installs a `pre-push` git hook that keeps formatting and linting checks aligned with CI before you push changes.

## 2. Writing tests with `insta` snapshot assertions

prek uses [insta](https://insta.rs/) for snapshot testing. It's recommended (but not necessary) to use `cargo-insta` for a better snapshot review experience.

If you are contributing new functionality, please include coverage via unit tests (in `src/…` using `#[cfg(test)]`) or integration tests (under `tests/`).

In integration tests, you can use `cmd_snapshot!` macro to simplify creating snapshots for prek commands. For example:

```rust
#[test]
fn test_run() {
    let context = TestContext::new();
    context.init_project();

    cmd_snapshot!(context.filters(), context.run(), @"");
}
```

## 3. Running tests and updating snapshots

You can invoke the test suite directly with Cargo or use the convenience tasks defined in `mise.toml`.

### Direct Cargo commands

- To run and review a specific snapshot test:

    ```bash
    cargo test --package <package> --test <test> -- <test_name> -- --exact
    cargo insta review
    ```

Where `<package>` is the crate name (for example, `prek`), `<test>` is the integration test file name (for example, `builtin_hooks`), and `<test_name>` is the specific test function name.

- Run snapshot-aware tests with the review UI:

    ```bash
    cargo insta test --review [test arguments]
    ```

    This command runs the selected tests, shows snapshot diffs, and lets you approve or reject updates interactively.

### Using mise tasks

`mise run <task>` picks up the arguments and environment declared in `mise.toml`. Helpful tasks include:

- `mise run test-unit -- <filter>` – run binary/unit tests matching `<filter>` with `cargo insta test --review --bin prek`.
- `mise run test-all-unit` – run all unit tests with snapshot review enabled.
- `mise run test-integration <test> [filter]` – run one integration test (for example `mise run test-integration builtin_hooks detect_private_key_hook`).
- `mise run test-all-integration` – execute the full integration test suite with review prompts.
- `mise run test` – run `cargo test` across the workspace without the snapshot review flow.
- `mise run lint` – run `cargo fmt` and `cargo clippy` (useful before opening a pull request).

## 4. Before you open a pull request

- Ensure `mise run lint` passes without errors.
- Include documentation updates if your change alters the user-facing behavior.
- Keep commits focused and write descriptive messages—this helps reviewers follow along.

Thanks again for contributing!


================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["crates/*"]
resolver = "3"

[workspace.package]
version = "0.3.6"
edition = "2024"
rust-version = "1.92.0"
repository = "https://github.com/j178/prek"
homepage = "https://prek.j178.dev/"
license = "MIT"

[workspace.dependencies]
prek-consts = { path = "crates/prek-consts", version = "0.3.6" }
prek-identify = { path = "crates/prek-identify", version = "0.3.6" }
prek-pty = { path = "crates/prek-pty", version = "0.3.6" }

aho-corasick = { version = "1.1.4" }
anstream = { version = "1.0.0" }
anstyle-query = { version = "1.1.5" }
anyhow = { version = "1.0.86" }
async-compression = { version = "0.4.18", features = ["gzip", "xz", "tokio"] }
async_zip = { version = "0.0.17", package = "astral_async_zip", features = [
  "deflate",
  "tokio",
] }
axoupdater = { version = "0.10.0", default-features = false, features = [
  "github_releases",
] }
bstr = { version = "1.11.0" }
cargo_metadata = { version = "0.23.1" }
clap = { version = "4.6.0", features = [
  "derive",
  "env",
  "string",
  "wrap_help",
] }
clap_complete = { version = "4.6.0", features = ["unstable-dynamic"] }
ctrlc = { version = "3.4.5" }
dunce = { version = "1.0.5" }
etcetera = { version = "0.11.0" }
fancy-regex = { version = "0.17.0" }
fs-err = { version = "3.3.0", features = ["tokio"] }
futures = { version = "0.3.31" }
hex = { version = "0.4.3" }
http = { version = "1.1.0" }
ignore = { version = "0.4.23" }
indicatif = { version = "0.18.0" }
indoc = { version = "2.0.5" }
itertools = { version = "0.14.0" }
json5 = { version = "1.3.0" }
lazy-regex = { version = "3.4.2" }
levenshtein = { version = "1.0.5" }
libc = { version = "0.2.182" }
# Enable static linking for liblzma
# This is required for the `xz` feature in `async-compression`
liblzma = { version = "0.4.5", features = ["static"] }
mea = { version = "0.6.3" }
memchr = { version = "2.7.5" }
owo-colors = { version = "4.1.0" }
path-clean = { version = "1.0.1" }
phf = { version = "0.13.1", default-features = false, features = ["macros"] }
pprof = { version = "0.15.0" }
quick-xml = { version = "0.39" }
rand = { version = "0.10.0" }
rayon = { version = "1.10.0" }
reqwest = { version = "0.13.2", default-features = false, features = [
  "http2",
  "stream",
  "json",
  "rustls",
  "system-proxy",
  "socks",
] }
rustc-hash = { version = "2.1.1" }
rustix = { version = "1.0.8", features = ["pty", "process", "fs", "termios"] }
same-file = { version = "1.0.6" }
semver = { version = "1.0.24", features = ["serde"] }
serde = { version = "1.0.210", features = ["derive"] }
serde_json = { version = "1.0.132", features = [
  "preserve_order",
  "unbounded_depth",
] }
serde_stacker = { version = "0.1.12" }
serde-saphyr = { version = "0.0.21", default-features = false }
shlex = { version = "1.3.0" }
globset = { version = "0.4.18" }
strum = { version = "0.28.0", features = ["derive"] }
target-lexicon = { version = "0.13.0" }
tempfile = { version = "3.25.0" }
thiserror = { version = "2.0.11" }
tokio = { version = "1.47.1", features = [
  "fs",
  "io-std",
  "process",
  "rt",
  "sync",
  "macros",
  "net",
] }
tokio-tar = { version = "0.6.0", package = "astral-tokio-tar" }
tokio-util = { version = "0.7.13" }
toml = { version = "1.0.1", default-features = false, features = [
  "fast_hash",
  "parse",
  "preserve_order",
  "serde",
] }
toml_edit = { version = "0.25.1" }
tracing = { version = "0.1.40" }
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
unicode-width = { version = "0.2.0", default-features = false }
walkdir = { version = "2.5.0" }
webpki-root-certs = { version = "1.0.6" }
which = { version = "8.0.0" }

# dev-dependencies
assert_cmd = { version = "2.2.0" }
assert_fs = { version = "1.1.2" }
insta = { version = "1.40.0", features = ["filters"] }
insta-cmd = { version = "0.6.0" }
markdown = { version = "1.0.0" }
predicates = { version = "3.1.2" }
pretty_assertions = { version = "1.4.1" }
regex = { version = "1.11.0" }
schemars = { version = "1.1.0" }
textwrap = { version = "0.16.0" }

[workspace.lints.rust]
dead_code = "allow"

[workspace.lints.clippy]
pedantic = { level = "warn", priority = -2 }
# Allowed pedantic lints
collapsible_else_if = "allow"
collapsible_if = "allow"
if_not_else = "allow"
implicit_hasher = "allow"
map_unwrap_or = "allow"
match_same_arms = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
module_name_repetitions = "allow"
must_use_candidate = "allow"
similar_names = "allow"
too_many_arguments = "allow"
too_many_lines = "allow"
used_underscore_binding = "allow"
items_after_statements = "allow"
iter-without-into-iter = "allow"
# Disallowed restriction lints
print_stdout = "warn"
print_stderr = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_structs_with_brackets = "warn"
exit = "warn"
get_unwrap = "warn"
rc_buffer = "warn"
rc_mutex = "warn"
rest_pat_in_fully_bound_structs = "warn"

[workspace.metadata.typos.default]
extend-ignore-re = [
  '(?s)-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----',
]

[workspace.metadata.typos.default.extend-words]
edn = "edn"
styl = "styl"
jod = "jod"

[workspace.metadata.typos.files]
extend-exclude = ["scripts/macports"]

[workspace.metadata.cargo-shear]
ignored = ["liblzma"]

[profile.dev.package]
# Insta suggests compiling these packages in opt mode for faster testing.
# See https://docs.rs/insta/latest/insta/#optional-faster-runs.
insta.opt-level = 3
similar.opt-level = 3

# Profile for fast test execution: Skip debug info generation, and
# apply basic optimization, which speed up build and running tests.
[profile.fast-build]
inherits = "dev"
debug = 0
strip = "debuginfo"

# Profile for faster builds: Skip debug info generation, for faster
# builds of smaller binaries.
[profile.no-debug]
inherits = "dev"
debug = 0
strip = "debuginfo"

[profile.profiling]
inherits = "release"
strip = false
debug = "full"
lto = false
codegen-units = 16

[profile.minimal-size]
inherits = "release"
# Enable Full LTO for the best optimizations
lto = "fat"
# Reduce codegen units to 1 for better optimizations
codegen-units = 1
strip = true
panic = "abort"

# The profile that 'cargo dist' will build with
[profile.dist]
inherits = "minimal-size"


================================================
FILE: Dockerfile
================================================
FROM --platform=$BUILDPLATFORM ubuntu AS build
ENV HOME="/root"
WORKDIR $HOME

RUN apt update \
  && apt install -y --no-install-recommends \
  build-essential \
  curl \
  python3-venv \
  && apt clean \
  && rm -rf /var/lib/apt/lists/*

# Setup zig as cross compiling linker
RUN python3 -m venv $HOME/.venv
RUN .venv/bin/pip install cargo-zigbuild
ENV PATH="$HOME/.venv/bin:$PATH"

# Install rust
ARG TARGETPLATFORM
RUN case "$TARGETPLATFORM" in \
  "linux/arm64") echo "aarch64-unknown-linux-musl" > rust_target.txt ;; \
  "linux/amd64") echo "x86_64-unknown-linux-musl" > rust_target.txt ;; \
  *) exit 1 ;; \
  esac

# Update rustup whenever we bump the rust version
COPY rust-toolchain.toml rust-toolchain.toml
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --target $(cat rust_target.txt) --profile minimal --default-toolchain none
ENV PATH="$HOME/.cargo/bin:$PATH"
# Install the toolchain then the musl target
RUN rustup toolchain install
RUN rustup target add $(cat rust_target.txt)

# Build
COPY ./Cargo.toml Cargo.toml
COPY ./Cargo.lock Cargo.lock
COPY crates crates
RUN case "${TARGETPLATFORM}" in \
  "linux/arm64") export JEMALLOC_SYS_WITH_LG_PAGE=16;; \
  esac && \
  cargo zigbuild --bin prek --profile dist --target $(cat rust_target.txt)
RUN cp target/$(cat rust_target.txt)/dist/prek /prek
# TODO: Optimize binary size, with a version that also works when cross compiling
# RUN strip --strip-all /prek

FROM scratch
COPY --from=build /prek /
WORKDIR /io
ENTRYPOINT ["/prek"]


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2024 j178

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<div align="center">

<img width="180" alt="prek" src="https://raw.githubusercontent.com/j178/prek/master/docs/assets/logo.webp" />
<h1>prek</h1>

[![prek](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json)](https://github.com/j178/prek)
[![PyPI version](https://img.shields.io/pypi/v/prek.svg)](https://pypi.python.org/pypi/prek)
[![codecov](https://codecov.io/github/j178/prek/graph/badge.svg?token=MP6TY24F43)](https://codecov.io/github/j178/prek)
[![PyPI Downloads](https://img.shields.io/pypi/dm/prek?logo=python)](https://pepy.tech/projects/prek)
[![Discord](https://img.shields.io/discord/1403581202102878289?logo=discord)](https://discord.gg/3NRJUqJz86)

</div>

<!-- --8<-- [start: description] -->

[pre-commit](https://pre-commit.com/) is a framework to run hooks written in many languages, and it manages the
language toolchain and dependencies for running the hooks.

*prek* is a reimagined version of pre-commit, built in Rust.
It is designed to be a faster, dependency-free and drop-in alternative for it,
while also providing some additional long-requested features.

<!-- --8<-- [end: description] -->

> [!NOTE]
> Although prek is pretty new, it’s already powering real‑world projects like [CPython](https://github.com/python/cpython), [Apache Airflow](https://github.com/apache/airflow), [FastAPI](https://github.com/fastapi/fastapi), and more projects are picking it up—see [Who is using prek?](#who-is-using-prek). If you’re looking for an alternative to `pre-commit`, please give it a try—we’d love your feedback!
>
> Please note that some languages are not yet supported for full drop‑in parity with `pre-commit`. See [Language Support](https://prek.j178.dev/languages/) for current status.

<!-- --8<-- [start:features] -->

## Features

- A single binary with no dependencies, does not require Python or any other runtime.
- [Faster](https://prek.j178.dev/benchmark/) than `pre-commit` and more efficient in disk space usage.
- Fully compatible with the original pre-commit configurations and hooks.
- Built-in support for monorepos (i.e. [workspace mode](https://prek.j178.dev/workspace/)).
- Integration with [`uv`](https://github.com/astral-sh/uv) for managing Python virtual environments and dependencies.
- Improved toolchain installations for Python, Node.js, Bun, Go, Rust and Ruby, shared between hooks.
- [Built-in](https://prek.j178.dev/builtin/) Rust-native implementation of some common hooks.

<!-- --8<-- [end:features] -->

## Table of contents

- [Installation](#installation)
- [Quick start](#quick-start)
- [Why prek?](#why-prek)
- [Who is using prek?](#who-is-using-prek)
- [Acknowledgements](#acknowledgements)

## Installation

<details>
<summary>Standalone installer</summary>

prek provides a standalone installer script to download and install the tool,

On Linux and macOS:

<!-- --8<-- [start: linux-standalone-install] -->

```bash
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/j178/prek/releases/download/v0.3.6/prek-installer.sh | sh
```

<!-- --8<-- [end: linux-standalone-install] -->

On Windows:

<!-- --8<-- [start: windows-standalone-install] -->

```powershell
powershell -ExecutionPolicy ByPass -c "irm https://github.com/j178/prek/releases/download/v0.3.6/prek-installer.ps1 | iex"
```

<!-- --8<-- [end: windows-standalone-install] -->

</details>

<details>
<summary>PyPI</summary>

<!-- --8<-- [start: pypi-install] -->

prek is published as Python binary wheel to PyPI, you can install it using `pip`, `uv` (recommended), or `pipx`:

```bash
# Using uv (recommended)
uv tool install prek

# Using uvx (install and run in one command)
uvx prek

# Adding prek to the project dev-dependencies
uv add --dev prek

# Using pip
pip install prek

# Using pipx
pipx install prek
```

<!-- --8<-- [end: pypi-install] -->

</details>

<details>
<summary>Homebrew</summary>

<!-- --8<-- [start: homebrew-install] -->

```bash
brew install prek
```

<!-- --8<-- [end: homebrew-install] -->

</details>

<details>
<summary>mise</summary>

<!-- --8<-- [start: mise-install] -->

To use prek with [mise](https://mise.jdx.dev) ([v2025.8.11](https://github.com/jdx/mise/releases/tag/v2025.8.11) or later):

```bash
mise use prek
```

<!-- --8<-- [end: mise-install] -->

</details>

<details>
<summary>Cargo binstall</summary>

<!-- --8<-- [start: cargo-binstall] -->

Install pre-compiled binaries from GitHub using [cargo-binstall](https://github.com/cargo-bins/cargo-binstall):

```bash
cargo binstall prek
```

<!-- --8<-- [end: cargo-binstall] -->

</details>

<details>
<summary>Cargo</summary>

<!-- --8<-- [start: cargo-install] -->

Build from source using Cargo (Rust 1.89+ is required):

```bash
cargo install --locked prek
```

<!-- --8<-- [end: cargo-install] -->

</details>

<details>
<summary>npmjs</summary>

<!-- --8<-- [start: npmjs-install] -->

prek is published as a [Node.js package](https://www.npmjs.com/package/@j178/prek)
and can be installed with any npm-compatible package manager:

```bash
# As a dev dependency
npm add -D @j178/prek
pnpm add -D @j178/prek
bun add -D @j178/prek

# Or install globally
npm install -g @j178/prek
pnpm add -g @j178/prek
bun install -g @j178/prek

# Or run directly without installing
npx @j178/prek --version
bunx @j178/prek --version
```

<!-- --8<-- [end: npmjs-install] -->

</details>

<details>
<summary>Nix</summary>

<!-- --8<-- [start: nix-install] -->

prek is available via [Nixpkgs](https://search.nixos.org/packages?channel=unstable&show=prek&query=prek).

```shell
# Choose what's appropriate for your use case.
# One-off in a shell:
nix-shell -p prek

# NixOS or non-NixOS without flakes:
nix-env -iA nixos.prek

# Non-NixOS with flakes:
nix profile install nixpkgs#prek
```

<!-- --8<-- [end: nix-install] -->

</details>

<details>
<summary>Conda</summary>

<!-- --8<-- [start: conda-forge-install] -->

prek is available as `prek` via [conda-forge](https://anaconda.org/conda-forge/prek).

```shell
conda install conda-forge::prek
```

<!-- --8<-- [end: conda-forge-install] -->

</details>

<details>
<summary>Scoop (Windows)</summary>

<!-- --8<-- [start: scoop-install] -->

prek is available via [Scoop](https://scoop.sh/#/apps?q=prek).

```powershell
scoop install main/prek
```

<!-- --8<-- [end: scoop-install] -->

</details>

<details>
<summary>Winget (Windows)</summary>

<!-- --8<-- [start: winget-install] -->

prek is available via [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/).

```powershell
winget install --id j178.Prek
```

<!-- --8<-- [end: winget-install] -->

</details>

<details>
<summary>MacPorts</summary>

<!-- --8<-- [start: macports-install] -->

prek is available via [MacPorts](https://ports.macports.org/port/prek/).

```bash
sudo port install prek
```

<!-- --8<-- [end: macports-install] -->

</details>

<details>
<summary>GitHub Releases</summary>

<!-- --8<-- [start: pre-built-binaries] -->

Pre-built binaries are available for download from the [GitHub releases](https://github.com/j178/prek/releases) page.

<!-- --8<-- [end: pre-built-binaries] -->

</details>

<details>
<summary>GitHub Actions</summary>

<!-- --8<-- [start: github-actions] -->

prek can be used in GitHub Actions via the [j178/prek-action](https://github.com/j178/prek-action) repository.

Example workflow:

```yaml
name: Prek checks
on: [push, pull_request]

jobs:
  prek:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: j178/prek-action@v2
```

This action installs prek and runs `prek run --all-files` on your repository.

prek is also available via [`taiki-e/install-action`](https://github.com/taiki-e/install-action) for installing various tools.

<!-- --8<-- [end: github-actions] -->

</details>

<!-- --8<-- [start: self-update] -->

If installed via the standalone installer, prek can update itself to the latest version:

```bash
prek self update
```

<!-- --8<-- [end: self-update] -->

## Quick start

- **I already use pre-commit:** follow the short migration checklist in the [quickstart guide](https://prek.j178.dev/quickstart/#already-using-pre-commit) to swap in `prek` safely.
- **I'm new to pre-commit-style tools:** learn the basics—creating a config, running hooks, and installing Git shims—in the [beginner quickstart walkthrough](https://prek.j178.dev/quickstart/#new-to-pre-commit-style-workflows).

<!-- --8<-- [start: why] -->

## Why prek?

### prek is faster

- It is [multiple times faster](https://prek.j178.dev/benchmark/) than `pre-commit` and takes up half the disk space.
- It redesigned how hook environments and toolchains are managed, they are all shared between hooks, which reduces the disk space usage and speeds up the installation process.
- Repositories are cloned in parallel, and hooks are installed in parallel if their dependencies are disjoint.
- Hooks can run in parallel by priority (hooks with the same [`priority`](https://prek.j178.dev/configuration/#priority) may run concurrently), reducing end-to-end runtime.
- It uses [`uv`](https://github.com/astral-sh/uv) for creating Python virtualenvs and installing dependencies, which is known for its speed and efficiency.
- It implements some common hooks in Rust, [built in prek](https://prek.j178.dev/builtin/), which are faster than their Python counterparts.
- It suppo
Download .txt
gitextract_9_ydfirn/

├── .config/
│   ├── nextest.toml
│   └── taplo.toml
├── .devcontainer/
│   └── devcontainer.json
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.yaml
│   ├── codecov.yml
│   ├── copilot-instructions.md
│   ├── renovate.json5
│   ├── workflows/
│   │   ├── build-binaries.yml
│   │   ├── build-docker.yml
│   │   ├── ci.yml
│   │   ├── performance.yml
│   │   ├── publish-crates.yml
│   │   ├── publish-docs.yml
│   │   ├── publish-homebrew.yml
│   │   ├── publish-npm.yml
│   │   ├── publish-prek-action.yml
│   │   ├── publish-pypi.yml
│   │   ├── publish-winget.yml
│   │   ├── release.yml
│   │   ├── setup-dev-drive.ps1
│   │   ├── sync-identify.yml
│   │   └── zizmor.yml
│   └── zizmor.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.md
├── clippy.toml
├── crates/
│   ├── prek/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── archive.rs
│   │   │   ├── cleanup.rs
│   │   │   ├── cli/
│   │   │   │   ├── auto_update.rs
│   │   │   │   ├── cache_clean.rs
│   │   │   │   ├── cache_gc.rs
│   │   │   │   ├── cache_size.rs
│   │   │   │   ├── completion.rs
│   │   │   │   ├── hook_impl.rs
│   │   │   │   ├── identify.rs
│   │   │   │   ├── install.rs
│   │   │   │   ├── list.rs
│   │   │   │   ├── list_builtins.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── reporter.rs
│   │   │   │   ├── run/
│   │   │   │   │   ├── filter.rs
│   │   │   │   │   ├── keeper.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── run.rs
│   │   │   │   │   └── selector.rs
│   │   │   │   ├── sample_config.rs
│   │   │   │   ├── self_update.rs
│   │   │   │   ├── try_repo.rs
│   │   │   │   ├── validate.rs
│   │   │   │   └── yaml_to_toml.rs
│   │   │   ├── config.rs
│   │   │   ├── fs.rs
│   │   │   ├── git.rs
│   │   │   ├── hook.rs
│   │   │   ├── hooks/
│   │   │   │   ├── builtin_hooks/
│   │   │   │   │   ├── check_json5.rs
│   │   │   │   │   └── mod.rs
│   │   │   │   ├── meta_hooks.rs
│   │   │   │   ├── mod.rs
│   │   │   │   └── pre_commit_hooks/
│   │   │   │       ├── check_added_large_files.rs
│   │   │   │       ├── check_case_conflict.rs
│   │   │   │       ├── check_executables_have_shebangs.rs
│   │   │   │       ├── check_json.rs
│   │   │   │       ├── check_merge_conflict.rs
│   │   │   │       ├── check_symlinks.rs
│   │   │   │       ├── check_toml.rs
│   │   │   │       ├── check_xml.rs
│   │   │   │       ├── check_yaml.rs
│   │   │   │       ├── detect_private_key.rs
│   │   │   │       ├── fix_byte_order_marker.rs
│   │   │   │       ├── fix_end_of_file.rs
│   │   │   │       ├── fix_trailing_whitespace.rs
│   │   │   │       ├── mixed_line_ending.rs
│   │   │   │       ├── mod.rs
│   │   │   │       └── no_commit_to_branch.rs
│   │   │   ├── http.rs
│   │   │   ├── install_source.rs
│   │   │   ├── languages/
│   │   │   │   ├── bun/
│   │   │   │   │   ├── bun.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── deno/
│   │   │   │   │   ├── deno.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── docker.rs
│   │   │   │   ├── docker_image.rs
│   │   │   │   ├── fail.rs
│   │   │   │   ├── golang/
│   │   │   │   │   ├── golang.rs
│   │   │   │   │   ├── gomod.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── haskell.rs
│   │   │   │   ├── julia.rs
│   │   │   │   ├── lua.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── node/
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── node.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── pygrep/
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── pygrep.rs
│   │   │   │   │   └── script.py
│   │   │   │   ├── python/
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── pep723.rs
│   │   │   │   │   ├── pyproject.rs
│   │   │   │   │   ├── python.rs
│   │   │   │   │   ├── uv.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── ruby/
│   │   │   │   │   ├── gem.rs
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── ruby.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── rust/
│   │   │   │   │   ├── installer.rs
│   │   │   │   │   ├── mod.rs
│   │   │   │   │   ├── rust.rs
│   │   │   │   │   ├── rustup.rs
│   │   │   │   │   └── version.rs
│   │   │   │   ├── script.rs
│   │   │   │   ├── swift.rs
│   │   │   │   ├── system.rs
│   │   │   │   └── version.rs
│   │   │   ├── main.rs
│   │   │   ├── printer.rs
│   │   │   ├── process.rs
│   │   │   ├── profiler.rs
│   │   │   ├── resource_limit.rs
│   │   │   ├── run.rs
│   │   │   ├── schema.rs
│   │   │   ├── snapshots/
│   │   │   │   ├── prek__config__tests__language_version.snap
│   │   │   │   ├── prek__config__tests__meta_hooks-5.snap
│   │   │   │   ├── prek__config__tests__numeric_rev_is_parsed_as_string.snap
│   │   │   │   ├── prek__config__tests__parse_hooks-3.snap
│   │   │   │   ├── prek__config__tests__parse_repos-2.snap
│   │   │   │   ├── prek__config__tests__parse_repos-3.snap
│   │   │   │   ├── prek__config__tests__parse_repos-4.snap
│   │   │   │   ├── prek__config__tests__parse_repos-6.snap
│   │   │   │   ├── prek__config__tests__parse_repos.snap
│   │   │   │   ├── prek__config__tests__read_config_with_merge_keys.snap
│   │   │   │   ├── prek__config__tests__read_config_with_nested_merge_keys.snap
│   │   │   │   ├── prek__config__tests__read_manifest.snap
│   │   │   │   ├── prek__config__tests__read_toml_config.snap
│   │   │   │   └── prek__config__tests__read_yaml_config.snap
│   │   │   ├── store.rs
│   │   │   ├── version.rs
│   │   │   ├── warnings.rs
│   │   │   ├── workspace.rs
│   │   │   └── yaml.rs
│   │   └── tests/
│   │       ├── auto_update.rs
│   │       ├── builtin_hooks.rs
│   │       ├── cache.rs
│   │       ├── common/
│   │       │   └── mod.rs
│   │       ├── fixtures/
│   │       │   ├── go.yaml
│   │       │   ├── issue227.yaml
│   │       │   ├── issue253/
│   │       │   │   ├── biome.json
│   │       │   │   ├── input.json
│   │       │   │   └── issue253.yaml
│   │       │   ├── issue265.yaml
│   │       │   ├── node-dependencies.yaml
│   │       │   ├── node-version.yaml
│   │       │   ├── python-version.yaml
│   │       │   ├── repeated-repos.yaml
│   │       │   ├── uv-pre-commit-config.yaml
│   │       │   └── uv-pre-commit-hooks.yaml
│   │       ├── hook_impl.rs
│   │       ├── identify.rs
│   │       ├── install.rs
│   │       ├── languages/
│   │       │   ├── bun.rs
│   │       │   ├── deno.rs
│   │       │   ├── docker.rs
│   │       │   ├── docker_image.rs
│   │       │   ├── fail.rs
│   │       │   ├── golang.rs
│   │       │   ├── haskell.rs
│   │       │   ├── julia.rs
│   │       │   ├── lua.rs
│   │       │   ├── main.rs
│   │       │   ├── node.rs
│   │       │   ├── pygrep.rs
│   │       │   ├── python.rs
│   │       │   ├── ruby.rs
│   │       │   ├── rust.rs
│   │       │   ├── script.rs
│   │       │   ├── swift.rs
│   │       │   ├── unimplemented.rs
│   │       │   └── unsupported.rs
│   │       ├── list.rs
│   │       ├── list_builtins.rs
│   │       ├── meta_hooks.rs
│   │       ├── run.rs
│   │       ├── sample_config.rs
│   │       ├── skipped_hooks.rs
│   │       ├── try_repo.rs
│   │       ├── validate.rs
│   │       ├── workspace.rs
│   │       └── yaml_to_toml.rs
│   ├── prek-consts/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── env_vars.rs
│   │       └── lib.rs
│   ├── prek-identify/
│   │   ├── Cargo.toml
│   │   ├── gen.py
│   │   └── src/
│   │       ├── lib.rs
│   │       └── tags.rs
│   └── prek-pty/
│       ├── Cargo.toml
│       ├── LICENSE
│       └── src/
│           ├── error.rs
│           ├── lib.rs
│           ├── pty.rs
│           ├── sys.rs
│           └── types.rs
├── dist-workspace.toml
├── docs/
│   ├── assets/
│   │   └── badge-v0.json
│   ├── authoring-hooks.md
│   ├── benchmark.md
│   ├── builtin.md
│   ├── changelog.md
│   ├── cli.md
│   ├── compatibility.md
│   ├── configuration.md
│   ├── debugging.md
│   ├── diff.md
│   ├── faq.md
│   ├── index.md
│   ├── installation.md
│   ├── integrations.md
│   ├── languages.md
│   ├── proposals/
│   │   └── concurrency.md
│   ├── quickstart.md
│   ├── requirements.in
│   ├── requirements.txt
│   └── workspace.md
├── licenses/
│   ├── LICENSE.identify.txt
│   └── LICENSE.pre-commit.txt
├── mise.toml
├── mkdocs.yml
├── prek.schema.json
├── pyproject.toml
├── python/
│   └── prek/
│       ├── __init__.py
│       ├── __main__.py
│       └── _find_prek.py
├── rust-toolchain.toml
└── scripts/
    ├── hyperfine-run-benchmarks.sh
    ├── hyperfine-setup-test-env.sh
    ├── macports/
    │   └── Portfile
    └── update-macports-portfile.py
Download .txt
Showing preview only (200K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2219 symbols across 149 files)

FILE: crates/prek-consts/src/env_vars.rs
  type EnvVars (line 5) | pub struct EnvVars;
    constant PATH (line 8) | pub const PATH: &'static str = "PATH";
    constant HOME (line 9) | pub const HOME: &'static str = "HOME";
    constant CI (line 10) | pub const CI: &'static str = "CI";
    constant LC_ALL (line 11) | pub const LC_ALL: &'static str = "LC_ALL";
    constant GIT_DIR (line 14) | pub const GIT_DIR: &'static str = "GIT_DIR";
    constant GIT_WORK_TREE (line 15) | pub const GIT_WORK_TREE: &'static str = "GIT_WORK_TREE";
    constant GIT_TERMINAL_PROMPT (line 16) | pub const GIT_TERMINAL_PROMPT: &'static str = "GIT_TERMINAL_PROMPT";
    constant SKIP (line 18) | pub const SKIP: &'static str = "SKIP";
    constant PREK_HOME (line 21) | pub const PREK_HOME: &'static str = "PREK_HOME";
    constant PREK_COLOR (line 22) | pub const PREK_COLOR: &'static str = "PREK_COLOR";
    constant PREK_SKIP (line 23) | pub const PREK_SKIP: &'static str = "PREK_SKIP";
    constant PREK_ALLOW_NO_CONFIG (line 24) | pub const PREK_ALLOW_NO_CONFIG: &'static str = "PREK_ALLOW_NO_CONFIG";
    constant PREK_NO_CONCURRENCY (line 25) | pub const PREK_NO_CONCURRENCY: &'static str = "PREK_NO_CONCURRENCY";
    constant PREK_MAX_CONCURRENCY (line 26) | pub const PREK_MAX_CONCURRENCY: &'static str = "PREK_MAX_CONCURRENCY";
    constant PREK_NO_FAST_PATH (line 27) | pub const PREK_NO_FAST_PATH: &'static str = "PREK_NO_FAST_PATH";
    constant PREK_UV_SOURCE (line 28) | pub const PREK_UV_SOURCE: &'static str = "PREK_UV_SOURCE";
    constant PREK_NATIVE_TLS (line 29) | pub const PREK_NATIVE_TLS: &'static str = "PREK_NATIVE_TLS";
    constant SSL_CERT_FILE (line 30) | pub const SSL_CERT_FILE: &'static str = "SSL_CERT_FILE";
    constant SSL_CERT_DIR (line 31) | pub const SSL_CERT_DIR: &'static str = "SSL_CERT_DIR";
    constant PREK_CONTAINER_RUNTIME (line 32) | pub const PREK_CONTAINER_RUNTIME: &'static str = "PREK_CONTAINER_RUNTI...
    constant PREK_QUIET (line 33) | pub const PREK_QUIET: &'static str = "PREK_QUIET";
    constant PREK_LOG_TRUNCATE_LIMIT (line 34) | pub const PREK_LOG_TRUNCATE_LIMIT: &'static str = "PREK_LOG_TRUNCATE_L...
    constant PREK_INTERNAL__TEST_DIR (line 37) | pub const PREK_INTERNAL__TEST_DIR: &'static str = "PREK_INTERNAL__TEST...
    constant PREK_INTERNAL__SORT_FILENAMES (line 38) | pub const PREK_INTERNAL__SORT_FILENAMES: &'static str = "PREK_INTERNAL...
    constant PREK_INTERNAL__SKIP_POST_CHECKOUT (line 39) | pub const PREK_INTERNAL__SKIP_POST_CHECKOUT: &'static str = "PREK_INTE...
    constant PREK_INTERNAL__RUN_ORIGINAL_PRE_COMMIT (line 40) | pub const PREK_INTERNAL__RUN_ORIGINAL_PRE_COMMIT: &'static str =
    constant PREK_INTERNAL__BUN_BINARY_NAME (line 42) | pub const PREK_INTERNAL__BUN_BINARY_NAME: &'static str = "PREK_INTERNA...
    constant PREK_INTERNAL__DENO_BINARY_NAME (line 43) | pub const PREK_INTERNAL__DENO_BINARY_NAME: &'static str = "PREK_INTERN...
    constant PREK_INTERNAL__GO_BINARY_NAME (line 44) | pub const PREK_INTERNAL__GO_BINARY_NAME: &'static str = "PREK_INTERNAL...
    constant PREK_INTERNAL__NODE_BINARY_NAME (line 45) | pub const PREK_INTERNAL__NODE_BINARY_NAME: &'static str = "PREK_INTERN...
    constant PREK_INTERNAL__RUSTUP_BINARY_NAME (line 46) | pub const PREK_INTERNAL__RUSTUP_BINARY_NAME: &'static str = "PREK_INTE...
    constant PREK_INTERNAL__SKIP_CABAL_UPDATE (line 47) | pub const PREK_INTERNAL__SKIP_CABAL_UPDATE: &'static str = "PREK_INTER...
    constant PREK_RUNNING_LEGACY (line 48) | pub const PREK_RUNNING_LEGACY: &'static str = "PREK_RUNNING_LEGACY";
    constant PREK_GENERATE (line 49) | pub const PREK_GENERATE: &'static str = "PREK_GENERATE";
    constant VIRTUAL_ENV (line 52) | pub const VIRTUAL_ENV: &'static str = "VIRTUAL_ENV";
    constant PYTHONHOME (line 53) | pub const PYTHONHOME: &'static str = "PYTHONHOME";
    constant UV_PYTHON (line 54) | pub const UV_PYTHON: &'static str = "UV_PYTHON";
    constant UV_SYSTEM_PYTHON (line 55) | pub const UV_SYSTEM_PYTHON: &'static str = "UV_SYSTEM_PYTHON";
    constant UV_CACHE_DIR (line 56) | pub const UV_CACHE_DIR: &'static str = "UV_CACHE_DIR";
    constant UV_PYTHON_INSTALL_DIR (line 57) | pub const UV_PYTHON_INSTALL_DIR: &'static str = "UV_PYTHON_INSTALL_DIR";
    constant UV_MANAGED_PYTHON (line 58) | pub const UV_MANAGED_PYTHON: &'static str = "UV_MANAGED_PYTHON";
    constant UV_NO_MANAGED_PYTHON (line 59) | pub const UV_NO_MANAGED_PYTHON: &'static str = "UV_NO_MANAGED_PYTHON";
    constant NPM_CONFIG_USERCONFIG (line 62) | pub const NPM_CONFIG_USERCONFIG: &'static str = "NPM_CONFIG_USERCONFIG";
    constant NPM_CONFIG_PREFIX (line 63) | pub const NPM_CONFIG_PREFIX: &'static str = "NPM_CONFIG_PREFIX";
    constant NODE_PATH (line 64) | pub const NODE_PATH: &'static str = "NODE_PATH";
    constant BUN_INSTALL (line 67) | pub const BUN_INSTALL: &'static str = "BUN_INSTALL";
    constant DENO_DIR (line 70) | pub const DENO_DIR: &'static str = "DENO_DIR";
    constant DENO_NO_UPDATE_CHECK (line 71) | pub const DENO_NO_UPDATE_CHECK: &'static str = "DENO_NO_UPDATE_CHECK";
    constant GITHUB_TOKEN (line 74) | pub const GITHUB_TOKEN: &'static str = "GITHUB_TOKEN";
    constant GOTOOLCHAIN (line 77) | pub const GOTOOLCHAIN: &'static str = "GOTOOLCHAIN";
    constant GOROOT (line 78) | pub const GOROOT: &'static str = "GOROOT";
    constant GOPATH (line 79) | pub const GOPATH: &'static str = "GOPATH";
    constant GOBIN (line 80) | pub const GOBIN: &'static str = "GOBIN";
    constant GOFLAGS (line 81) | pub const GOFLAGS: &'static str = "GOFLAGS";
    constant LUA_PATH (line 84) | pub const LUA_PATH: &'static str = "LUA_PATH";
    constant LUA_CPATH (line 85) | pub const LUA_CPATH: &'static str = "LUA_CPATH";
    constant PREK_RUBY_MIRROR (line 88) | pub const PREK_RUBY_MIRROR: &'static str = "PREK_RUBY_MIRROR";
    constant GEM_HOME (line 89) | pub const GEM_HOME: &'static str = "GEM_HOME";
    constant GEM_PATH (line 90) | pub const GEM_PATH: &'static str = "GEM_PATH";
    constant BUNDLE_IGNORE_CONFIG (line 91) | pub const BUNDLE_IGNORE_CONFIG: &'static str = "BUNDLE_IGNORE_CONFIG";
    constant BUNDLE_GEMFILE (line 92) | pub const BUNDLE_GEMFILE: &'static str = "BUNDLE_GEMFILE";
    constant RUSTUP_TOOLCHAIN (line 95) | pub const RUSTUP_TOOLCHAIN: &'static str = "RUSTUP_TOOLCHAIN";
    constant RUSTUP_AUTO_INSTALL (line 96) | pub const RUSTUP_AUTO_INSTALL: &'static str = "RUSTUP_AUTO_INSTALL";
    constant CARGO_HOME (line 97) | pub const CARGO_HOME: &'static str = "CARGO_HOME";
    constant RUSTUP_HOME (line 98) | pub const RUSTUP_HOME: &'static str = "RUSTUP_HOME";
    constant PRE_COMMIT_HOME (line 103) | pub const PRE_COMMIT_HOME: &'static str = "PRE_COMMIT_HOME";
    constant PRE_COMMIT_ALLOW_NO_CONFIG (line 104) | const PRE_COMMIT_ALLOW_NO_CONFIG: &'static str = "PRE_COMMIT_ALLOW_NO_...
    constant PRE_COMMIT_NO_CONCURRENCY (line 105) | const PRE_COMMIT_NO_CONCURRENCY: &'static str = "PRE_COMMIT_NO_CONCURR...
    method var_os (line 110) | pub fn var_os(name: &str) -> Option<OsString> {
    method is_set (line 120) | pub fn is_set(name: &str) -> bool {
    method is_under_ci (line 125) | pub fn is_under_ci() -> bool {
    method var (line 130) | pub fn var(name: &str) -> Result<String, std::env::VarError> {
    method var_as_bool (line 138) | pub fn var_as_bool(name: &str) -> Option<bool> {
    method parse_boolish (line 153) | fn parse_boolish(val: &str) -> Option<bool> {
    method pre_commit_name (line 171) | fn pre_commit_name(name: &str) -> Option<&str> {
  function test_parse_boolish (line 185) | fn test_parse_boolish() {

FILE: crates/prek-consts/src/lib.rs
  constant PRE_COMMIT_CONFIG_YAML (line 8) | pub const PRE_COMMIT_CONFIG_YAML: &str = ".pre-commit-config.yaml";
  constant PRE_COMMIT_CONFIG_YML (line 9) | pub const PRE_COMMIT_CONFIG_YML: &str = ".pre-commit-config.yml";
  constant PREK_TOML (line 10) | pub const PREK_TOML: &str = "prek.toml";
  constant PRE_COMMIT_HOOKS_YAML (line 11) | pub const PRE_COMMIT_HOOKS_YAML: &str = ".pre-commit-hooks.yaml";
  function prepend_paths (line 18) | pub fn prepend_paths(paths: &[&Path]) -> Result<OsString, std::env::Join...

FILE: crates/prek-identify/gen.py
  function gen (line 44) | def gen():
  function main (line 97) | def main():

FILE: crates/prek-identify/src/lib.rs
  constant TAG_WORDS (line 31) | const TAG_WORDS: usize = tags::ALL_TAGS.len().div_ceil(64);
  type TagSet (line 38) | pub struct TagSet {
    method fmt (line 43) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    method new (line 90) | pub const fn new(tag_ids: &[u16]) -> Self {
    method from_tags (line 106) | pub fn from_tags<I, S>(tags: I) -> Self
    method insert (line 124) | pub const fn insert(&mut self, tag_id: u16) {
    method is_disjoint (line 131) | pub fn is_disjoint(&self, other: &TagSet) -> bool {
    method is_subset (line 141) | pub fn is_subset(&self, other: &TagSet) -> bool {
    method iter (line 151) | pub fn iter(&self) -> TagSetIter<'_> {
    method is_empty (line 160) | pub fn is_empty(&self) -> bool {
    method bitor_assign (line 166) | fn bitor_assign(&mut self, rhs: &TagSet) {
    method deserialize (line 175) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    method inline_schema (line 214) | fn inline_schema() -> bool {
    method schema_name (line 218) | fn schema_name() -> Cow<'static, str> {
    method json_schema (line 222) | fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars...
  function tag_id (line 48) | fn tag_id(tag: &str) -> Option<usize> {
  type TagSetIter (line 52) | pub struct TagSetIter<'a> {
  type Item (line 59) | type Item = &'static str;
  method next (line 61) | fn next(&mut self) -> Option<Self::Item> {
  type Error (line 234) | pub enum Error {
  function tags_from_path (line 243) | pub fn tags_from_path(path: &Path) -> Result<TagSet, Error> {
  function tags_from_filename (line 301) | fn tags_from_filename(filename: &Path) -> TagSet {
  function tags_from_interpreter (line 337) | fn tags_from_interpreter(interpreter: &str) -> TagSet {
  type ShebangError (line 360) | pub enum ShebangError {
  function starts_with (line 373) | fn starts_with(slice: &[String], prefix: &[&str]) -> bool {
  function parse_nix_shebang (line 381) | fn parse_nix_shebang<R: BufRead>(reader: &mut R, mut cmd: Vec<String>) -...
  function parse_shebang (line 424) | pub fn parse_shebang(path: &Path) -> Result<Vec<String>, ShebangError> {
  function is_text_char (line 483) | fn is_text_char(b: u8) -> bool {
  function is_text_file (line 492) | fn is_text_file(path: &Path) -> bool {
  function assert_tagset (line 514) | fn assert_tagset(actual: &TagSet, expected: &[&'static str]) {
  function tags_from_path (line 524) | fn tags_from_path() -> anyhow::Result<()> {
  function tags_from_path (line 543) | fn tags_from_path() -> anyhow::Result<()> {
  function tags_from_filename (line 557) | fn tags_from_filename() {
  function tags_from_interpreter (line 605) | fn tags_from_interpreter() {
  function tagset_new_iter_and_is_empty (line 626) | fn tagset_new_iter_and_is_empty() {
  function tagset_from_tags_intersects_subset_and_bitor_assign (line 640) | fn tagset_from_tags_intersects_subset_and_bitor_assign() {
  function tagset_new_panics_on_out_of_range_id (line 656) | fn tagset_new_panics_on_out_of_range_id() {
  function tagset_deserialize_from_string_slice (line 664) | fn tagset_deserialize_from_string_slice() {
  function tagset_deserialize_unknown_tag_errors (line 672) | fn tagset_deserialize_unknown_tag_errors() {
  function parse_shebang_nix_shell_interpreter (line 682) | fn parse_shebang_nix_shell_interpreter() -> anyhow::Result<()> {
  function parse_shebang_nix_shell_without_interpreter (line 702) | fn parse_shebang_nix_shell_without_interpreter() -> anyhow::Result<()> {

FILE: crates/prek-identify/src/tags.rs
  constant ALL_TAGS (line 5) | pub const ALL_TAGS: [&str; 311] = [
  constant TAG_FILE (line 319) | pub const TAG_FILE: u16 = 78;
  constant TAG_DIRECTORY (line 320) | pub const TAG_DIRECTORY: u16 = 58;
  constant TAG_SYMLINK (line 321) | pub const TAG_SYMLINK: u16 = 248;
  constant TAG_SOCKET (line 322) | pub const TAG_SOCKET: u16 = 238;
  constant TAG_EXECUTABLE (line 323) | pub const TAG_EXECUTABLE: u16 = 74;
  constant TAG_NON_EXECUTABLE (line 324) | pub const TAG_NON_EXECUTABLE: u16 = 176;
  constant TAG_TEXT (line 325) | pub const TAG_TEXT: u16 = 255;
  constant TAG_BINARY (line 326) | pub const TAG_BINARY: u16 = 21;
  constant TAG_SET_FILE (line 328) | pub const TAG_SET_FILE: TagSet = TagSet::new(&[78]);
  constant TAG_SET_DIRECTORY (line 329) | pub const TAG_SET_DIRECTORY: TagSet = TagSet::new(&[58]);
  constant TAG_SET_SYMLINK (line 330) | pub const TAG_SET_SYMLINK: TagSet = TagSet::new(&[248]);
  constant TAG_SET_SOCKET (line 331) | pub const TAG_SET_SOCKET: TagSet = TagSet::new(&[238]);
  constant TAG_SET_TEXT (line 332) | pub const TAG_SET_TEXT: TagSet = TagSet::new(&[255]);
  constant TAG_SET_TEXT_OR_BINARY (line 333) | pub const TAG_SET_TEXT_OR_BINARY: TagSet = TagSet::new(&[21, 255]);
  constant TAG_SET_EXECUTABLE_TEXT (line 334) | pub const TAG_SET_EXECUTABLE_TEXT: TagSet = TagSet::new(&[74, 255]);
  constant TAG_SET_JSON (line 335) | pub const TAG_SET_JSON: TagSet = TagSet::new(&[135]);
  constant TAG_SET_JSON5 (line 336) | pub const TAG_SET_JSON5: TagSet = TagSet::new(&[136]);
  constant TAG_SET_TOML (line 337) | pub const TAG_SET_TOML: TagSet = TagSet::new(&[260]);
  constant TAG_SET_XML (line 338) | pub const TAG_SET_XML: TagSet = TagSet::new(&[297]);
  constant TAG_SET_YAML (line 339) | pub const TAG_SET_YAML: TagSet = TagSet::new(&[301]);
  constant INTERPRETERS (line 341) | pub const INTERPRETERS: phf::Map<&str, TagSet> = phf::phf_map! {
  constant EXTENSIONS (line 390) | pub const EXTENSIONS: phf::Map<&str, TagSet> = phf::phf_map! {
  constant NAMES (line 1071) | pub const NAMES: phf::Map<&str, TagSet> = phf::phf_map! {

FILE: crates/prek-pty/src/error.rs
  type Error (line 3) | pub enum Error {
    method fmt (line 13) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    method from (line 25) | fn from(e: std::io::Error) -> Self {
    method from (line 31) | fn from(e: rustix::io::Errno) -> Self {
    method source (line 37) | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
  type Result (line 47) | pub type Result<T> = std::result::Result<T, Error>;

FILE: crates/prek-pty/src/pty.rs
  type AsyncPty (line 4) | type AsyncPty = tokio::io::unix::AsyncFd<crate::sys::Pty>;
  function open (line 11) | pub fn open() -> crate::Result<(Pty, Pts)> {
  type Pty (line 20) | pub struct Pty(AsyncPty);
    method from_fd (line 31) | pub unsafe fn from_fd(fd: std::os::fd::OwnedFd) -> crate::Result<Self> {
    method resize (line 41) | pub fn resize(&self, size: crate::Size) -> crate::Result<()> {
    method split (line 48) | pub fn split(&self) -> (ReadPty<'_>, WritePty<'_>) {
    method into_split (line 58) | pub fn into_split(self) -> (OwnedReadPty, OwnedWritePty) {
    method as_fd (line 73) | fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
    method as_raw_fd (line 79) | fn as_raw_fd(&self) -> std::os::fd::RawFd {
    method poll_read (line 85) | fn poll_read(
    method poll_write (line 95) | fn poll_write(
    method poll_flush (line 103) | fn poll_flush(
    method poll_shutdown (line 110) | fn poll_shutdown(
  function from (line 67) | fn from(pty: Pty) -> Self {
  type Pts (line 121) | pub struct Pts(pub(crate) crate::sys::Pts);
    method from_fd (line 130) | pub unsafe fn from_fd(fd: std::os::fd::OwnedFd) -> Self {
    method setup_subprocess (line 134) | pub fn setup_subprocess(
    method session_leader (line 144) | pub fn session_leader(&self) -> impl FnMut() -> std::io::Result<()> + ...
    method as_fd (line 150) | fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
    method as_raw_fd (line 156) | fn as_raw_fd(&self) -> std::os::fd::RawFd {
  type ReadPty (line 162) | pub struct ReadPty<'a>(&'a AsyncPty);
  function poll_read (line 165) | fn poll_read(
  type WritePty (line 175) | pub struct WritePty<'a>(&'a AsyncPty);
  function resize (line 182) | pub fn resize(&self, size: crate::Size) -> crate::Result<()> {
  function poll_write (line 188) | fn poll_write(
  function poll_flush (line 196) | fn poll_flush(
  function poll_shutdown (line 203) | fn poll_shutdown(
  type OwnedReadPty (line 213) | pub struct OwnedReadPty(std::sync::Arc<AsyncPty>);
    method unsplit (line 223) | pub fn unsplit(self, write_half: OwnedWritePty) -> crate::Result<Pty> {
    method poll_read (line 242) | fn poll_read(
  type OwnedWritePty (line 253) | pub struct OwnedWritePty(std::sync::Arc<AsyncPty>);
    method resize (line 260) | pub fn resize(&self, size: crate::Size) -> crate::Result<()> {
    method poll_write (line 266) | fn poll_write(
    method poll_flush (line 274) | fn poll_flush(
    method poll_shutdown (line 281) | fn poll_shutdown(
  function poll_read (line 289) | fn poll_read(
  function poll_write (line 324) | fn poll_write(
  function poll_flush (line 341) | fn poll_flush(

FILE: crates/prek-pty/src/sys.rs
  type Pty (line 7) | pub struct Pty(std::os::fd::OwnedFd);
    method open (line 10) | pub fn open() -> crate::Result<Self> {
    method from_fd (line 25) | pub unsafe fn from_fd(fd: std::os::fd::OwnedFd) -> Self {
    method set_term_size (line 29) | pub fn set_term_size(&self, size: crate::Size) -> crate::Result<()> {
    method pts (line 36) | pub fn pts(&self) -> crate::Result<Pts> {
    method set_nonblocking (line 47) | pub fn set_nonblocking(&self) -> rustix::io::Result<()> {
    method read_buf (line 55) | pub fn read_buf<'a>(
    method as_fd (line 77) | fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
    method as_raw_fd (line 87) | fn as_raw_fd(&self) -> std::os::fd::RawFd {
    method read (line 93) | fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
    method write (line 99) | fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
    method flush (line 103) | fn flush(&mut self) -> std::io::Result<()> {
  function from (line 64) | fn from(pty: Pty) -> Self {
  function read (line 109) | fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
  function write (line 115) | fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
  function flush (line 119) | fn flush(&mut self) -> std::io::Result<()> {
  type Pts (line 124) | pub struct Pts(std::os::fd::OwnedFd);
    method from_fd (line 127) | pub unsafe fn from_fd(fd: std::os::fd::OwnedFd) -> Self {
    method setup_subprocess (line 131) | pub fn setup_subprocess(
    method session_leader (line 145) | pub fn session_leader(&self) -> impl FnMut() -> std::io::Result<()> + ...
    method as_fd (line 164) | fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
    method as_raw_fd (line 170) | fn as_raw_fd(&self) -> std::os::fd::RawFd {
  function from (line 158) | fn from(pts: Pts) -> Self {

FILE: crates/prek-pty/src/types.rs
  type Size (line 3) | pub struct Size {
    method new (line 14) | pub fn new(row: u16, col: u16) -> Self {
    method new_with_pixel (line 26) | pub fn new_with_pixel(row: u16, col: u16, xpixel: u16, ypixel: u16) ->...
  function from (line 37) | fn from(size: Size) -> Self {

FILE: crates/prek/build.rs
  function main (line 29) | fn main() {
  function commit_info (line 43) | fn commit_info(workspace_root: &Path) {
  function git_head (line 104) | fn git_head(git_dir: &Path) -> Option<PathBuf> {

FILE: crates/prek/src/archive.rs
  type Error (line 35) | pub enum Error {
  constant DEFAULT_BUF_SIZE (line 50) | const DEFAULT_BUF_SIZE: usize = 128 * 1024;
  type ArchiveExtension (line 53) | pub enum ArchiveExtension {
    method from_path (line 65) | pub fn from_path(path: impl AsRef<Path>) -> Result<Self, Error> {
  method fmt (line 98) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  function strip_component (line 114) | pub fn strip_component(source: impl AsRef<Path>) -> Result<PathBuf, Erro...
  function unzip (line 134) | pub async fn unzip<R: AsyncRead + Unpin>(reader: R, target: impl AsRef<P...
  function untar_gz (line 255) | pub async fn untar_gz<R: AsyncRead + Unpin>(
  function untar_xz (line 275) | pub async fn untar_xz<R: AsyncRead + Unpin>(
  function untar (line 295) | pub async fn untar<R: AsyncRead + Unpin>(reader: R, target: impl AsRef<P...
  function unpack (line 310) | pub async fn unpack<R: AsyncRead + Unpin>(

FILE: crates/prek/src/cleanup.rs
  function cleanup (line 6) | pub fn cleanup() {
  function add_cleanup (line 14) | pub fn add_cleanup<F: Fn() + Send + 'static>(f: F) {

FILE: crates/prek/src/cli/auto_update.rs
  type Revision (line 31) | struct Revision {
  function auto_update (line 36) | pub(crate) async fn auto_update(
  function update_repo (line 189) | async fn update_repo(
  function setup_and_fetch_repo (line 228) | async fn setup_and_fetch_repo(repo_url: &str, repo_path: &Path) -> Resul...
  function resolve_bleeding_edge (line 257) | async fn resolve_bleeding_edge(repo_path: &Path) -> Result<Option<String...
  function get_tag_timestamps (line 296) | async fn get_tag_timestamps(repo: &Path) -> Result<Vec<(String, u64)>> {
  function resolve_revision (line 341) | async fn resolve_revision(
  function freeze_revision (line 377) | async fn freeze_revision(repo_path: &Path, rev: &str) -> Result<Option<S...
  function checkout_and_validate_manifest (line 394) | async fn checkout_and_validate_manifest(
  function get_best_candidate_tag (line 454) | async fn get_best_candidate_tag(repo: &Path, rev: &str, current_rev: &st...
  function write_new_config (line 478) | async fn write_new_config(path: &Path, revisions: &[Option<Revision>]) -...
  function render_updated_toml_config (line 499) | fn render_updated_toml_config(
  function render_updated_yaml_config (line 571) | fn render_updated_yaml_config(
  function setup_test_repo (line 639) | async fn setup_test_repo() -> tempfile::TempDir {
  function git_cmd (line 702) | fn git_cmd(dir: impl AsRef<Path>, summary: &str) -> Cmd {
  function create_commit (line 710) | async fn create_commit(repo: &Path, message: &str) {
  function create_backdated_commit (line 719) | async fn create_backdated_commit(repo: &Path, message: &str, days_ago: u...
  function create_lightweight_tag (line 738) | async fn create_lightweight_tag(repo: &Path, tag: &str) {
  function create_annotated_tag (line 748) | async fn create_annotated_tag(repo: &Path, tag: &str, days_ago: u64) {
  function get_backdated_timestamp (line 770) | fn get_backdated_timestamp(days_ago: u64) -> u64 {
  function test_get_tag_timestamps (line 779) | async fn test_get_tag_timestamps() {
  function test_resolve_bleeding_edge_prefers_exact_tag (line 798) | async fn test_resolve_bleeding_edge_prefers_exact_tag() {
  function test_resolve_bleeding_edge_falls_back_to_rev_parse (line 819) | async fn test_resolve_bleeding_edge_falls_back_to_rev_parse() {
  function test_resolve_revision_uses_cooldown_bucket (line 851) | async fn test_resolve_revision_uses_cooldown_bucket() {
  function test_resolve_revision_returns_none_when_all_tags_too_new (line 868) | async fn test_resolve_revision_returns_none_when_all_tags_too_new() {
  function test_resolve_revision_picks_oldest_eligible_bucket (line 884) | async fn test_resolve_revision_picks_oldest_eligible_bucket() {
  function test_resolve_revision_prefers_version_like_tags (line 903) | async fn test_resolve_revision_prefers_version_like_tags() {
  function test_resolve_revision_picks_closest_version_string (line 921) | async fn test_resolve_revision_picks_closest_version_string() {
  function test_get_tag_timestamps_stable_order_for_equal_timestamps (line 936) | async fn test_get_tag_timestamps_stable_order_for_equal_timestamps() {
  function test_get_tag_timestamps_deterministic_order_for_equal_timestamp_non_semver (line 956) | async fn test_get_tag_timestamps_deterministic_order_for_equal_timestamp...

FILE: crates/prek/src/cli/cache_clean.rs
  function cache_clean (line 16) | pub(crate) fn cache_clean(store: &Store, printer: Printer) -> Result<Exi...
  type RemovalStats (line 64) | pub struct RemovalStats {
  function remove_dir_all (line 71) | fn remove_dir_all(path: &Path, reporter: Option<&CleaningReporter>) -> i...
  function remove_symlink (line 117) | fn remove_symlink(path: &Path, file_type: FileType) -> io::Result<()> {
  function fix_permissions (line 138) | pub fn fix_permissions<P: AsRef<Path>>(path: P) -> io::Result<()> {
  function fix_permissions (line 167) | pub fn fix_permissions<P: AsRef<Path>>(_path: P) -> io::Result<()> {
  function rm_rf_counts_and_removes_tree (line 178) | fn rm_rf_counts_and_removes_tree() -> anyhow::Result<()> {
  function rm_rf_empty_directory (line 196) | fn rm_rf_empty_directory() -> anyhow::Result<()> {
  function rm_rf_rejects_non_directory (line 211) | fn rm_rf_rejects_non_directory() -> anyhow::Result<()> {
  function rm_rf_non_exist_directory (line 224) | fn rm_rf_non_exist_directory() -> anyhow::Result<()> {
  function rm_rf_counts_symlink_entries (line 238) | fn rm_rf_counts_symlink_entries() -> anyhow::Result<()> {

FILE: crates/prek/src/cli/cache_gc.rs
  type RemovalKind (line 21) | enum RemovalKind {
    method display (line 29) | fn display(self, count: usize) -> &'static str {
  type RemovalItem (line 49) | struct RemovalItem {
    method new (line 56) | fn new(label: String, abs_path: String) -> Self {
  type Removal (line 66) | struct Removal {
    method new (line 74) | fn new(kind: RemovalKind) -> Self {
  method fmt (line 85) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  method add_assign (line 96) | fn add_assign(&mut self, rhs: Self) {
  type RemovalSummary (line 106) | struct RemovalSummary {
    method is_empty (line 113) | fn is_empty(&self) -> bool {
    method joined (line 117) | fn joined(&self) -> String {
    method total_bytes (line 121) | fn total_bytes(&self) -> u64 {
    method add_assign (line 127) | fn add_assign(&mut self, rhs: &Removal) {
  function cache_gc (line 136) | pub(crate) async fn cache_gc(
  function print_removed_details (line 311) | fn print_removed_details(printer: Printer, verb: &str, removal: &Removal...
  function hook_env_keys_from_config (line 341) | fn hook_env_keys_from_config(store: &Store, config: &config::Config) -> ...
  function mark_tool_versions_from_install_info (line 402) | fn mark_tool_versions_from_install_info(
  function tool_version_dir_name (line 421) | fn tool_version_dir_name(bucket_root: &Path, toolchain: &Path) -> Option...
  function sweep_tool_versions (line 430) | fn sweep_tool_versions(
  function sweep_tool_bucket_versions (line 449) | fn sweep_tool_bucket_versions(
  function sweep_dir_by_name (line 525) | fn sweep_dir_by_name(
  function label_for_entry (line 611) | fn label_for_entry(
  function detail_lines_for_entry (line 626) | fn detail_lines_for_entry(
  type RepoMarker (line 667) | struct RepoMarker {
  function read_repo_marker (line 672) | fn read_repo_marker(root: &Path) -> Option<RepoMarker> {
  function read_hook_marker (line 680) | fn read_hook_marker(root: &Path) -> Option<InstallInfo> {
  function truncate_end (line 685) | fn truncate_end(s: &str, max_chars: usize) -> String {
  function split_repo_dependency (line 697) | fn split_repo_dependency(deps: &FxHashSet<String>) -> (Option<String>, V...
  function format_dependency_list (line 721) | fn format_dependency_list(deps: &[String], max_items: usize, max_chars: ...
  function truncate_end_returns_input_when_short_enough (line 740) | fn truncate_end_returns_input_when_short_enough() {
  function truncate_end_truncates_and_appends_ellipsis (line 746) | fn truncate_end_truncates_and_appends_ellipsis() {
  function truncate_end_counts_chars_not_bytes (line 752) | fn truncate_end_counts_chars_not_bytes() {
  function split_repo_dependency_prefers_url_like_repo_at_rev (line 759) | fn split_repo_dependency_prefers_url_like_repo_at_rev() {
  function split_repo_dependency_returns_none_when_no_repo_like_dep (line 775) | fn split_repo_dependency_returns_none_when_no_repo_like_dep() {
  function format_dependency_list_includes_more_suffix (line 786) | fn format_dependency_list_includes_more_suffix() {
  function format_dependency_list_truncates_rendered_string (line 792) | fn format_dependency_list_truncates_rendered_string() {

FILE: crates/prek/src/cli/cache_size.rs
  function cache_size (line 11) | pub(crate) fn cache_size(
  function human_readable_bytes (line 37) | pub(crate) fn human_readable_bytes(bytes: u64) -> (f32, &'static str) {
  function dir_size_bytes (line 45) | pub(crate) fn dir_size_bytes(path: &Path) -> u64 {
  function human_readable_bytes_handles_zero (line 67) | fn human_readable_bytes_handles_zero() {
  function dir_stats_missing_directory (line 74) | fn dir_stats_missing_directory() -> anyhow::Result<()> {
  function dir_stats_empty_directory (line 84) | fn dir_stats_empty_directory() -> anyhow::Result<()> {
  function dir_stats_nested_files (line 93) | fn dir_stats_nested_files() -> anyhow::Result<()> {

FILE: crates/prek/src/cli/completion.rs
  function selector_completer (line 14) | pub(crate) fn selector_completer(current: &OsStr) -> Vec<CompletionCandi...
  function all_hooks (line 157) | fn all_hooks(proj: &Project) -> Vec<(String, Option<String>)> {
  function list_subdirs (line 188) | fn list_subdirs(
  function list_direct_project_colons (line 229) | fn list_direct_project_colons(

FILE: crates/prek/src/cli/hook_impl.rs
  function hook_impl (line 27) | pub(crate) async fn hook_impl(
  function read_hook_stdin (line 150) | async fn read_hook_stdin(hook_type: HookType) -> Result<Vec<u8>> {
  function run_legacy (line 161) | async fn run_legacy(
  function to_run_args (line 220) | async fn to_run_args(hook_type: HookType, args: &[OsString], stdin: &[u8...
  type PushInfo (line 275) | struct PushInfo {
  function parse_pre_push_info (line 283) | async fn parse_pre_push_info(remote_name: &str, stdin: &[u8]) -> Option<...
  function format_expected_args (line 352) | fn format_expected_args(range: RangeInclusive<usize>) -> String {
  function format_received_args (line 364) | fn format_received_args(received: usize) -> String {
  function format_argument_dump (line 372) | fn format_argument_dump(args: &[OsString]) -> String {

FILE: crates/prek/src/cli/identify.rs
  type IdentifyEntry (line 13) | struct IdentifyEntry {
  function identify (line 18) | pub(crate) fn identify(

FILE: crates/prek/src/cli/install.rs
  function install (line 26) | pub(crate) async fn install(
  function prepare_hooks (line 104) | pub(crate) async fn prepare_hooks(
  function get_hook_types (line 136) | fn get_hook_types(
  function install_hook_script (line 176) | fn install_hook_script(
  function render_global_args (line 329) | fn render_global_args(quiet: u8, verbose: u8, no_progress: bool) -> Stri...
  function is_our_script (line 378) | fn is_our_script(hook_path: &Path) -> std::io::Result<bool> {
  function uninstall (line 385) | pub(crate) async fn uninstall(
  function init_template_dir (line 459) | pub(crate) async fn init_template_dir(

FILE: crates/prek/src/cli/list.rs
  type SerializableHook (line 18) | struct SerializableHook {
  function list (line 28) | pub(crate) async fn list(

FILE: crates/prek/src/cli/list_builtins.rs
  type SerializableBuiltinHook (line 13) | struct SerializableBuiltinHook {
  function list_builtins (line 20) | pub(crate) fn list_builtins(

FILE: crates/prek/src/cli/mod.rs
  type ExitStatus (line 52) | pub(crate) enum ExitStatus {
    method from (line 82) | fn from(code: u8) -> Self {
  method from (line 70) | fn from(status: ExitStatus) -> Self {
  type ColorChoice (line 91) | pub enum ColorChoice {
  function from (line 103) | fn from(value: ColorChoice) -> Self {
  constant STYLES (line 112) | const STYLES: Styles = Styles::styled()
  type Cli (line 131) | pub(crate) struct Cli {
  type GlobalArgs (line 146) | pub(crate) struct GlobalArgs {
  type Command (line 217) | pub(crate) enum Command {
  type InstallArgs (line 272) | pub(crate) struct InstallArgs {
  type PrepareHooksArgs (line 342) | pub(crate) struct PrepareHooksArgs {
  type UninstallArgs (line 377) | pub(crate) struct UninstallArgs {
  type RunExtraArgs (line 398) | pub(crate) struct RunExtraArgs {
  type RunArgs (line 427) | pub(crate) struct RunArgs {
  type TryRepoArgs (line 531) | pub(crate) struct TryRepoArgs {
  type ListOutputFormat (line 545) | pub(crate) enum ListOutputFormat {
  type IdentifyOutputFormat (line 553) | pub(crate) enum IdentifyOutputFormat {
  type ListBuiltinsArgs (line 560) | pub(crate) struct ListBuiltinsArgs {
  type ListArgs (line 567) | pub(crate) struct ListArgs {
  type IdentifyArgs (line 612) | pub(crate) struct IdentifyArgs {
  type ValidateConfigArgs (line 622) | pub(crate) struct ValidateConfigArgs {
  type ValidateManifestArgs (line 629) | pub(crate) struct ValidateManifestArgs {
  type SampleConfigArgs (line 637) | pub(crate) struct SampleConfigArgs {
  type SampleConfigFormat (line 656) | pub(crate) enum SampleConfigFormat {
  type SampleConfigTarget (line 662) | pub(crate) enum SampleConfigTarget {
    method from (line 669) | fn from(value: Option<Option<PathBuf>>) -> Self {
  type AutoUpdateArgs (line 679) | pub(crate) struct AutoUpdateArgs {
  type HookImplArgs (line 709) | pub(crate) struct HookImplArgs {
  type CacheNamespace (line 755) | pub(crate) struct CacheNamespace {
  type UtilNamespace (line 761) | pub(crate) struct UtilNamespace {
  type UtilCommand (line 767) | pub(crate) enum UtilCommand {
  type YamlToTomlArgs (line 783) | pub(crate) struct YamlToTomlArgs {
  type CacheCommand (line 800) | pub(crate) enum CacheCommand {
  type SizeArgs (line 812) | pub struct SizeArgs {
  type CacheGcArgs (line 819) | pub(crate) struct CacheGcArgs {
  type SelfNamespace (line 826) | pub(crate) struct SelfNamespace {
  type SelfCommand (line 832) | pub(crate) enum SelfCommand {
  type SelfUpdateArgs (line 838) | pub(crate) struct SelfUpdateArgs {
  type GenerateShellCompletionArgs (line 850) | pub(crate) struct GenerateShellCompletionArgs {
  type InitTemplateDirArgs (line 857) | pub(crate) struct InitTemplateDirArgs {
  constant ROOT_DIR (line 887) | const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
  type Mode (line 889) | enum Mode {
  function generate (line 900) | fn generate(mut cmd: Command) -> String {
  function generate_command (line 921) | fn generate_command<'a>(
  function emit_env_option (line 1102) | fn emit_env_option(opt: &clap::Arg, output: &mut String) {
  function emit_default_option (line 1114) | fn emit_default_option(opt: &clap::Arg, output: &mut String) {
  function emit_possible_options (line 1132) | fn emit_possible_options(opt: &clap::Arg, output: &mut String) {
  function generate_cli_reference (line 1159) | fn generate_cli_reference() -> Result<()> {

FILE: crates/prek/src/cli/reporter.rs
  function set_current_reporter (line 18) | fn set_current_reporter(reporter: Option<&Arc<ProgressReporter>>) {
  function suspend (line 27) | pub(crate) fn suspend(f: impl FnOnce() + Send + 'static) {
  type BarState (line 36) | struct BarState {
    method id (line 45) | fn id(&mut self) -> usize {
  type ProgressReporter (line 51) | struct ProgressReporter {
    method new (line 59) | fn new(root: ProgressBar, children: MultiProgress, printer: Printer) -...
    method on_start (line 68) | fn on_start(&self, msg: impl Into<Cow<'static, str>>) -> usize {
    method on_progress (line 84) | fn on_progress(&self, id: usize) {
    method on_complete (line 94) | fn on_complete(&self) {
    method from (line 101) | fn from(printer: Printer) -> Self {
  type HookInitReporter (line 115) | pub(crate) struct HookInitReporter {
    method new (line 120) | pub(crate) fn new(printer: Printer) -> Self {
    method on_clone_start (line 128) | fn on_clone_start(&self, repo: &str) -> usize {
    method on_clone_complete (line 137) | fn on_clone_complete(&self, id: usize) {
    method on_complete (line 141) | fn on_complete(&self) {
  type HookInstallReporter (line 146) | pub(crate) struct HookInstallReporter {
    method new (line 151) | pub(crate) fn new(printer: Printer) -> Self {
    method on_install_start (line 159) | pub fn on_install_start(&self, hook: &Hook) -> usize {
    method on_install_complete (line 171) | pub fn on_install_complete(&self, id: usize) {
    method on_complete (line 175) | pub fn on_complete(&self) {
  type HookRunReporter (line 180) | pub(crate) struct HookRunReporter {
    method new (line 186) | pub fn new(printer: Printer, dots: usize) -> Self {
    method on_run_start (line 193) | pub fn on_run_start(&self, hook: &Hook, len: usize) -> usize {
    method on_run_progress (line 220) | pub fn on_run_progress(&self, id: usize, completed: u64) {
    method on_run_complete (line 226) | pub fn on_run_complete(&self, id: usize) {
    method suspend (line 241) | pub fn suspend<R>(&self, f: impl FnOnce() -> R) -> R {
    method on_complete (line 245) | pub fn on_complete(&self) {
  type AutoUpdateReporter (line 251) | pub(crate) struct AutoUpdateReporter {
    method new (line 256) | pub(crate) fn new(printer: Printer) -> Self {
    method on_update_start (line 264) | pub fn on_update_start(&self, repo: &str) -> usize {
    method on_update_complete (line 273) | pub fn on_update_complete(&self, id: usize) {
    method on_complete (line 277) | pub fn on_complete(&self) {
  type CleaningReporter (line 283) | pub(crate) struct CleaningReporter {
    method new (line 288) | pub(crate) fn new(printer: Printer, max: usize) -> Self {
    method on_clean (line 301) | pub(crate) fn on_clean(&self) {
    method on_complete (line 305) | pub(crate) fn on_complete(&self) {

FILE: crates/prek/src/cli/run/filter.rs
  type FilenameFilter (line 19) | pub(crate) struct FilenameFilter<'a> {
  function new (line 25) | pub(crate) fn new(include: Option<&'a FilePattern>, exclude: Option<&'a ...
  function filter (line 29) | pub(crate) fn filter(&self, filename: &Path) -> bool {
  type FileTagFilter (line 48) | pub(crate) struct FileTagFilter<'a> {
  function new (line 55) | fn new(
  function filter (line 67) | pub(crate) fn filter(&self, file_types: &TagSet) -> bool {
  type FileFilter (line 84) | pub(crate) struct FileFilter<'a> {
  function for_project (line 93) | pub(crate) fn for_project<I>(
  function len (line 143) | pub(crate) fn len(&self) -> usize {
  function by_type (line 148) | pub(crate) fn by_type(
  function for_hook (line 173) | pub(crate) fn for_hook(&self, hook: &Hook) -> Vec<&Path> {
  type CollectOptions (line 213) | pub(crate) struct CollectOptions {
    method all_files (line 224) | pub(crate) fn all_files() -> Self {
  function collect_files (line 235) | pub(crate) async fn collect_files(root: &Path, opts: CollectOptions) -> ...
  function adjust_relative_path (line 290) | fn adjust_relative_path(path: &str, new_cwd: &Path) -> Result<PathBuf, s...
  function collect_files_from_args (line 298) | async fn collect_files_from_args(
  function glob_pattern (line 401) | fn glob_pattern(pattern: &str) -> FilePattern {
  function filename_filter_supports_glob_include_and_exclude (line 406) | fn filename_filter_supports_glob_include_and_exclude() {

FILE: crates/prek/src/cli/run/keeper.rs
  type IntentToAddKeeper (line 19) | struct IntentToAddKeeper(Vec<PathBuf>);
    method clean (line 26) | async fn clean(root: &Path) -> Result<Self> {
    method restore (line 47) | fn restore(&self) -> Result<()> {
  type WorkingTreeKeeper (line 20) | struct WorkingTreeKeeper {
    method clean (line 76) | async fn clean(root: &Path, patch_dir: &Path) -> Result<Self> {
    method checkout_working_tree (line 146) | fn checkout_working_tree(root: &Path) -> Result<()> {
    method git_apply (line 165) | fn git_apply(patch: &Path) -> Result<()> {
    method restore (line 178) | fn restore(&self) -> Result<()> {
  method drop (line 65) | fn drop(&mut self) {
  method drop (line 211) | fn drop(&mut self) {
  type WorkTreeKeeper (line 222) | pub struct WorkTreeKeeper {
    method clean (line 243) | pub async fn clean(store: &Store, root: &Path) -> Result<RestoreGuard> {
    method restore (line 263) | fn restore(&mut self) {
  type RestoreGuard (line 228) | pub struct RestoreGuard {
  method drop (line 233) | fn drop(&mut self) {

FILE: crates/prek/src/cli/run/run.rs
  function run (line 35) | pub(crate) async fn run(
  function set_env_vars (line 218) | fn set_env_vars(from_ref: Option<&String>, to_ref: Option<&String>, args...
  type LazyInstallInfo (line 267) | struct LazyInstallInfo {
    method new (line 273) | fn new(info: Arc<InstallInfo>) -> Self {
    method matches (line 280) | fn matches(&self, hook: &Hook) -> bool {
    method info (line 284) | fn info(&self) -> Arc<InstallInfo> {
    method ensure_healthy (line 288) | async fn ensure_healthy(&self) -> bool {
  function install_hooks (line 307) | pub async fn install_hooks(
  function partition_hooks (line 442) | fn partition_hooks(hooks: &[Arc<Hook>]) -> Vec<Vec<Arc<Hook>>> {
  type StatusPrinter (line 489) | struct StatusPrinter {
    constant PASSED (line 495) | const PASSED: &'static str = "Passed";
    constant FAILED (line 496) | const FAILED: &'static str = "Failed";
    constant SKIPPED (line 497) | const SKIPPED: &'static str = "Skipped";
    constant DRY_RUN (line 498) | const DRY_RUN: &'static str = "Dry Run";
    constant NO_FILES (line 499) | const NO_FILES: &'static str = "(no files to check)";
    constant UNIMPLEMENTED (line 500) | const UNIMPLEMENTED: &'static str = "(unimplemented yet)";
    method for_hooks (line 502) | fn for_hooks(hooks: &[InstalledHook], printer: Printer) -> Self {
    method printer (line 516) | fn printer(&self) -> Printer {
    method bar_len (line 520) | fn bar_len(&self) -> usize {
    method write (line 524) | fn write(
  function run_hooks (line 575) | async fn run_hooks(
  type PriorityGroupRanges (line 739) | struct PriorityGroupRanges<'a> {
  function new (line 745) | fn new(hooks: &'a [InstalledHook]) -> Self {
  type Item (line 751) | type Item = std::ops::Range<usize>;
  method next (line 753) | fn next(&mut self) -> Option<Self::Item> {
  function run_priority_group (line 769) | async fn run_priority_group(
  function render_priority_group (line 797) | fn render_priority_group(
  function apply_group_outcome (line 920) | fn apply_group_outcome(
  function shuffle (line 948) | fn shuffle<T>(filenames: &mut [T]) {
  type RunStatus (line 955) | enum RunStatus {
    method as_bool (line 964) | fn as_bool(self) -> bool {
    method is_unimplemented (line 971) | fn is_unimplemented(self) -> bool {
    method is_skipped (line 975) | fn is_skipped(self) -> bool {
  type RunResult (line 980) | struct RunResult {
    method from_status (line 989) | fn from_status(hook: InstalledHook, status: RunStatus) -> Self {
  function run_hook (line 1000) | async fn run_hook(
  function status_printer_write_dots_saturates_instead_of_underflow (line 1075) | fn status_printer_write_dots_saturates_instead_of_underflow() {

FILE: crates/prek/src/cli/run/selector.rs
  type Error (line 17) | pub(crate) enum Error {
  type SelectorSource (line 34) | pub(crate) enum SelectorSource {
  type SelectorExpr (line 41) | pub(crate) enum SelectorExpr {
  type Selector (line 51) | pub(crate) struct Selector {
    method as_flag (line 83) | pub(crate) fn as_flag(&self) -> Cow<'_, str> {
    method as_normalized_flag (line 91) | pub(crate) fn as_normalized_flag(&self) -> String {
    method source (line 99) | pub(crate) fn source(&self) -> &SelectorSource {
    method kind_str (line 103) | pub(crate) fn kind_str(&self) -> &'static str {
    method matches_hook (line 112) | pub(crate) fn matches_hook(&self, hook: &Hook) -> bool {
  method fmt (line 58) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Selectors (line 135) | pub(crate) struct Selectors {
    method load (line 143) | pub(crate) fn load(
    method includes (line 188) | pub(crate) fn includes(&self) -> &[Selector] {
    method skips (line 192) | pub(crate) fn skips(&self) -> &[Selector] {
    method has_project_selectors (line 196) | pub(crate) fn has_project_selectors(&self) -> bool {
    method includes_only_hook_targets (line 205) | pub(crate) fn includes_only_hook_targets(&self) -> bool {
    method matches_hook (line 216) | pub(crate) fn matches_hook(&self, hook: &Hook) -> bool {
    method matches_hook_id (line 245) | pub(crate) fn matches_hook_id(&self, hook_id: &str) -> bool {
    method matches_path (line 278) | pub(crate) fn matches_path(&self, path: &Path) -> bool {
    method report_unused (line 315) | pub(crate) fn report_unused(&self) {
  type SelectorUsage (line 322) | struct SelectorUsage {
    method use_include (line 328) | fn use_include(&mut self, idx: usize) {
    method use_skip (line 332) | fn use_skip(&mut self, idx: usize) {
    method report_unused (line 336) | fn report_unused(&self, selectors: &Selectors) {
  function parse_single_selector (line 395) | fn parse_single_selector<FS: FileSystem>(
  type FileSystem (line 464) | pub trait FileSystem: Copy {
    method absolute (line 465) | fn absolute<P: AsRef<Path>>(&self, path: P) -> std::io::Result<PathBuf>;
    method absolute (line 472) | fn absolute<P: AsRef<Path>>(&self, path: P) -> std::io::Result<PathBuf> {
    method absolute (line 562) | fn absolute<P: AsRef<Path>>(&self, path: P) -> std::io::Result<PathBuf> {
  type RealFileSystem (line 469) | pub struct RealFileSystem;
  function normalize_path (line 491) | fn normalize_path<FS: FileSystem>(
  function load_skips (line 513) | pub(crate) fn load_skips<FS: FileSystem>(
  function parse_comma_separated (line 548) | fn parse_comma_separated(input: &str) -> impl Iterator<Item = &str> {
  type MockFileSystem (line 557) | struct MockFileSystem {
    method root (line 573) | fn root(&self) -> &Path {
  function create_test_workspace (line 578) | fn create_test_workspace() -> anyhow::Result<MockFileSystem> {
  function test_parse_single_selector_hook_id (line 590) | fn test_parse_single_selector_hook_id() -> anyhow::Result<()> {
  function test_parse_single_selector_project_prefix (line 608) | fn test_parse_single_selector_project_prefix() -> anyhow::Result<()> {
  function test_parse_single_selector_project_hook (line 631) | fn test_parse_single_selector_project_hook() -> anyhow::Result<()> {
  function test_parse_single_selector_invalid (line 663) | fn test_parse_single_selector_invalid() -> anyhow::Result<()> {
  function test_normalize_path (line 682) | fn test_normalize_path() -> anyhow::Result<()> {
  function test_selector_display (line 707) | fn test_selector_display() -> anyhow::Result<()> {
  function test_selector_as_flag (line 753) | fn test_selector_as_flag() {

FILE: crates/prek/src/cli/sample_config.rs
  function sample_config (line 40) | pub(crate) fn sample_config(

FILE: crates/prek/src/cli/self_update.rs
  function format_install_hint (line 35) | fn format_install_hint() -> String {
  function self_update (line 53) | pub(crate) async fn self_update(

FILE: crates/prek/src/cli/try_repo.rs
  function get_head_rev (line 20) | async fn get_head_rev(repo: &Path) -> Result<String> {
  function clone_and_commit (line 32) | async fn clone_and_commit(repo_path: &Path, head_rev: &str, tmp_dir: &Pa...
  function prepare_repo_and_rev (line 93) | async fn prepare_repo_and_rev<'a>(
  function render_repo_config_toml (line 137) | fn render_repo_config_toml(repo_path: &str, rev: &str, hooks: Vec<String...
  function try_repo (line 162) | pub(crate) async fn try_repo(

FILE: crates/prek/src/cli/validate.rs
  function validate_configs (line 14) | pub(crate) fn validate_configs(configs: Vec<PathBuf>, printer: Printer) ...
  function validate_manifest (line 48) | pub(crate) fn validate_manifest(manifests: Vec<PathBuf>, printer: Printe...

FILE: crates/prek/src/cli/yaml_to_toml.rs
  function resolve_input (line 17) | fn resolve_input(input: Option<PathBuf>) -> Result<PathBuf> {
  function yaml_to_toml (line 42) | pub(crate) fn yaml_to_toml(
  function json_to_toml (line 105) | fn json_to_toml(value: &serde_json::Value) -> Result<String> {
  function json_to_toml_value (line 130) | fn json_to_toml_value(value: &serde_json::Value) -> Value {
  function json_array_to_value_with_indent (line 151) | fn json_array_to_value_with_indent(
  function json_object_to_inline (line 180) | fn json_object_to_inline(values: &serde_json::Map<String, serde_json::Va...
  function format_inline_table_multiline (line 195) | fn format_inline_table_multiline(table: &mut InlineTable, base_indent: &...
  function repos_to_array_of_tables (line 220) | fn repos_to_array_of_tables(values: &[serde_json::Value]) -> Result<Arra...

FILE: crates/prek/src/config.rs
  type GlobPatterns (line 26) | pub(crate) struct GlobPatterns {
    method new (line 32) | pub(crate) fn new(patterns: Vec<String>) -> Result<Self, globset::Erro...
    method is_match (line 41) | fn is_match(&self, value: &str) -> bool {
    method fmt (line 47) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type FilePatternWire (line 54) | enum FilePatternWire {
    method deserialize (line 61) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  type FilePatternWireError (line 166) | enum FilePatternWireError {
  type FilePattern (line 176) | pub(crate) enum FilePattern {
    method new_glob (line 182) | pub(crate) fn new_glob(patterns: Vec<String>) -> Result<Self, globset:...
    method new_regex (line 186) | pub(crate) fn new_regex(pattern: &str) -> Result<Self, fancy_regex::Er...
    method is_match (line 190) | pub(crate) fn is_match(&self, str: &str) -> bool {
    type Error (line 211) | type Error = FilePatternWireError;
    method try_from (line 213) | fn try_from(value: FilePatternWire) -> Result<Self, Self::Error> {
  method fmt (line 199) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Language (line 239) | pub enum Language {
  type HookType (line 273) | pub(crate) enum HookType {
    method num_args (line 289) | pub fn num_args(self) -> RangeInclusive<usize> {
  type Stage (line 324) | pub(crate) enum Stage {
    method from (line 343) | fn from(value: HookType) -> Self {
    method operate_on_files (line 360) | pub fn operate_on_files(self) -> bool {
  type Stages (line 374) | pub(crate) enum Stages {
    method is_empty (line 380) | pub(crate) fn is_empty(&self) -> bool {
    method contains (line 384) | pub(crate) fn contains(&self, stage: Stage) -> bool {
    method to_vec (line 391) | pub(crate) fn to_vec(&self) -> Vec<Stage> {
    method from (line 416) | fn from(value: Vec<Stage>) -> Self {
    method from (line 427) | fn from(value: [Stage; N]) -> Self {
    method deserialize (line 433) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  method fmt (line 400) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type PassFilenames (line 444) | pub(crate) enum PassFilenames {
    method deserialize (line 456) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  type HookOptions (line 507) | pub(crate) struct HookOptions {
    method update (line 566) | pub fn update(&mut self, other: &Self) {
  type ManifestHook (line 612) | pub(crate) struct ManifestHook {
  type Manifest (line 628) | pub(crate) struct Manifest {
  type RemoteHook (line 638) | pub(crate) struct RemoteHook {
  type LocalHook (line 663) | pub(crate) struct LocalHook {
  type MetaHook (line 685) | pub(crate) struct MetaHook {
    type Error (line 728) | type Error = PredefinedHookWireError;
    method try_from (line 730) | fn try_from(hook_options: RemoteHook) -> Result<Self, Self::Error> {
  type PredefinedHookWireError (line 698) | pub(crate) enum PredefinedHookWireError {
  type PredefinedHookKind (line 713) | pub(crate) enum PredefinedHookKind {
  method fmt (line 719) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type BuiltinHook (line 765) | pub(crate) struct BuiltinHook {
    type Error (line 785) | type Error = PredefinedHookWireError;
    method try_from (line 787) | fn try_from(hook_options: RemoteHook) -> Result<Self, Self::Error> {
  type RemoteRepo (line 820) | pub(crate) struct RemoteRepo {
    method new (line 832) | pub fn new(repo: String, rev: String, hooks: Vec<RemoteHook>) -> Self {
    method hash (line 851) | fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
  method eq (line 843) | fn eq(&self, other: &Self) -> bool {
  method fmt (line 858) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type LocalRepo (line 865) | pub(crate) struct LocalRepo {
  method fmt (line 875) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type MetaRepo (line 882) | pub(crate) struct MetaRepo {
  method fmt (line 892) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type BuiltinRepo (line 899) | pub(crate) struct BuiltinRepo {
  type Repo (line 909) | pub(crate) enum Repo {
    method deserialize (line 917) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  function remote_hook_to_local (line 1056) | fn remote_hook_to_local<E>(hook: RemoteHook) -> Result<LocalHook, E>
  type Config (line 1081) | pub(crate) struct Config {
  type Error (line 1113) | pub(crate) enum Error {
    method warn_parse_error (line 1126) | pub(crate) fn warn_parse_error(&self) {
  constant EXPECTED_UNUSED (line 1140) | const EXPECTED_UNUSED: &[&str] = &["minimum_pre_commit_version", "ci"];
  function push_unused_paths (line 1142) | fn push_unused_paths<'a, I>(acc: &mut Vec<String>, prefix: &str, keys: I)
  function collect_unused_paths (line 1156) | fn collect_unused_paths(config: &Config) -> Vec<String> {
  function warn_unused_paths (line 1208) | fn warn_unused_paths(path: &Path, entries: &[String]) {
  function load_config (line 1235) | pub(crate) fn load_config(path: &Path) -> Result<Config, Error> {
  function read_config (line 1249) | pub(crate) fn read_config(path: &Path) -> Result<Config, Error> {
  function read_manifest (line 1295) | pub(crate) fn read_manifest(path: &Path) -> Result<Manifest, Error> {
  function looks_like_sha (line 1304) | fn looks_like_sha(s: &str) -> bool {
  function deserialize_and_validate_minimum_version (line 1308) | fn deserialize_and_validate_minimum_version<'de, D>(
  constant VERSION_FILTER (line 1345) | const VERSION_FILTER: (&str, &str) = (
  function stages_deserialize_empty_as_empty (line 1351) | fn stages_deserialize_empty_as_empty() {
  function config_default_stages_deserialize_empty_as_empty (line 1364) | fn config_default_stages_deserialize_empty_as_empty() {
  function config_default_stages_omitted_keeps_none (line 1372) | fn config_default_stages_omitted_keeps_none() {
  function stages_deserialize_to_subset (line 1379) | fn stages_deserialize_to_subset() {
  function parse_file_patterns_regex_and_glob (line 1393) | fn parse_file_patterns_regex_and_glob() {
  function file_patterns_expose_sources_and_display (line 1451) | fn file_patterns_expose_sources_and_display() {
  function empty_glob_list_matches_nothing (line 1468) | fn empty_glob_list_matches_nothing() {
  function invalid_glob_pattern_errors (line 1475) | fn invalid_glob_pattern_errors() {
  function parse_repos (line 1486) | fn parse_repos() {
  function parse_hooks (line 1639) | fn parse_hooks() {
  function meta_hooks (line 1698) | fn meta_hooks() {
  function language_version (line 1793) | fn language_version() {
  function test_read_yaml_config (line 1819) | fn test_read_yaml_config() -> Result<()> {
  function test_read_toml_config (line 1826) | fn test_read_toml_config() -> Result<()> {
  function test_read_invalid_toml_config (line 1863) | fn test_read_invalid_toml_config() {
  function test_read_manifest (line 1932) | fn test_read_manifest() -> Result<()> {
  function test_minimum_prek_version (line 1939) | fn test_minimum_prek_version() {
  function test_validate_type_tags (line 2015) | fn test_validate_type_tags() {
  function read_config_with_merge_keys (line 2128) | fn read_config_with_merge_keys() -> Result<()> {
  function read_config_with_nested_merge_keys (line 2155) | fn read_config_with_nested_merge_keys() -> Result<()> {
  function test_list_with_unindented_square (line 2185) | fn test_list_with_unindented_square() {
  function test_numeric_rev_is_parsed_as_string (line 2210) | fn test_numeric_rev_is_parsed_as_string() {
  function pass_filenames_zero_is_rejected (line 2225) | fn pass_filenames_zero_is_rejected() {
  function pass_filenames_negative_is_rejected (line 2241) | fn pass_filenames_negative_is_rejected() {
  function pass_filenames_string_is_rejected (line 2257) | fn pass_filenames_string_is_rejected() {

FILE: crates/prek/src/fs.rs
  type LockedFile (line 54) | pub struct LockedFile {
    method lock_file_blocking (line 61) | fn lock_file_blocking(
    method acquire (line 100) | pub async fn acquire(
  method drop (line 175) | fn drop(&mut self) {
  function normalize_path (line 198) | pub(crate) fn normalize_path(path: PathBuf) -> PathBuf {
  function normalize_path (line 206) | pub(crate) fn normalize_path(path: PathBuf) -> PathBuf {
  function relative_to (line 235) | pub fn relative_to(
  type Simplified (line 265) | pub trait Simplified {
    method simplified (line 269) | fn simplified(&self) -> &Path;
    method simplified_display (line 275) | fn simplified_display(&self) -> impl Display;
    method user_display (line 280) | fn user_display(&self) -> impl Display;
    method simplified (line 284) | fn simplified(&self) -> &Path {
    method simplified_display (line 288) | fn simplified_display(&self) -> impl Display {
    method user_display (line 292) | fn user_display(&self) -> impl Display {
  function lock_warning_suppressed_for_in_process_contention (line 313) | async fn lock_warning_suppressed_for_in_process_contention() {
  function lock_warning_emitted_when_forced_cross_process (line 355) | async fn lock_warning_emitted_when_forced_cross_process() {

FILE: crates/prek/src/git.rs
  type Error (line 19) | pub(crate) enum Error {
  function git_cmd (line 72) | pub(crate) fn git_cmd(summary: &str) -> Result<Cmd, Error> {
  function zsplit (line 79) | fn zsplit(s: &[u8]) -> Result<Vec<PathBuf>, Utf8Error> {
  function intent_to_add_files (line 86) | pub(crate) async fn intent_to_add_files(root: &Path) -> Result<Vec<PathB...
  function get_added_files (line 102) | pub(crate) async fn get_added_files(root: &Path) -> Result<Vec<PathBuf>,...
  function get_changed_files (line 116) | pub(crate) async fn get_changed_files(
  function ls_files (line 153) | pub(crate) async fn ls_files(cwd: &Path, path: &Path) -> Result<Vec<Path...
  function get_git_dir (line 167) | pub(crate) async fn get_git_dir() -> Result<PathBuf, Error> {
  function get_git_common_dir (line 179) | pub(crate) async fn get_git_common_dir() -> Result<PathBuf, Error> {
  function get_staged_files (line 195) | pub(crate) async fn get_staged_files(root: &Path) -> Result<Vec<PathBuf>...
  function files_not_staged (line 210) | pub(crate) async fn files_not_staged(files: &[&Path]) -> Result<Vec<Path...
  function has_unmerged_paths (line 229) | pub(crate) async fn has_unmerged_paths() -> Result<bool, Error> {
  function has_diff (line 239) | pub(crate) async fn has_diff(rev: &str, path: &Path) -> Result<bool> {
  function is_in_merge_conflict (line 251) | pub(crate) async fn is_in_merge_conflict() -> Result<bool, Error> {
  function get_conflicted_files (line 256) | pub(crate) async fn get_conflicted_files(root: &Path) -> Result<Vec<Path...
  function parse_merge_msg_for_conflicts (line 286) | async fn parse_merge_msg_for_conflicts() -> Result<Vec<PathBuf>, Error> {
  function get_diff (line 302) | pub(crate) async fn get_diff(path: &Path) -> Result<Vec<u8>, Error> {
  function write_tree (line 320) | pub(crate) async fn write_tree() -> Result<String, Error> {
  function get_root (line 333) | pub(crate) fn get_root() -> Result<PathBuf, Error> {
  function init_repo (line 354) | pub(crate) async fn init_repo(url: &str, path: &Path) -> Result<(), Erro...
  type TerminalPrompt (line 394) | pub(crate) enum TerminalPrompt {
    method env_value (line 400) | fn env_value(self) -> &'static str {
  function is_auth_error (line 409) | pub(crate) fn is_auth_error(err: &Error) -> bool {
  function shallow_clone (line 436) | async fn shallow_clone(
  function full_clone (line 487) | async fn full_clone(rev: &str, path: &Path, terminal_prompt: TerminalPro...
  function clone_repo_attempt (line 528) | async fn clone_repo_attempt(
  function clone_repo (line 547) | pub(crate) async fn clone_repo(
  function has_hooks_path_set (line 557) | pub(crate) async fn has_hooks_path_set() -> Result<bool> {
  function shared_repository_file_mode (line 576) | fn shared_repository_file_mode(value: &str, mode: u32) -> Option<u32> {
  function get_shared_repository_file_mode (line 621) | pub(crate) async fn get_shared_repository_file_mode(mode: u32) -> Result...
  function get_lfs_files (line 637) | pub(crate) async fn get_lfs_files(paths: &[&Path]) -> Result<FxHashSet<P...
  function rev_exists (line 699) | pub(crate) async fn rev_exists(rev: &str) -> Result<bool, Error> {
  function get_ancestors_not_in_remote (line 712) | pub(crate) async fn get_ancestors_not_in_remote(
  function get_root_commits (line 734) | pub(crate) async fn get_root_commits(local_sha: &str) -> Result<FxHashSe...
  function get_parent_commit (line 750) | pub(crate) async fn get_parent_commit(commit: &str) -> Result<Option<Str...
  function list_submodules (line 768) | pub(crate) fn list_submodules(git_root: &Path) -> Result<Vec<PathBuf>, E...
  function shared_repository_group_mode_matches_git_behavior (line 796) | fn shared_repository_group_mode_matches_git_behavior() {
  function shared_repository_everybody_mode_matches_git_behavior (line 803) | fn shared_repository_everybody_mode_matches_git_behavior() {
  function shared_repository_octal_mode_matches_git_behavior (line 810) | fn shared_repository_octal_mode_matches_git_behavior() {
  function shared_repository_umask_or_invalid_values_do_not_override_mode (line 816) | fn shared_repository_umask_or_invalid_values_do_not_override_mode() {

FILE: crates/prek/src/hook.rs
  type Error (line 27) | pub(crate) enum Error {
  type HookSpec (line 51) | pub(crate) struct HookSpec {
    method apply_remote_hook_overrides (line 61) | pub(crate) fn apply_remote_hook_overrides(&mut self, config: &RemoteHo...
    method apply_project_defaults (line 78) | pub(crate) fn apply_project_defaults(&mut self, config: &Config) {
    method from (line 94) | fn from(hook: ManifestHook) -> Self {
    method from (line 107) | fn from(hook: LocalHook) -> Self {
    method from (line 120) | fn from(hook: MetaHook) -> Self {
    method from (line 133) | fn from(hook: BuiltinHook) -> Self {
  type Repo (line 146) | pub(crate) enum Repo {
    method remote (line 167) | pub(crate) fn remote(url: String, rev: String, path: PathBuf) -> Resul...
    method local (line 184) | pub(crate) fn local(hooks: Vec<LocalHook>) -> Self {
    method meta (line 191) | pub(crate) fn meta(hooks: Vec<MetaHook>) -> Self {
    method builtin (line 198) | pub(crate) fn builtin(hooks: Vec<BuiltinHook>) -> Self {
    method path (line 205) | pub(crate) fn path(&self) -> Option<&Path> {
    method get_hook (line 213) | pub(crate) fn get_hook(&self, id: &str) -> Option<&HookSpec> {
  method fmt (line 225) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  type HookBuilder (line 235) | pub(crate) struct HookBuilder {
    method new (line 244) | pub(crate) fn new(
    method check (line 259) | fn check(&self) -> Result<(), Error> {
    method build (line 312) | pub(crate) async fn build(mut self) -> Result<Hook, Error> {
  type Entry (line 396) | pub(crate) struct Entry {
    method new (line 402) | pub(crate) fn new(hook: String, entry: String) -> Self {
    method resolve (line 407) | pub(crate) fn resolve(&self, env_path: Option<&OsStr>) -> Result<Vec<S...
    method split (line 414) | pub(crate) fn split(&self) -> Result<Vec<String>, Error> {
    method raw (line 429) | pub(crate) fn raw(&self) -> &str {
  type Hook (line 436) | pub(crate) struct Hook {
    method project (line 481) | pub(crate) fn project(&self) -> &Project {
    method repo (line 485) | pub(crate) fn repo(&self) -> &Repo {
    method repo_path (line 490) | pub(crate) fn repo_path(&self) -> Option<&Path> {
    method full_id (line 494) | pub(crate) fn full_id(&self) -> String {
    method work_dir (line 504) | pub(crate) fn work_dir(&self) -> &Path {
    method is_remote (line 508) | pub(crate) fn is_remote(&self) -> bool {
    method env_key_dependencies (line 516) | pub(crate) fn env_key_dependencies(&self) -> &FxHashSet<String> {
    method env_key (line 528) | pub(crate) fn env_key(&self) -> Option<HookEnvKeyRef<'_>> {
    method install_dependencies (line 544) | pub(crate) fn install_dependencies(&self) -> Cow<'_, FxHashSet<String>> {
  method fmt (line 471) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  type HookEnvKey (line 556) | pub(crate) struct HookEnvKey {
    method from_hook_spec (line 607) | pub(crate) fn from_hook_spec(
    method matches_install_info (line 647) | pub(crate) fn matches_install_info(&self, info: &InstallInfo) -> bool {
  type HookEnvKeyRef (line 565) | pub(crate) struct HookEnvKeyRef<'a> {
  function env_key_dependencies (line 575) | fn env_key_dependencies(
  function matches_install_info (line 592) | fn matches_install_info(
  function matches_install_info (line 659) | pub(crate) fn matches_install_info(&self, info: &InstallInfo) -> bool {
  type InstalledHook (line 670) | pub(crate) enum InstalledHook {
    method env_path (line 700) | pub(crate) fn env_path(&self) -> Option<&Path> {
    method toolchain_dir (line 708) | pub(crate) fn toolchain_dir(&self) -> Option<&Path> {
    method install_info (line 716) | pub(crate) fn install_info(&self) -> Option<&InstallInfo> {
    method mark_as_installed (line 724) | pub(crate) async fn mark_as_installed(&self, _store: &Store) -> Result...
  type Target (line 679) | type Target = Hook;
  method deref (line 681) | fn deref(&self) -> &Self::Target {
  method fmt (line 690) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  constant HOOK_MARKER (line 696) | pub(crate) const HOOK_MARKER: &str = ".prek-hook.json";
  type InstallInfo (line 741) | pub(crate) struct InstallInfo {
    method new (line 767) | pub(crate) fn new(
    method persist_env_path (line 788) | pub(crate) fn persist_env_path(&mut self) {
    method from_env_path (line 794) | pub(crate) async fn from_env_path(path: &Path) -> Result<Self> {
    method check_health (line 801) | pub(crate) async fn check_health(&self) -> Result<()> {
    method with_language_version (line 805) | pub(crate) fn with_language_version(&mut self, version: semver::Versio...
    method with_toolchain (line 810) | pub(crate) fn with_toolchain(&mut self, toolchain: PathBuf) -> &mut Se...
    method with_extra (line 815) | pub(crate) fn with_extra(&mut self, key: &str, value: &str) -> &mut Se...
    method get_extra (line 820) | pub(crate) fn get_extra(&self, key: &str) -> Option<&String> {
    method matches (line 824) | pub(crate) fn matches(&self, hook: &Hook) -> bool {
  method clone (line 753) | fn clone(&self) -> Self {
  function hook_builder_build_fills_and_merges_attributes (line 849) | async fn hook_builder_build_fills_and_merges_attributes() -> Result<()> {
  function hook_builder_empty_hook_stages_inherit_default_stages (line 1004) | async fn hook_builder_empty_hook_stages_inherit_default_stages() -> Resu...
  function hook_spec_apply_project_defaults_sets_explicit_all_when_default_stages_missing (line 1039) | fn hook_spec_apply_project_defaults_sets_explicit_all_when_default_stage...
  function hook_builder_preserves_explicit_empty_default_stages (line 1057) | async fn hook_builder_preserves_explicit_empty_default_stages() -> Resul...
  function hook_builder_defaults_to_all_when_stages_and_default_stages_missing (line 1086) | async fn hook_builder_defaults_to_all_when_stages_and_default_stages_mis...
  function hook_builder_empty_hook_stages_default_to_all_when_default_stages_missing (line 1115) | async fn hook_builder_empty_hook_stages_default_to_all_when_default_stag...
  function setup_python_hook_test (line 1149) | fn setup_python_hook_test() -> Result<(tempfile::TempDir, Arc<Project>)> {
  function build_python_hook (line 1166) | async fn build_python_hook(
  function hook_builder_python_pep723_overrides_user_and_pyproject (line 1203) | async fn hook_builder_python_pep723_overrides_user_and_pyproject() -> Re...
  function hook_builder_python_user_language_version_overrides_pyproject (line 1222) | async fn hook_builder_python_user_language_version_overrides_pyproject()...
  function hook_builder_python_pep723_overrides_pyproject_without_user_version (line 1241) | async fn hook_builder_python_pep723_overrides_pyproject_without_user_ver...
  function hook_builder_python_defaults_to_any_without_version_sources (line 1260) | async fn hook_builder_python_defaults_to_any_without_version_sources() -...
  function hook_builder_python_pyproject_provides_version_when_no_other_source (line 1272) | async fn hook_builder_python_pyproject_provides_version_when_no_other_so...

FILE: crates/prek/src/hooks/builtin_hooks/check_json5.rs
  function check_json5 (line 8) | pub(crate) async fn check_json5(
  function check_file (line 18) | async fn check_file(file_base: &Path, filename: &Path) -> anyhow::Result...
  function create_test_file (line 40) | async fn create_test_file(
  function test_valid_json5 (line 51) | async fn test_valid_json5() -> anyhow::Result<()> {
  function test_duplicate_keys (line 78) | async fn test_duplicate_keys() -> anyhow::Result<()> {
  function test_invalid_json5 (line 98) | async fn test_invalid_json5() -> anyhow::Result<()> {

FILE: crates/prek/src/hooks/builtin_hooks/mod.rs
  type BuiltinHooks (line 29) | pub(crate) enum BuiltinHooks {
    method run (line 49) | pub(crate) async fn run(
  method from_id (line 91) | pub(crate) fn from_id(id: &str) -> Result<Self, ()> {

FILE: crates/prek/src/hooks/meta_hooks.rs
  type MetaHooks (line 27) | pub(crate) enum MetaHooks {
    method run (line 34) | pub(crate) async fn run(
  method from_id (line 53) | pub(crate) fn from_id(id: &str) -> Result<Self, ()> {
  function check_hooks_apply (line 92) | pub(crate) async fn check_hooks_apply(
  function excludes_any (line 139) | fn excludes_any(
  function check_useless_excludes (line 168) | pub(crate) async fn check_useless_excludes(
  function identity (line 257) | pub fn identity(_hook: &Hook, filenames: &[&Path]) -> (i32, Vec<u8>) {
  function regex_pattern (line 273) | fn regex_pattern(pattern: &str) -> FilePattern {
  function test_excludes_any (line 278) | fn test_excludes_any() {
  function meta_hook_patterns_cover_config_files (line 299) | fn meta_hook_patterns_cover_config_files() {

FILE: crates/prek/src/hooks/mod.rs
  function check_fast_path (line 22) | pub fn check_fast_path(hook: &Hook) -> bool {
  function run_fast_path (line 38) | pub async fn run_fast_path(
  function run_concurrent_file_checks (line 61) | pub(crate) async fn run_concurrent_file_checks<'a, I, F, Fut>(

FILE: crates/prek/src/hooks/pre_commit_hooks/check_added_large_files.rs
  type FileFilter (line 11) | enum FileFilter {
    method contains (line 17) | fn contains(&self, path: &Path) -> bool {
  type Args (line 29) | struct Args {
  function check_added_large_files (line 36) | pub(crate) async fn check_added_large_files(

FILE: crates/prek/src/hooks/pre_commit_hooks/check_case_conflict.rs
  function check_case_conflict (line 11) | pub(crate) async fn check_case_conflict(
  function insert_path_and_parents (line 99) | fn insert_path_and_parents<'p>(set: &mut FxHashSet<&'p Path>, file: &'p ...
  function lower_key (line 112) | fn lower_key(path: &Path) -> String {
  function test_insert_path_and_parents (line 121) | fn test_insert_path_and_parents() {
  function test_insert_path_and_parents_nested (line 136) | fn test_insert_path_and_parents_nested() {
  function test_insert_path_and_parents_no_slash (line 152) | fn test_insert_path_and_parents_no_slash() {
  function test_lower_key (line 159) | fn test_lower_key() {

FILE: crates/prek/src/hooks/pre_commit_hooks/check_executables_have_shebangs.rs
  function check_executables_have_shebangs (line 13) | pub(crate) async fn check_executables_have_shebangs(
  function os_check_shebangs (line 40) | async fn os_check_shebangs(
  function print_shebang_warning (line 57) | fn print_shebang_warning(path: &Path) -> String {
  function git_check_shebangs (line 76) | async fn git_check_shebangs(
  function file_has_shebang (line 147) | async fn file_has_shebang(path: &Path) -> Result<bool, anyhow::Error> {
  function test_file_with_shebang (line 160) | async fn test_file_with_shebang() -> Result<(), anyhow::Error> {
  function test_file_without_shebang (line 169) | async fn test_file_without_shebang() -> Result<(), anyhow::Error> {
  function test_empty_file (line 178) | async fn test_empty_file() -> Result<(), anyhow::Error> {
  function test_file_with_partial_shebang (line 187) | async fn test_file_with_partial_shebang() -> Result<(), anyhow::Error> {
  function test_file_with_shebang_and_spaces (line 195) | async fn test_file_with_shebang_and_spaces() -> Result<(), anyhow::Error> {
  function test_file_with_non_shebang_start (line 203) | async fn test_file_with_non_shebang_start() -> Result<(), anyhow::Error> {
  function test_os_check_shebangs_with_shebang (line 211) | async fn test_os_check_shebangs_with_shebang() -> Result<(), anyhow::Err...
  function test_os_check_shebangs_without_shebang (line 223) | async fn test_os_check_shebangs_without_shebang() -> Result<(), anyhow::...

FILE: crates/prek/src/hooks/pre_commit_hooks/check_json.rs
  type JsonValue (line 12) | pub(crate) enum JsonValue {
    method deserialize (line 66) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  function check_json (line 21) | pub(crate) async fn check_json(hook: &Hook, filenames: &[&Path]) -> Resu...
  function check_file (line 28) | async fn check_file(file_base: &Path, filename: &Path) -> Result<(i32, V...
  function carefully_drop_nested_json (line 53) | fn carefully_drop_nested_json(value: JsonValue) {
  function create_test_file (line 147) | async fn create_test_file(
  function test_valid_json (line 158) | async fn test_valid_json() -> Result<()> {
  function test_invalid_json (line 170) | async fn test_invalid_json() -> Result<()> {
  function test_duplicate_keys (line 182) | async fn test_duplicate_keys() -> Result<()> {
  function test_empty_json (line 194) | async fn test_empty_json() -> Result<()> {
  function test_valid_json_array (line 206) | async fn test_valid_json_array() -> Result<()> {
  function test_duplicate_keys_in_nested_object (line 218) | async fn test_duplicate_keys_in_nested_object() -> Result<()> {
  function test_recursion_limit (line 230) | async fn test_recursion_limit() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/check_merge_conflict.rs
  constant CONFLICT_PATTERNS (line 12) | const CONFLICT_PATTERNS: &[&[u8]] = &[
  type Args (line 24) | struct Args {
  function check_merge_conflict (line 29) | pub(crate) async fn check_merge_conflict(
  function is_in_merge (line 46) | async fn is_in_merge() -> Result<bool> {
  function check_file (line 62) | async fn check_file(file_base: &Path, filename: &Path) -> Result<(i32, V...
  function create_test_file (line 109) | async fn create_test_file(
  function test_no_conflict_markers (line 120) | async fn test_no_conflict_markers() -> Result<()> {
  function test_conflict_marker_start (line 131) | async fn test_conflict_marker_start() -> Result<()> {
  function test_conflict_marker_middle (line 145) | async fn test_conflict_marker_middle() -> Result<()> {
  function test_conflict_marker_end (line 158) | async fn test_conflict_marker_end() -> Result<()> {
  function test_full_conflict_block (line 171) | async fn test_full_conflict_block() -> Result<()> {
  function test_conflict_marker_not_at_start (line 187) | async fn test_conflict_marker_not_at_start() -> Result<()> {
  function test_conflict_marker_crlf (line 199) | async fn test_conflict_marker_crlf() -> Result<()> {
  function test_conflict_marker_lf (line 210) | async fn test_conflict_marker_lf() -> Result<()> {
  function test_empty_file (line 221) | async fn test_empty_file() -> Result<()> {
  function test_multiple_conflicts (line 232) | async fn test_multiple_conflicts() -> Result<()> {
  function test_binary_file_with_conflict (line 246) | async fn test_binary_file_with_conflict() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/check_symlinks.rs
  function check_symlinks (line 9) | pub(crate) async fn check_symlinks(hook: &Hook, filenames: &[&Path]) -> ...
  function check_file (line 17) | async fn check_file(file_base: &Path, filename: &Path) -> Result<(i32, V...
  function create_test_file (line 35) | async fn create_test_file(
  function test_regular_file (line 46) | async fn test_regular_file() -> Result<()> {
  function test_valid_symlink_unix (line 58) | async fn test_valid_symlink_unix() -> Result<()> {
  function test_broken_symlink_unix (line 72) | async fn test_broken_symlink_unix() -> Result<()> {
  function test_valid_symlink_windows (line 88) | async fn test_valid_symlink_windows() -> Result<()> {
  function test_broken_symlink_windows (line 107) | async fn test_broken_symlink_windows() -> Result<()> {
  function test_valid_symlink_macos (line 132) | async fn test_valid_symlink_macos() -> Result<()> {
  function test_broken_symlink_macos (line 146) | async fn test_broken_symlink_macos() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/check_toml.rs
  function check_toml (line 9) | pub(crate) async fn check_toml(hook: &Hook, filenames: &[&Path]) -> Resu...
  function check_file (line 16) | async fn check_file(file_base: &Path, filename: &Path) -> Result<(i32, V...
  function create_test_file (line 54) | async fn create_test_file(
  function test_valid_toml (line 65) | async fn test_valid_toml() -> Result<()> {
  function test_invalid_toml (line 78) | async fn test_invalid_toml() -> Result<()> {
  function test_duplicate_keys (line 91) | async fn test_duplicate_keys() -> Result<()> {
  function test_empty_toml (line 104) | async fn test_empty_toml() -> Result<()> {
  function test_multiple_errors_reported (line 115) | async fn test_multiple_errors_reported() -> Result<()> {
  function test_invalid_utf8 (line 136) | async fn test_invalid_utf8() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/check_xml.rs
  function check_xml (line 9) | pub(crate) async fn check_xml(hook: &Hook, filenames: &[&Path]) -> Resul...
  function check_file (line 16) | async fn check_file(file_base: &Path, filename: &Path) -> Result<(i32, V...
  function create_test_file (line 73) | async fn create_test_file(
  function test_valid_xml (line 84) | async fn test_valid_xml() -> Result<()> {
  function test_invalid_xml_unclosed_tag (line 98) | async fn test_invalid_xml_unclosed_tag() -> Result<()> {
  function test_invalid_xml_mismatched_tags (line 114) | async fn test_invalid_xml_mismatched_tags() -> Result<()> {
  function test_invalid_xml_syntax_error (line 128) | async fn test_invalid_xml_syntax_error() -> Result<()> {
  function test_empty_xml (line 142) | async fn test_empty_xml() -> Result<()> {
  function test_valid_xml_with_attributes (line 155) | async fn test_valid_xml_with_attributes() -> Result<()> {
  function test_valid_xml_with_cdata (line 170) | async fn test_valid_xml_with_cdata() -> Result<()> {
  function test_valid_xml_with_comments (line 184) | async fn test_valid_xml_with_comments() -> Result<()> {
  function test_xml_with_doctype (line 200) | async fn test_xml_with_doctype() -> Result<()> {
  function test_invalid_xml_no_root (line 215) | async fn test_invalid_xml_no_root() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/check_yaml.rs
  type Args (line 14) | struct Args {
  function check_yaml (line 22) | pub(crate) async fn check_yaml(hook: &Hook, filenames: &[&Path]) -> Resu...
  function check_file (line 35) | async fn check_file(
  function create_test_file (line 85) | async fn create_test_file(
  function test_valid_yaml (line 96) | async fn test_valid_yaml() -> Result<()> {
  function test_invalid_yaml (line 109) | async fn test_invalid_yaml() -> Result<()> {
  function test_duplicate_keys (line 122) | async fn test_duplicate_keys() -> Result<()> {
  function test_empty_yaml (line 135) | async fn test_empty_yaml() -> Result<()> {
  function test_multiple_documents (line 146) | async fn test_multiple_documents() -> Result<()> {
  function test_yaml_with_binary_scalar (line 167) | async fn test_yaml_with_binary_scalar() -> Result<()> {
  function test_yaml_with_many_aliases_and_few_anchors (line 191) | async fn test_yaml_with_many_aliases_and_few_anchors() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/detect_private_key.rs
  constant BLACKLIST (line 12) | const BLACKLIST: &[&[u8]] = &[
  constant BUFFER_SIZE (line 24) | const BUFFER_SIZE: usize = 8192;
  constant CARRY_CAPACITY (line 27) | const CARRY_CAPACITY: usize = {
  function detect_private_key (line 44) | pub(crate) async fn detect_private_key(hook: &Hook, filenames: &[&Path])...
  function check_file (line 56) | async fn check_file(file_base: &Path, filename: &Path) -> Result<(i32, V...
  function create_test_file (line 92) | async fn create_test_file(
  function test_no_private_key (line 103) | async fn test_no_private_key() -> Result<()> {
  function test_rsa_private_key (line 114) | async fn test_rsa_private_key() -> Result<()> {
  function test_key_in_middle_of_file (line 127) | async fn test_key_in_middle_of_file() -> Result<()> {
  function test_false_positive_similar_text (line 138) | async fn test_false_positive_similar_text() -> Result<()> {
  function test_empty_file (line 149) | async fn test_empty_file() -> Result<()> {
  function test_binary_file_with_key (line 160) | async fn test_binary_file_with_key() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/fix_byte_order_marker.rs
  constant UTF8_BOM (line 10) | const UTF8_BOM: &[u8] = b"\xef\xbb\xbf";
  constant BUFFER_SIZE (line 11) | const BUFFER_SIZE: usize = 8192;
  function fix_byte_order_marker (line 13) | pub(crate) async fn fix_byte_order_marker(
  function fix_file (line 23) | async fn fix_file(file_base: &Path, filename: &Path) -> Result<(i32, Vec...
  function shift_file_left (line 56) | async fn shift_file_left(file: &mut fs_err::tokio::File, offset: u64) ->...
  function create_test_file (line 84) | async fn create_test_file(
  function test_file_with_bom (line 95) | async fn test_file_with_bom() -> Result<()> {
  function test_file_without_bom (line 113) | async fn test_file_without_bom() -> Result<()> {
  function test_empty_file (line 130) | async fn test_empty_file() -> Result<()> {
  function test_file_shorter_than_bom (line 147) | async fn test_file_shorter_than_bom() -> Result<()> {
  function test_file_with_partial_bom (line 164) | async fn test_file_with_partial_bom() -> Result<()> {
  function test_bom_only_file (line 181) | async fn test_bom_only_file() -> Result<()> {
  function test_utf8_content_with_bom (line 199) | async fn test_utf8_content_with_bom() -> Result<()> {
  function test_large_file_streaming (line 221) | async fn test_large_file_streaming() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/fix_end_of_file.rs
  function fix_end_of_file (line 10) | pub(crate) async fn fix_end_of_file(hook: &Hook, filenames: &[&Path]) ->...
  function fix_file (line 17) | async fn fix_file(file_base: &Path, filename: &Path) -> Result<(i32, Vec...
  function determine_line_ending (line 60) | fn determine_line_ending(first: u8, second: u8) -> Option<&'static str> {
  function find_last_non_ending (line 74) | async fn find_last_non_ending<T>(reader: &mut T) -> Result<(Option<u64>,...
  function create_test_file (line 129) | async fn create_test_file(
  function test_no_line_ending_1 (line 140) | async fn test_no_line_ending_1() -> Result<()> {
  function test_already_has_correct_windows_ending (line 175) | async fn test_already_has_correct_windows_ending() -> Result<()> {
  function test_already_has_correct_unix_ending (line 193) | async fn test_already_has_correct_unix_ending() -> Result<()> {
  function test_empty_file (line 211) | async fn test_empty_file() -> Result<()> {
  function test_excess_newlines_removal (line 229) | async fn test_excess_newlines_removal() -> Result<()> {
  function test_excess_crlf_removal (line 247) | async fn test_excess_crlf_removal() -> Result<()> {
  function test_all_newlines_make_empty (line 265) | async fn test_all_newlines_make_empty() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/fix_trailing_whitespace.rs
  constant MARKDOWN_LINE_BREAK (line 13) | const MARKDOWN_LINE_BREAK: &[u8] = b"  ";
  type Chars (line 16) | struct Chars(Vec<char>);
  type Err (line 19) | type Err = String;
  method from_str (line 20) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type Target (line 26) | type Target = Vec<char>;
  method deref (line 27) | fn deref(&self) -> &Self::Target {
  type Args (line 36) | struct Args {
    method markdown_exts (line 46) | fn markdown_exts(&self) -> Result<Vec<String>> {
    method force_markdown (line 66) | fn force_markdown(&self) -> bool {
  function fix_trailing_whitespace (line 71) | pub(crate) async fn fix_trailing_whitespace(
  function fix_file (line 97) | async fn fix_file(
  function detect_line_ending (line 150) | fn detect_line_ending(line: &[u8]) -> &[u8] {
  function needs_markdown_break (line 162) | fn needs_markdown_break(is_markdown: bool, trimmed: &[u8]) -> bool {
  function create_test_file (line 175) | async fn create_test_file(dir: &TempDir, name: &str, content: &[u8]) -> ...
  function test_trim_non_markdown_trims_spaces (line 182) | async fn test_trim_non_markdown_trims_spaces() -> Result<()> {
  function test_markdown_preserve_two_spaces_and_reduce_extra (line 206) | async fn test_markdown_preserve_two_spaces_and_reduce_extra() -> Result<...
  function test_force_markdown_obeys_markdown_rules (line 231) | async fn test_force_markdown_obeys_markdown_rules() -> Result<()> {
  function test_no_changes_returns_zero_and_no_write (line 257) | async fn test_no_changes_returns_zero_and_no_write() -> Result<()> {
  function test_empty_file_no_change (line 275) | async fn test_empty_file_no_change() -> Result<()> {
  function test_only_whitespace_lines_are_handled_not_markdown_end (line 291) | async fn test_only_whitespace_lines_are_handled_not_markdown_end() -> Re...
  function test_chars_empty_uses_trim_ascii_end (line 310) | async fn test_chars_empty_uses_trim_ascii_end() -> Result<()> {
  function test_crlf_lines_handling (line 328) | async fn test_crlf_lines_handling() -> Result<()> {
  function test_no_newline_at_eof (line 347) | async fn test_no_newline_at_eof() -> Result<()> {
  function test_unicode_trim_char (line 365) | async fn test_unicode_trim_char() -> Result<()> {
  function test_extension_case_insensitive_matching (line 382) | async fn test_extension_case_insensitive_matching() -> Result<()> {
  function test_mixed_lines_modified_flag_true_if_any_changed (line 400) | async fn test_mixed_lines_modified_flag_true_if_any_changed() -> Result<...
  function test_no_change_no_newline_at_eof (line 417) | async fn test_no_change_no_newline_at_eof() -> Result<()> {
  function test_markdown_wildcard_ext_and_eof_whitespace_removed (line 435) | async fn test_markdown_wildcard_ext_and_eof_whitespace_removed() -> Resu...
  function test_markdown_with_custom_charset (line 453) | async fn test_markdown_with_custom_charset() -> Result<()> {
  function test_eol_trim (line 470) | async fn test_eol_trim() -> Result<()> {
  function test_markdown_trim (line 487) | async fn test_markdown_trim() -> Result<()> {
  function test_invalid_utf8_file_is_handled (line 504) | async fn test_invalid_utf8_file_is_handled() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/mixed_line_ending.rs
  constant CRLF (line 12) | const CRLF: &[u8] = b"\r\n";
  constant LF (line 13) | const LF: &[u8] = b"\n";
  constant CR (line 14) | const CR: &[u8] = b"\r";
  constant ALL_ENDINGS (line 15) | const ALL_ENDINGS: [&[u8]; 3] = [CR, CRLF, LF];
  type Args (line 21) | struct Args {
  type FixMode (line 30) | enum FixMode {
  function mixed_line_ending (line 44) | pub(crate) async fn mixed_line_ending(hook: &Hook, filenames: &[&Path]) ...
  function fix_file (line 54) | async fn fix_file(file_base: &Path, filename: &Path, fix_mode: FixMode) ...
  function count_line_endings (line 105) | fn count_line_endings(contents: &[u8]) -> FxHashMap<&'static [u8], usize> {
  function find_most_common_ending (line 124) | fn find_most_common_ending(counts: &FxHashMap<&'static [u8], usize>) -> ...
  function apply_line_ending (line 132) | async fn apply_line_ending(filename: &Path, contents: &[u8], ending: &[u...
  function strip_line_ending (line 146) | fn strip_line_ending(line: &[u8]) -> &[u8] {
  function split_lines_with_endings (line 156) | fn split_lines_with_endings(contents: &[u8]) -> Vec<&[u8]> {
  function create_test_file (line 204) | async fn create_test_file(
  function test_auto_fix_crlf_wins (line 215) | async fn test_auto_fix_crlf_wins() -> Result<()> {
  function test_auto_fix_lf_wins (line 229) | async fn test_auto_fix_lf_wins() -> Result<()> {
  function test_auto_fix_tie_prefers_lf (line 243) | async fn test_auto_fix_tie_prefers_lf() -> Result<()> {
  function test_fix_no (line 257) | async fn test_fix_no() -> Result<()> {
  function test_no_line_endings (line 271) | async fn test_no_line_endings() -> Result<()> {
  function test_fix_with_cr_endings (line 283) | async fn test_fix_with_cr_endings() -> Result<()> {

FILE: crates/prek/src/hooks/pre_commit_hooks/mod.rs
  type PreCommitHooks (line 43) | pub(crate) enum PreCommitHooks {
    method check_supported (line 62) | pub(crate) fn check_supported(&self, hook: &Hook) -> bool {
    method run (line 70) | pub(crate) async fn run(self, hook: &Hook, filenames: &[&Path]) -> Res...
  function is_pre_commit_hooks (line 95) | pub(crate) fn is_pre_commit_hooks(url: &str) -> bool {

FILE: crates/prek/src/hooks/pre_commit_hooks/no_commit_to_branch.rs
  type Args (line 12) | struct Args {
    method check_protected (line 20) | fn check_protected(&self, branch: &str) -> Result<bool> {
  function no_commit_to_branch (line 42) | pub(crate) async fn no_commit_to_branch(hook: &Hook) -> Result<(i32, Vec...

FILE: crates/prek/src/http.rs
  function download_and_extract (line 16) | pub(crate) async fn download_and_extract(
  function download_and_extract_with (line 28) | pub(crate) async fn download_and_extract_with(
  function load_pem_certs_from_file (line 87) | fn load_pem_certs_from_file(path: &Path) -> Result<Vec<Certificate>> {
  function load_pem_certs_from_dir (line 95) | fn load_pem_certs_from_dir(dir: &Path) -> Result<Vec<Certificate>> {
  function load_certs_from_paths (line 124) | fn load_certs_from_paths(file: Option<&Path>, dirs: &[impl AsRef<Path>])...
  function create_reqwest_client (line 155) | fn create_reqwest_client(native_tls: bool, custom_certs: Vec<Certificate...
  constant TEST_CERT_PEM (line 183) | const TEST_CERT_PEM: &str = "-----BEGIN CERTIFICATE-----
  function write_cert (line 196) | fn write_cert(path: &Path) {
  function test_load_pem_certs_from_file (line 201) | fn test_load_pem_certs_from_file() -> Result<()> {
  function test_load_pem_certs_from_dir_skips_invalid_files (line 213) | fn test_load_pem_certs_from_dir_skips_invalid_files() -> Result<()> {
  function test_load_certs_from_paths_combines_sources (line 228) | fn test_load_certs_from_paths_combines_sources() -> Result<()> {
  function test_native_tls (line 245) | async fn test_native_tls() {

FILE: crates/prek/src/install_source.rs
  type InstallSource (line 6) | pub(crate) enum InstallSource {
    method from_path (line 17) | fn from_path(path: &Path) -> Option<Self> {
    method is_standalone_installer (line 63) | fn is_standalone_installer() -> anyhow::Result<bool> {
    method detect (line 72) | pub(crate) fn detect() -> Option<Self> {
    method description (line 84) | pub(crate) fn description(self) -> &'static str {
    method update_instructions (line 96) | pub(crate) fn update_instructions(self) -> &'static str {
  function detects_homebrew_cellar_arm (line 113) | fn detects_homebrew_cellar_arm() {
  function detects_homebrew_cellar_intel (line 121) | fn detects_homebrew_cellar_intel() {
  function returns_none_for_unknown_unix_path (line 129) | fn returns_none_for_unknown_unix_path() {
  function detects_mise_installs (line 137) | fn detects_mise_installs() {
  function does_not_match_other_mise_tool (line 147) | fn does_not_match_other_mise_tool() {
  function does_not_match_other_cellar_formula (line 157) | fn does_not_match_other_cellar_formula() {
  function detects_uv_tool_macos (line 165) | fn detects_uv_tool_macos() {
  function detects_uv_tool_linux (line 173) | fn detects_uv_tool_linux() {
  function detects_uv_tool_custom_xdg (line 181) | fn detects_uv_tool_custom_xdg() {
  function does_not_match_other_uv_tool (line 189) | fn does_not_match_other_uv_tool() {
  function detects_pipx_macos (line 197) | fn detects_pipx_macos() {
  function detects_pipx_linux (line 205) | fn detects_pipx_linux() {
  function does_not_match_other_pipx_package (line 215) | fn does_not_match_other_pipx_package() {
  function detects_asdf (line 223) | fn detects_asdf() {
  function does_not_match_other_asdf_plugin (line 231) | fn does_not_match_other_asdf_plugin() {
  function returns_none_for_unknown_windows_path (line 242) | fn returns_none_for_unknown_windows_path() {

FILE: crates/prek/src/languages/bun/bun.rs
  type Bun (line 22) | pub(crate) struct Bun;
  method install (line 25) | async fn install(
  method check_health (line 102) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 119) | async fn run(

FILE: crates/prek/src/languages/bun/installer.rs
  type BunResult (line 22) | pub(crate) struct BunResult {
    method from_executable (line 44) | pub(crate) fn from_executable(bun: PathBuf) -> Self {
    method from_dir (line 51) | pub(crate) fn from_dir(dir: &Path) -> Self {
    method with_version (line 56) | pub(crate) fn with_version(mut self, version: BunVersion) -> Self {
    method fill_version (line 61) | pub(crate) async fn fill_version(mut self) -> Result<Self> {
    method bun (line 78) | pub(crate) fn bun(&self) -> &Path {
    method version (line 82) | pub(crate) fn version(&self) -> &BunVersion {
  method fmt (line 28) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type BunInstaller (line 87) | pub(crate) struct BunInstaller {
    method new (line 92) | pub(crate) fn new(root: PathBuf) -> Self {
    method install (line 97) | pub(crate) async fn install(
    method find_installed (line 129) | fn find_installed(&self, req: &BunRequest) -> Result<BunResult> {
    method resolve_version (line 161) | async fn resolve_version(&self, req: &BunRequest) -> Result<BunVersion> {
    method list_remote_versions (line 175) | async fn list_remote_versions(&self) -> Result<Vec<BunVersion>> {
    method download (line 205) | async fn download(&self, store: &Store, version: &BunVersion) -> Resul...
    method find_system_bun (line 248) | async fn find_system_bun(&self, bun_request: &BunRequest) -> Result<Op...
  function bin_dir (line 285) | pub(crate) fn bin_dir(prefix: &Path) -> PathBuf {
  function lib_dir (line 290) | pub(crate) fn lib_dir(prefix: &Path) -> PathBuf {

FILE: crates/prek/src/languages/bun/version.rs
  type BunVersion (line 12) | pub(crate) struct BunVersion(semver::Version);
  method default (line 15) | fn default() -> Self {
  type Target (line 21) | type Target = semver::Version;
  method deref (line 23) | fn deref(&self) -> &Self::Target {
  method fmt (line 29) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Err (line 35) | type Err = semver::Error;
  method from_str (line 37) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type BunRequest (line 53) | pub(crate) enum BunRequest {
    method is_any (line 100) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 104) | fn parse_version_numbers(
    method satisfied_by (line 119) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
    method matches (line 127) | pub(crate) fn matches(&self, version: &BunVersion, toolchain: Option<&...
  type Err (line 63) | type Err = Error;
  method from_str (line 65) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  function test_bun_version_from_str (line 147) | fn test_bun_version_from_str() {
  function test_bun_request_from_str (line 160) | fn test_bun_request_from_str() {
  function test_bun_request_range (line 188) | fn test_bun_request_range() {
  function test_bun_request_invalid (line 197) | fn test_bun_request_invalid() {
  function test_bun_request_matches (line 204) | fn test_bun_request_matches() {

FILE: crates/prek/src/languages/deno/deno.rs
  function is_valid_install_name (line 20) | fn is_valid_install_name(name: &str) -> bool {
  function parse_install_dependency (line 41) | fn parse_install_dependency(spec: &str) -> (&str, Option<&str>) {
  type Deno (line 56) | pub(crate) struct Deno;
  method install (line 59) | async fn install(
  method check_health (line 163) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 180) | async fn run(
  function parse_install_dependency_without_name (line 244) | fn parse_install_dependency_without_name() {
  function parse_install_dependency_with_name (line 252) | fn parse_install_dependency_with_name() {
  function parse_install_dependency_with_local_path_name (line 260) | fn parse_install_dependency_with_local_path_name() {
  function parse_install_dependency_with_invalid_name_keeps_original (line 268) | fn parse_install_dependency_with_invalid_name_keeps_original() {

FILE: crates/prek/src/languages/deno/installer.rs
  type DenoResult (line 22) | pub(crate) struct DenoResult {
    method from_executable (line 44) | pub(crate) fn from_executable(deno: PathBuf) -> Self {
    method from_dir (line 51) | pub(crate) fn from_dir(dir: &Path) -> Self {
    method with_version (line 56) | pub(crate) fn with_version(mut self, version: DenoVersion) -> Self {
    method fill_version (line 61) | pub(crate) async fn fill_version(mut self) -> Result<Self> {
    method deno (line 84) | pub(crate) fn deno(&self) -> &Path {
    method version (line 88) | pub(crate) fn version(&self) -> &DenoVersion {
  method fmt (line 28) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type DenoInstaller (line 93) | pub(crate) struct DenoInstaller {
    method new (line 98) | pub(crate) fn new(root: PathBuf) -> Self {
    method install (line 103) | pub(crate) async fn install(
    method find_installed (line 135) | fn find_installed(&self, req: &DenoRequest) -> Result<DenoResult> {
    method resolve_version (line 167) | async fn resolve_version(&self, req: &DenoRequest) -> Result<DenoVersi...
    method list_remote_versions (line 184) | async fn list_remote_versions(&self) -> Result<Vec<DenoVersion>> {
    method download (line 208) | async fn download(&self, store: &Store, version: &DenoVersion) -> Resu...
    method find_system_deno (line 265) | async fn find_system_deno(&self, deno_request: &DenoRequest) -> Result...
  function bin_dir (line 305) | pub(crate) fn bin_dir(prefix: &Path) -> PathBuf {

FILE: crates/prek/src/languages/deno/version.rs
  type DenoVersion (line 12) | pub(crate) struct DenoVersion(semver::Version);
  method default (line 15) | fn default() -> Self {
  type Target (line 21) | type Target = semver::Version;
  method deref (line 23) | fn deref(&self) -> &Self::Target {
  method fmt (line 29) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Err (line 35) | type Err = semver::Error;
  method from_str (line 37) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type DenoRequest (line 52) | pub(crate) enum DenoRequest {
    method is_any (line 89) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 93) | fn parse_version_numbers(
    method satisfied_by (line 108) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
    method matches (line 116) | pub(crate) fn matches(&self, version: &DenoVersion, _toolchain: Option...
  type Err (line 61) | type Err = Error;
  method from_str (line 63) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  function test_deno_version_from_str (line 134) | fn test_deno_version_from_str() {
  function test_deno_request_from_str (line 147) | fn test_deno_request_from_str() {
  function test_deno_request_range (line 181) | fn test_deno_request_range() {
  function test_deno_request_invalid (line 190) | fn test_deno_request_invalid() {
  function test_deno_request_matches (line 197) | fn test_deno_request_matches() {

FILE: crates/prek/src/languages/docker.rs
  type Docker (line 24) | pub(crate) struct Docker;
    method docker_tag (line 321) | fn docker_tag(info: &InstallInfo) -> String {
    method build_docker_image (line 333) | async fn build_docker_image(
    method docker_run_cmd (line 371) | pub(crate) fn docker_run_cmd(work_dir: &Path) -> Cmd {
  type Error (line 27) | enum Error {
  function is_in_docker (line 37) | fn is_in_docker() -> bool {
  function current_container_id (line 53) | fn current_container_id() -> Result<String> {
  function current_container_id_from_paths (line 57) | fn current_container_id_from_paths(
  function container_id_from_cgroup_v1 (line 67) | fn container_id_from_cgroup_v1(cgroup: impl AsRef<Path>) -> Result<Strin...
  function parse_id_from_line (line 75) | fn parse_id_from_line(line: &str) -> Option<String> {
  function container_id_from_cgroup_v2 (line 102) | fn container_id_from_cgroup_v2(mount_info: impl AsRef<Path>) -> Result<S...
  type RuntimeKind (line 112) | enum RuntimeKind {
    method cmd (line 142) | fn cmd(&self) -> &str {
    method detect_rootless (line 152) | fn detect_rootless(self) -> Result<bool> {
    method list_mounts (line 180) | fn list_mounts(self) -> Result<Vec<Mount>> {
  type Err (line 120) | type Err = String;
  method from_str (line 122) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type Mount (line 134) | struct Mount {
  type ContainerRuntimeInfo (line 204) | struct ContainerRuntimeInfo {
    method resolve_runtime_kind (line 213) | fn resolve_runtime_kind<DF, PF, CF>(
    method detect_runtime (line 260) | fn detect_runtime() -> Self {
    method cmd (line 284) | fn cmd(&self) -> &str {
    method is_rootless (line 288) | fn is_rootless(&self) -> bool {
    method is_podman (line 292) | fn is_podman(&self) -> bool {
    method is_apple_container (line 296) | fn is_apple_container(&self) -> bool {
    method map_to_host_path (line 301) | fn map_to_host_path<'a>(&self, path: &'a Path) -> Cow<'a, Path> {
  method install (line 429) | async fn install(
  method check_health (line 457) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 461) | async fn run(
  constant CONTAINER_ID_V1 (line 533) | const CONTAINER_ID_V1: &str =
  constant CGROUP_V1_SAMPLE (line 535) | const CGROUP_V1_SAMPLE: &str = r"9:cpuset:/system.slice/docker-7be928087...
  constant CONTAINER_ID_V2 (line 539) | const CONTAINER_ID_V2: &str =
  constant MOUNTINFO_SAMPLE (line 541) | const MOUNTINFO_SAMPLE: &str = r"402 401 0:45 /docker/containers/6d81fc3...
  function test_container_id_from_cgroup_v1 (line 546) | fn test_container_id_from_cgroup_v1() -> anyhow::Result<()> {
  function invalid_container_id_from_cgroup_v1 (line 588) | fn invalid_container_id_from_cgroup_v1() -> anyhow::Result<()> {
  function test_container_id_from_cgroup_v2 (line 609) | fn test_container_id_from_cgroup_v2() -> anyhow::Result<()> {
  function test_current_container_id_prefers_cgroup_v1 (line 651) | fn test_current_container_id_prefers_cgroup_v1() -> anyhow::Result<()> {
  function test_current_container_id_falls_back_to_cgroup_v2 (line 666) | fn test_current_container_id_falls_back_to_cgroup_v2() -> anyhow::Result...
  function test_current_container_id_errors_when_no_match (line 681) | fn test_current_container_id_errors_when_no_match() -> anyhow::Result<()> {
  function test_detect_container_runtime (line 694) | fn test_detect_container_runtime() {

FILE: crates/prek/src/languages/docker_image.rs
  type DockerImage (line 15) | pub(crate) struct DockerImage;
  method install (line 18) | async fn install(
  method check_health (line 27) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 31) | async fn run(

FILE: crates/prek/src/languages/fail.rs
  type Fail (line 13) | pub(crate) struct Fail;
  method install (line 16) | async fn install(
  method check_health (line 25) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 29) | async fn run(

FILE: crates/prek/src/languages/golang/golang.rs
  type Golang (line 21) | pub(crate) struct Golang;
  method install (line 24) | async fn install(
  method check_health (line 116) | async fn check_health(&self, _info: &InstallInfo) -> anyhow::Result<()> {
  method run (line 120) | async fn run(
  function bin_dir (line 186) | pub(crate) fn bin_dir(env_path: &Path) -> PathBuf {

FILE: crates/prek/src/languages/golang/gomod.rs
  function parse_go_mod_directives (line 11) | fn parse_go_mod_directives(contents: &str) -> (Option<String>, Option<St...
  function normalize_go_semver_min (line 57) | fn normalize_go_semver_min(version: &str) -> String {
  function choose_language_version_from_go_mod (line 85) | fn choose_language_version_from_go_mod(contents: &str) -> Option<String> {
  function extract_go_mod_language_request (line 95) | async fn extract_go_mod_language_request(repo_path: &Path) -> Result<Opt...
  function extract_go_mod_metadata (line 107) | pub(crate) async fn extract_go_mod_metadata(hook: &mut Hook) -> Result<(...
  function go_line_is_used_when_only_go_present (line 142) | fn go_line_is_used_when_only_go_present() {
  function go_is_preferred_over_toolchain (line 154) | fn go_is_preferred_over_toolchain() {
  function invalid_toolchain_value_is_ignored (line 167) | fn invalid_toolchain_value_is_ignored() {
  function comments_and_whitespace_are_ignored (line 179) | fn comments_and_whitespace_are_ignored() {
  function toolchain_is_used_when_no_go_present (line 193) | fn toolchain_is_used_when_no_go_present() {
  function go_minor_is_normalized_to_patch (line 205) | fn go_minor_is_normalized_to_patch() {
  function extract_language_request_from_repo_go_line (line 217) | async fn extract_language_request_from_repo_go_line() -> anyhow::Result<...
  function extract_language_request_from_repo_toolchain_when_no_go (line 234) | async fn extract_language_request_from_repo_toolchain_when_no_go() -> an...
  function extract_language_request_ignores_invalid_toolchain_value (line 251) | async fn extract_language_request_ignores_invalid_toolchain_value() -> a...
  function extract_language_request_missing_go_mod_is_none (line 265) | async fn extract_language_request_missing_go_mod_is_none() -> anyhow::Re...

FILE: crates/prek/src/languages/golang/installer.rs
  type GoResult (line 22) | pub(crate) struct GoResult {
    method from_executable (line 45) | fn from_executable(path: PathBuf, from_system: bool) -> Self {
    method from_dir (line 53) | pub(crate) fn from_dir(dir: &Path, from_system: bool) -> Self {
    method bin (line 58) | pub(crate) fn bin(&self) -> &Path {
    method version (line 62) | pub(crate) fn version(&self) -> &GoVersion {
    method is_from_system (line 66) | pub(crate) fn is_from_system(&self) -> bool {
    method cmd (line 70) | pub(crate) fn cmd(&self, summary: &str) -> Cmd {
    method with_version (line 74) | pub(crate) fn with_version(mut self, version: GoVersion) -> Self {
    method fill_version (line 79) | pub(crate) async fn fill_version(mut self) -> Result<Self> {
  method fmt (line 29) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type GoInstaller (line 102) | pub(crate) struct GoInstaller {
    method new (line 107) | pub(crate) fn new(root: PathBuf) -> Self {
    method install (line 111) | pub(crate) async fn install(
    method find_installed (line 144) | fn find_installed(&self, request: &GoRequest) -> Result<GoResult> {
    method resolve_version (line 178) | async fn resolve_version(&self, req: &GoRequest) -> Result<GoVersion> {
    method download (line 204) | async fn download(&self, store: &Store, version: &GoVersion) -> Result...
    method find_system_go (line 250) | async fn find_system_go(&self, go_request: &GoRequest) -> Result<Optio...
  function fill_version_uses_local_gotoolchain (line 296) | async fn fill_version_uses_local_gotoolchain() -> anyhow::Result<()> {

FILE: crates/prek/src/languages/golang/version.rs
  type GoVersion (line 12) | pub(crate) struct GoVersion(semver::Version);
  method default (line 15) | fn default() -> Self {
  type Target (line 21) | type Target = semver::Version;
  method deref (line 23) | fn deref(&self) -> &Self::Target {
  method fmt (line 29) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Err (line 35) | type Err = semver::Error;
  method from_str (line 38) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type GoRequest (line 56) | pub(crate) enum GoRequest {
    method is_any (line 118) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 122) | fn parse_version_numbers(
    method satisfied_by (line 137) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
    method matches (line 146) | pub(crate) fn matches(&self, version: &GoVersion, toolchain: Option<&P...
  method fmt (line 68) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Err (line 83) | type Err = Error;
  method from_str (line 85) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  function test_go_request_from_str (line 168) | fn test_go_request_from_str() {
  function test_go_request_invalid (line 194) | fn test_go_request_invalid() {
  function test_go_request_matches (line 203) | fn test_go_request_matches() {
  function test_go_request_display (line 236) | fn test_go_request_display() {

FILE: crates/prek/src/languages/haskell.rs
  type Haskell (line 23) | pub(crate) struct Haskell;
  method install (line 26) | async fn install(
  method check_health (line 107) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 111) | async fn run(

FILE: crates/prek/src/languages/julia.rs
  type Julia (line 16) | pub(crate) struct Julia;
  method install (line 19) | async fn install(
  method check_health (line 90) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 100) | async fn run(

FILE: crates/prek/src/languages/lua.rs
  type Lua (line 19) | pub(crate) struct Lua;
    method install_rockspec (line 187) | async fn install_rockspec(env_path: &Path, root_path: &Path, rockspec:...
    method install_dependency (line 201) | async fn install_dependency(env_path: &Path, dependency: &str) -> Resu...
    method get_rockspec_file (line 214) | fn get_rockspec_file(root_path: &Path) -> Option<PathBuf> {
    method get_lua_path (line 226) | fn get_lua_path(env_dir: &Path, version: &str) -> String {
    method get_lua_cpath (line 240) | fn get_lua_cpath(env_dir: &Path, version: &str) -> String {
  type LuaInfo (line 21) | pub(crate) struct LuaInfo {
  function query_lua_info (line 26) | pub(crate) async fn query_lua_info() -> Result<LuaInfo> {
  method install (line 58) | async fn install(
  method check_health (line 102) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 126) | async fn run(

FILE: crates/prek/src/languages/mod.rs
  type LanguageImpl (line 56) | trait LanguageImpl {
    method install (line 57) | async fn install(
    method check_health (line 64) | async fn check_health(&self, info: &InstallInfo) -> Result<()>;
    method run (line 66) | async fn run(
    method install (line 82) | async fn install(
    method check_health (line 91) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
    method run (line 95) | async fn run(
  type UnimplementedError (line 77) | struct UnimplementedError(String);
  type Unimplemented (line 79) | struct Unimplemented;
  method supported (line 130) | pub fn supported(lang: Language) -> bool {
  method supports_install_env (line 153) | pub fn supports_install_env(self) -> bool {
  method tool_buckets (line 160) | pub fn tool_buckets(self) -> &'static [ToolBucket] {
  method cache_buckets (line 173) | pub fn cache_buckets(self) -> &'static [CacheBucket] {
  method supports_language_version (line 186) | pub fn supports_language_version(self) -> bool {
  method supports_dependency (line 203) | pub fn supports_dependency(self) -> bool {
  method install (line 217) | pub async fn install(
  method check_health (line 245) | pub async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 269) | pub async fn run(
  function extract_metadata (line 322) | pub(crate) async fn extract_metadata(hook: &mut Hook) -> Result<()> {
  function resolve_command (line 331) | pub(crate) fn resolve_command(mut cmds: Vec<String>, paths: Option<&OsSt...
  function write_file (line 389) | fn write_file(path: &Path, contents: &str) {
  function make_executable (line 394) | fn make_executable(path: &Path) {
  function make_executable (line 404) | fn make_executable(_path: &Path) {}
  function resolve_command_passthrough_when_not_found (line 407) | fn resolve_command_passthrough_when_not_found() {
  function resolve_command_resolves_shebang_interpreter_from_path (line 414) | fn resolve_command_resolves_shebang_interpreter_from_path() {
  function resolve_command_windows_rewrites_bin_sh_to_path_sh (line 442) | fn resolve_command_windows_rewrites_bin_sh_to_path_sh() {
  function resolve_command_windows_keeps_existing_absolute_interpreter_path (line 462) | fn resolve_command_windows_keeps_existing_absolute_interpreter_path() {

FILE: crates/prek/src/languages/node/installer.rs
  type NodeResult (line 22) | pub(crate) struct NodeResult {
    method from_executables (line 45) | pub(crate) fn from_executables(node: PathBuf, npm: PathBuf) -> Self {
    method from_dir (line 53) | pub(crate) fn from_dir(dir: &Path) -> Self {
    method with_version (line 61) | pub(crate) fn with_version(mut self, version: NodeVersion) -> Self {
    method fill_version (line 66) | pub(crate) async fn fill_version(mut self) -> Result<Self> {
    method node (line 83) | pub(crate) fn node(&self) -> &Path {
    method npm (line 87) | pub(crate) fn npm(&self) -> &Path {
    method version (line 91) | pub(crate) fn version(&self) -> &NodeVersion {
  method fmt (line 29) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type NodeInstaller (line 96) | pub(crate) struct NodeInstaller {
    method new (line 101) | pub(crate) fn new(root: PathBuf) -> Self {
    method install (line 106) | pub(crate) async fn install(
    method find_installed (line 138) | fn find_installed(&self, req: &NodeRequest) -> Result<NodeResult> {
    method resolve_version (line 170) | async fn resolve_version(&self, req: &NodeRequest) -> Result<NodeVersi...
    method list_remote_versions (line 184) | async fn list_remote_versions(&self) -> Result<Vec<NodeVersion>> {
    method download (line 192) | async fn download(&self, store: &Store, version: &NodeVersion) -> Resu...
    method find_system_node (line 239) | async fn find_system_node(&self, node_request: &NodeRequest) -> Result...
    method find_npm_in_same_directory (line 289) | fn find_npm_in_same_directory(node_path: &Path) -> Result<Option<PathB...
  function bin_dir (line 313) | pub(crate) fn bin_dir(prefix: &Path) -> PathBuf {
  function lib_dir (line 321) | pub(crate) fn lib_dir(prefix: &Path) -> PathBuf {
  function is_executable (line 329) | fn is_executable(path: &Path) -> bool {

FILE: crates/prek/src/languages/node/node.rs
  type Node (line 23) | pub(crate) struct Node;
  method install (line 26) | async fn install(
  method check_health (line 119) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 136) | async fn run(

FILE: crates/prek/src/languages/node/version.rs
  type Lts (line 12) | pub(crate) enum Lts {
    method code_name (line 18) | pub(crate) fn code_name(&self) -> Option<&str> {
    method deserialize (line 27) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  method serialize (line 42) | fn serialize<S>(&self, serializer: S) -> anyhow::Result<S::Ok, S::Error>
  type NodeVersion (line 54) | pub(crate) struct NodeVersion {
    method deserialize (line 69) | fn deserialize<D>(deserializer: D) -> anyhow::Result<NodeVersion, D::E...
    method major (line 114) | pub fn major(&self) -> u64 {
    method minor (line 117) | pub fn minor(&self) -> u64 {
    method patch (line 120) | pub fn patch(&self) -> u64 {
    method version (line 123) | pub fn version(&self) -> &semver::Version {
  method default (line 60) | fn default() -> Self {
  method fmt (line 90) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Err (line 100) | type Err = semver::Error;
  method from_str (line 102) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  type NodeRequest (line 139) | pub(crate) enum NodeRequest {
    method is_any (line 198) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 202) | fn parse_version_numbers(
    method satisfied_by (line 217) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
    method matches (line 233) | pub(crate) fn matches(&self, version: &NodeVersion, toolchain: Option<...
  type Err (line 153) | type Err = Error;
  method from_str (line 155) | fn from_str(request: &str) -> Result<Self, Self::Err> {
  constant EXTRA_KEY_LTS (line 195) | pub(crate) const EXTRA_KEY_LTS: &str = "lts";
  function test_node_request_from_str (line 265) | fn test_node_request_from_str() {
  function test_node_request_invalid (line 301) | fn test_node_request_invalid() {
  function test_node_request_satisfied_by (line 311) | fn test_node_request_satisfied_by() -> anyhow::Result<()> {

FILE: crates/prek/src/languages/pygrep/pygrep.rs
  type Args (line 19) | struct Args {
    method parse (line 26) | fn parse(args: &[String]) -> Result<Self> {
    method to_args (line 41) | fn to_args(&self) -> Vec<&'static str> {
  type Error (line 55) | enum Error {
  constant INSTALL_PYTHON_VERSION (line 68) | const INSTALL_PYTHON_VERSION: &str = "3.13";
  type Pygrep (line 70) | pub(crate) struct Pygrep;
  function find_installed_python (line 72) | fn find_installed_python(python_dir: &Path) -> Option<PathBuf> {
  method install (line 91) | async fn install(
  method check_health (line 174) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 182) | async fn run(

FILE: crates/prek/src/languages/pygrep/script.py
  function process_file (line 13) | def process_file(
  function _process_filename_by_line (line 33) | def _process_filename_by_line(
  function _process_filename_at_once (line 48) | def _process_filename_at_once(
  function _process_filename_by_line_negated (line 69) | def _process_filename_by_line_negated(
  function _process_filename_at_once_negated (line 80) | def _process_filename_at_once_negated(
  function run (line 92) | def run(
  function main (line 156) | def main():

FILE: crates/prek/src/languages/python/mod.rs
  function extract_metadata (line 14) | pub(crate) async fn extract_metadata(hook: &mut Hook) -> Result<()> {

FILE: crates/prek/src/languages/python/pep723.rs
  type Pep723Script (line 39) | pub struct Pep723Script {
    method read (line 54) | pub async fn read(file: impl AsRef<Path>) -> Result<Option<Self>, Pep7...
  type Pep723Metadata (line 84) | pub struct Pep723Metadata {
  type Err (line 90) | type Err = toml::de::Error;
  method from_str (line 93) | fn from_str(raw: &str) -> Result<Self, Self::Err> {
  type Pep723Error (line 100) | pub enum Pep723Error {
  type ScriptTag (line 114) | pub struct ScriptTag {
    method parse (line 152) | pub fn parse(contents: &[u8]) -> Result<Option<Self>, Pep723Error> {
  function extract_pep723_metadata (line 258) | pub(crate) async fn extract_pep723_metadata(hook: &mut Hook) -> Result<(...

FILE: crates/prek/src/languages/python/pyproject.rs
  type PyProjectToml (line 13) | struct PyProjectToml {
  type ProjectTable (line 19) | struct ProjectTable {
  function extract_pyproject_requires_python (line 23) | async fn extract_pyproject_requires_python(repo_path: &Path) -> Result<O...
  function extract_pyproject_metadata (line 46) | pub(crate) async fn extract_pyproject_metadata(hook: &mut Hook) -> Resul...
  function valid_requires_python (line 83) | async fn valid_requires_python() -> anyhow::Result<()> {
  function missing_file_returns_none (line 97) | async fn missing_file_returns_none() -> anyhow::Result<()> {
  function missing_project_table_returns_none (line 105) | async fn missing_project_table_returns_none() -> anyhow::Result<()> {
  function missing_requires_python_returns_none (line 119) | async fn missing_requires_python_returns_none() -> anyhow::Result<()> {
  function unparsable_toml_returns_none (line 133) | async fn unparsable_toml_returns_none() -> anyhow::Result<()> {
  function invalid_version_specifier_is_ignored (line 147) | async fn invalid_version_specifier_is_ignored() -> anyhow::Result<()> {

FILE: crates/prek/src/languages/python/python.rs
  type Python (line 28) | pub(crate) struct Python;
    method remove_uv_python_override_envs (line 256) | fn remove_uv_python_override_envs(cmd: &mut Cmd) -> &mut Cmd {
    method pip_install_command (line 265) | fn pip_install_command(uv: &Uv, store: &Store, env_path: &Path) -> Cmd {
    method create_venv (line 281) | async fn create_venv(
    method create_venv_command (line 329) | fn create_venv_command(
    method can_retry_with_downloads (line 365) | fn can_retry_with_downloads(error: &process::Error) -> bool {
  type PythonInfo (line 30) | pub(crate) struct PythonInfo {
  type PythonInfoError (line 36) | pub(crate) enum PythonInfoError {
  function query_python_info (line 48) | async fn query_python_info(python: &Path) -> Result<PythonInfo, PythonIn...
  function query_python_info_cached (line 84) | pub(crate) async fn query_python_info_cached(
  method install (line 97) | async fn install(
  method check_health (line 169) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 186) | async fn run(
  function to_uv_python_request (line 238) | fn to_uv_python_request(request: &LanguageRequest) -> Option<String> {
  function bin_dir (line 383) | fn bin_dir(venv: &Path) -> PathBuf {
  function python_exec (line 391) | pub(crate) fn python_exec(venv: &Path) -> PathBuf {
  function setup_test_install (line 410) | fn setup_test_install() -> (tempfile::TempDir, Uv, Store, InstallInfo) {
  function env_map (line 423) | fn env_map(cmd: &crate::process::Cmd) -> HashMap<String, Option<String>> {
  function create_venv_command_removes_uv_system_python_override (line 435) | fn create_venv_command_removes_uv_system_python_override() {
  function pip_install_command_removes_uv_system_python_override (line 448) | fn pip_install_command_removes_uv_system_python_override() {

FILE: crates/prek/src/languages/python/uv.rs
  constant CUR_UV_VERSION (line 23) | const CUR_UV_VERSION: &str = "0.10.9";
  function wheel_platform_tag_for_host (line 27) | fn wheel_platform_tag_for_host(
  function get_wheel_platform_tag (line 83) | fn get_wheel_platform_tag() -> Result<String> {
  function get_uv_version (line 88) | fn get_uv_version(uv_path: &Path) -> Result<Version> {
  function validate_uv_binary (line 107) | fn validate_uv_binary(uv_path: &Path) -> Result<Version> {
  function replace_uv_binary (line 118) | async fn replace_uv_binary(source: &Path, target_path: &Path) -> Result<...
  type PyPiMirror (line 146) | enum PyPiMirror {
    method url (line 158) | fn url(&self) -> &str {
    method iter (line 168) | fn iter() -> impl Iterator<Item = Self> {
  type InstallSource (line 174) | enum InstallSource {
    method install (line 184) | async fn install(&self, store: &Store, target: &Path) -> Result<()> {
    method install_from_github (line 192) | async fn install_from_github(&self, store: &Store, target: &Path) -> R...
    method install_from_pypi (line 215) | async fn install_from_pypi(
    method install_from_simple_api (line 267) | async fn install_from_simple_api(
    method download_and_extract_wheel (line 319) | async fn download_and_extract_wheel(
    method install_from_pip (line 359) | async fn install_from_pip(&self, target: &Path) -> Result<()> {
  type Uv (line 398) | pub(crate) struct Uv {
    method new (line 403) | pub(crate) fn new(path: PathBuf) -> Self {
    method cmd (line 407) | pub(crate) fn cmd(&self, summary: &str, store: &Store) -> Cmd {
    method select_source (line 413) | async fn select_source() -> Result<InstallSource> {
    method install (line 474) | pub(crate) async fn install(store: &Store, uv_dir: &Path) -> Result<Se...
  function uv_source_from_env (line 559) | fn uv_source_from_env() -> Option<InstallSource> {
  function ensure_cur_uv_version_in_range (line 581) | fn ensure_cur_uv_version_in_range() {
  function wheel_platform_tag_x86_64_linux_gnu (line 591) | fn wheel_platform_tag_x86_64_linux_gnu() -> Result<()> {
  function wheel_platform_tag_x86_64_linux_musl (line 602) | fn wheel_platform_tag_x86_64_linux_musl() -> Result<()> {
  function wheel_platform_tag_i686_linux_gnu (line 613) | fn wheel_platform_tag_i686_linux_gnu() -> Result<()> {
  function wheel_platform_tag_i686_linux_musl (line 624) | fn wheel_platform_tag_i686_linux_musl() -> Result<()> {
  function wheel_platform_tag_aarch64_linux_gnu (line 635) | fn wheel_platform_tag_aarch64_linux_gnu() -> Result<()> {
  function wheel_platform_tag_aarch64_linux_musl (line 649) | fn wheel_platform_tag_aarch64_linux_musl() -> Result<()> {
  function wheel_platform_tag_armv7_linux_gnu (line 664) | fn wheel_platform_tag_armv7_linux_gnu() -> Result<()> {
  function wheel_platform_tag_armv7_linux_musl (line 675) | fn wheel_platform_tag_armv7_linux_musl() -> Result<()> {
  function replace_uv_binary_overwrites_existing_file (line 689) | async fn replace_uv_binary_overwrites_existing_file() -> Result<()> {
  function replace_uv_binary_recreates_missing_parent_dir (line 708) | async fn replace_uv_binary_recreates_missing_parent_dir() -> Result<()> {

FILE: crates/prek/src/languages/python/version.rs
  type PythonRequest (line 10) | pub(crate) enum PythonRequest {
    method is_any (line 71) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 76) | fn parse_version_numbers(
    method satisfied_by (line 92) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
  type Err (line 35) | type Err = Error;
  method from_str (line 37) | fn from_str(request: &str) -> Result<Self, Self::Err> {
  function split_wheel_tag_version (line 116) | fn split_wheel_tag_version(mut version: Vec<u64>) -> Vec<u64> {
  function test_parse_python_request (line 143) | fn test_parse_python_request() {
  function test_satisfied_by (line 219) | fn test_satisfied_by() -> anyhow::Result<()> {

FILE: crates/prek/src/languages/ruby/gem.rs
  function find_gemspecs (line 17) | fn find_gemspecs(dir: &Path) -> Result<Vec<PathBuf>> {
  function build_gemspec (line 37) | async fn build_gemspec(ruby: &RubyResult, gemspec_path: &Path) -> Result...
  function build_gemspecs (line 74) | pub(crate) async fn build_gemspecs(ruby: &RubyResult, repo_dir: &Path) -...
  function gem_env (line 87) | fn gem_env<'a>(cmd: &'a mut Cmd, gem_home: &Path) -> &'a mut Cmd {
  type ResolvedGem (line 105) | struct ResolvedGem {
    method key (line 114) | fn key(&self) -> String {
  function parse_explain_output (line 128) | fn parse_explain_output(output: &str) -> Vec<ResolvedGem> {
  function resolve_gems (line 172) | async fn resolve_gems(
  function install_single_gem (line 200) | async fn install_single_gem(
  function install_gems_sequential (line 235) | async fn install_gems_sequential(
  function install_gems (line 266) | pub(crate) async fn install_gems(
  function gem (line 367) | fn gem(name: &str, version: &str, platform: Option<&str>) -> ResolvedGem {
  function test_parse_explain_output (line 376) | fn test_parse_explain_output() {
  function test_parse_explain_output_empty (line 397) | fn test_parse_explain_output_empty() {
  function test_parse_explain_output_platform_gems (line 403) | fn test_parse_explain_output_platform_gems() {
  function test_parse_explain_output_edge_cases (line 416) | fn test_parse_explain_output_edge_cases() {
  function test_resolved_gem_key (line 427) | fn test_resolved_gem_key() {

FILE: crates/prek/src/languages/ruby/installer.rs
  constant RV_RUBY_DEFAULT_URL (line 17) | const RV_RUBY_DEFAULT_URL: &str = "https://github.com/spinel-coop/rv-ruby";
  function rv_ruby_mirror (line 20) | fn rv_ruby_mirror() -> (String, bool) {
  function rv_ruby_api_url (line 37) | fn rv_ruby_api_url() -> (String, bool) {
  function is_github_https (line 55) | fn is_github_https(url: &str) -> bool {
  function rv_ruby_download_base (line 62) | fn rv_ruby_download_base() -> (String, bool) {
  function maybe_add_github_auth (line 69) | fn maybe_add_github_auth(req: reqwest::RequestBuilder, is_github: bool) ...
  type GitHubRelease (line 79) | struct GitHubRelease {
  type GitHubAsset (line 84) | struct GitHubAsset {
  function rv_platform_string (line 100) | fn rv_platform_string(triple: &Triple) -> Option<&'static str> {
  type RubyResult (line 129) | pub(crate) struct RubyResult {
    method ruby_bin (line 141) | pub(crate) fn ruby_bin(&self) -> &Path {
    method version (line 145) | pub(crate) fn version(&self) -> &semver::Version {
    method engine (line 149) | pub(crate) fn engine(&self) -> &str {
  type RubyInstaller (line 155) | pub(crate) struct RubyInstaller {
    method new (line 160) | pub(crate) fn new(root: PathBuf) -> Self {
    method install (line 165) | pub(crate) async fn install(
    method find_installed (line 236) | fn find_installed(&self, request: &RubyRequest) -> Option<RubyResult> {
    method list_remote_versions (line 267) | async fn list_remote_versions(&self, platform: &str) -> Result<Vec<sem...
    method download (line 311) | async fn download(
    method find_system_ruby (line 366) | async fn find_system_ruby(&self, request: &RubyRequest) -> Result<Opti...
  function try_ruby_path (line 387) | async fn try_ruby_path(ruby_path: &Path, request: &RubyRequest) -> Optio...
  function search_version_managers (line 418) | async fn search_version_managers(request: &RubyRequest) -> Option<RubyRe...
  function search_ruby_installations (line 461) | async fn search_ruby_installations(dir: &Path, request: &RubyRequest) ->...
  function parse_version_from_asset (line 490) | fn parse_version_from_asset(name: &str, platform_suffix: &str) -> Option...
  function ruby_not_found_error (line 502) | fn ruby_not_found_error(request: &RubyRequest, reason: &str) -> String {
  function find_gem_for_ruby (line 509) | fn find_gem_for_ruby(ruby_path: &Path) -> Result<PathBuf> {
  function query_ruby_info (line 535) | async fn query_ruby_info(ruby_path: &Path) -> Result<(semver::Version, S...
  type EnvVarGuard (line 569) | struct EnvVarGuard {
    method new (line 576) | fn new(key: &'static str) -> Self {
  method drop (line 590) | fn drop(&mut self) {
  function test_ruby_request_display (line 599) | fn test_ruby_request_display() {
  function test_search_ruby_installations_empty_dir (line 614) | async fn test_search_ruby_installations_empty_dir() {
  function test_search_ruby_installations_no_ruby (line 624) | async fn test_search_ruby_installations_no_ruby() {
  function test_search_ruby_installations_with_file (line 638) | async fn test_search_ruby_installations_with_file() {
  function test_ruby_not_found_error (line 656) | fn test_ruby_not_found_error() {
  function test_rv_ruby_urls_default (line 669) | fn test_rv_ruby_urls_default() {
  function test_rv_ruby_urls_github_mirror (line 689) | fn test_rv_ruby_urls_github_mirror() {
  function test_rv_ruby_urls_non_github_mirror (line 715) | fn test_rv_ruby_urls_non_github_mirror() {
  function test_find_gem_for_ruby_missing (line 741) | fn test_find_gem_for_ruby_missing() {
  function test_find_gem_for_ruby_found (line 760) | fn test_find_gem_for_ruby_found() {
  function test_parse_version_from_asset (line 777) | fn test_parse_version_from_asset() {
  function test_rv_platform_string_for_macos (line 818) | fn test_rv_platform_string_for_macos() {
  function test_rv_platform_string_for_linux (line 827) | fn test_rv_platform_string_for_linux() {
  function test_rv_platform_string_unsupported (line 842) | fn test_rv_platform_string_unsupported() {
  function test_find_installed_empty_dir (line 851) | fn test_find_installed_empty_dir() {
  function test_find_installed_with_versions (line 859) | fn test_find_installed_with_versions() {
  function test_is_github_https (line 897) | fn test_is_github_https() {
  function test_find_installed_skips_incomplete_dirs (line 922) | fn test_find_installed_skips_incomplete_dirs() {

FILE: crates/prek/src/languages/ruby/ruby.rs
  type Ruby (line 22) | pub(crate) struct Ruby;
  method install (line 25) | async fn install(
  method check_health (line 100) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 142) | async fn run(
  function gem_home (line 208) | fn gem_home(env_path: &Path) -> PathBuf {

FILE: crates/prek/src/languages/ruby/version.rs
  type RubyRequest (line 10) | pub(crate) enum RubyRequest {
    method fmt (line 31) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method is_any (line 85) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 90) | fn parse_version_numbers(
    method matches (line 108) | pub(crate) fn matches(&self, version: &semver::Version, toolchain: Opt...
    method satisfied_by (line 125) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
  type Err (line 44) | type Err = Error;
  method from_str (line 46) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  function test_parse_ruby_request (line 140) | fn test_parse_ruby_request() {
  function test_version_matching (line 180) | fn test_version_matching() -> anyhow::Result<()> {

FILE: crates/prek/src/languages/rust/installer.rs
  type RustResult (line 16) | pub(crate) struct RustResult {
    method from_dir (line 29) | pub(crate) fn from_dir(dir: &Path) -> Self {
    method toolchain (line 36) | pub(crate) fn toolchain(&self) -> &Path {
    method version (line 40) | pub(crate) fn version(&self) -> &RustVersion {
    method with_version (line 44) | pub(crate) fn with_version(mut self, version: RustVersion) -> Self {
    method fill_version (line 49) | pub(crate) async fn fill_version(mut self) -> Result<Self> {
  method fmt (line 22) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type RustInstaller (line 79) | pub(crate) struct RustInstaller {
    method new (line 84) | pub(crate) fn new(rustup: Rustup) -> Self {
    method install (line 88) | pub(crate) async fn install(
    method find_installed (line 118) | async fn find_installed(&self, request: &RustRequest) -> Result<RustRe...
    method find_system_rust (line 141) | async fn find_system_rust(&self, rust_request: &RustRequest) -> Result...
    method resolve_version (line 166) | async fn resolve_version(&self, req: &RustRequest) -> Result<RustVersi...
    method download (line 203) | async fn download(&self, toolchain: &RustVersion) -> Result<RustResult> {

FILE: crates/prek/src/languages/rust/rust.rs
  function format_cargo_dependency (line 27) | fn format_cargo_dependency(dep: &str) -> String {
  type CargoCliDependency (line 37) | enum CargoCliDependency {
    method to_cargo_args (line 103) | fn to_cargo_args(&self) -> Vec<&str> {
  type Err (line 50) | type Err = anyhow::Error;
  method from_str (line 52) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  function find_package_dir (line 132) | async fn find_package_dir(
  function names_match (line 194) | fn names_match(a: &str, b: &str) -> bool {
  function package_produces_binary (line 199) | fn package_produces_binary(package: &cargo_metadata::Package, binary_nam...
  function copy_binaries (line 208) | async fn copy_binaries(release_dir: &Path, dest_bin_dir: &Path) -> anyho...
  function install_local_project (line 243) | async fn install_local_project(
  function install_cli_dependency (line 382) | async fn install_cli_dependency(
  type Rust (line 408) | pub(crate) struct Rust;
  method install (line 411) | async fn install(
  method check_health (line 507) | async fn check_health(&self, _info: &InstallInfo) -> anyhow::Result<()> {
  method run (line 511) | async fn run(
  function bin_dir (line 568) | pub(crate) fn bin_dir(env_path: &Path) -> PathBuf {
  function write_file (line 577) | async fn write_file(path: &Path, content: &str) {
  function test_find_package_dir_single_package (line 585) | async fn test_find_package_dir_single_package() {
  function test_find_package_dir_single_package_underscore_normalization (line 607) | async fn test_find_package_dir_single_package_underscore_normalization() {
  function test_find_package_dir_workspace_with_root_package (line 628) | async fn test_find_package_dir_workspace_with_root_package() {
  function test_find_package_dir_workspace_member (line 663) | async fn test_find_package_dir_workspace_member() {
  function test_find_package_dir_by_bin_name (line 700) | async fn test_find_package_dir_by_bin_name() {
  function test_find_package_dir_by_src_bin_file (line 739) | async fn test_find_package_dir_by_src_bin_file() {
  function test_find_package_dir_virtual_workspace_nested_member (line 762) | async fn test_find_package_dir_virtual_workspace_nested_member() {
  function test_find_package_dir_virtual_workspace_glob_members (line 791) | async fn test_find_package_dir_virtual_workspace_glob_members() {
  function test_find_package_dir_no_cargo_toml (line 835) | async fn test_find_package_dir_no_cargo_toml() {
  function test_find_package_dir_workspace_binary_not_found (line 845) | async fn test_find_package_dir_workspace_binary_not_found() {
  function test_format_cargo_dependency (line 869) | fn test_format_cargo_dependency() {
  function test_parse_cargo_cli_dependency_crate_forms (line 876) | fn test_parse_cargo_cli_dependency_crate_forms() {
  function test_parse_cargo_cli_dependency_git_valid_forms (line 894) | fn test_parse_cargo_cli_dependency_git_valid_forms() {
  function test_parse_cargo_cli_dependency_git_invalid_forms (line 936) | fn test_parse_cargo_cli_dependency_git_invalid_forms() {
  function test_format_cargo_cli_dependency (line 952) | fn test_format_cargo_cli_dependency() {

FILE: crates/prek/src/languages/rust/rustup.rs
  type Rustup (line 19) | pub(crate) struct Rustup {
    method rustup_home (line 36) | pub(crate) fn rustup_home(&self) -> &Path {
    method install (line 41) | pub(crate) async fn install(store: &Store, rustup_home: &Path) -> Resu...
    method download (line 79) | async fn download(store: &Store, rustup_home: &Path) -> Result<Self> {
    method install_toolchain (line 126) | pub(crate) async fn install_toolchain(&self, toolchain: &str) -> Resul...
    method list_installed_toolchains (line 165) | pub(crate) async fn list_installed_toolchains(&self) -> Result<Vec<Too...
    method list_system_toolchains (line 199) | pub(crate) async fn list_system_toolchains(&self) -> Result<Vec<Toolch...
  type ToolchainInfo (line 24) | pub(crate) struct ToolchainInfo {
  function parse_toolchain_line (line 232) | fn parse_toolchain_line(line: &str) -> Option<(String, PathBuf)> {
  function toolchain_info (line 247) | async fn toolchain_info(name: String, toolchain_dir: PathBuf) -> Result<...
  function make_executable (line 274) | fn make_executable(path: &Path) -> std::io::Result<()> {

FILE: crates/prek/src/languages/rust/version.rs
  type Channel (line 10) | pub(crate) enum Channel {
  type Err (line 17) | type Err = ();
  method from_str (line 19) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  method fmt (line 30) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type RustVersion (line 41) | pub(crate) struct RustVersion {
    method from_version (line 64) | pub(crate) fn from_version(version: &semver::Version) -> Self {
    method from_channel (line 71) | pub(crate) fn from_channel(channel: Channel) -> Self {
    method from_path (line 78) | pub(crate) fn from_path(version: &semver::Version, path: &Path) -> Self {
    method to_toolchain_name (line 99) | pub(crate) fn to_toolchain_name(&self) -> String {
  method default (line 47) | fn default() -> Self {
  type Target (line 56) | type Target = semver::Version;
  method deref (line 58) | fn deref(&self) -> &Self::Target {
  type RustRequest (line 120) | pub(crate) enum RustRequest {
    method is_any (line 169) | pub(crate) fn is_any(&self) -> bool {
    method parse_version_numbers (line 173) | fn parse_version_numbers(
    method satisfied_by (line 188) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
    method matches (line 213) | pub(crate) fn matches(&self, version: &RustVersion, _toolchain: Option...
  type Err (line 130) | type Err = Error;
  method from_str (line 132) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  method fmt (line 152) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  constant EXTRA_KEY_CHANNEL (line 166) | pub(crate) const EXTRA_KEY_CHANNEL: &str = "channel";
  function test_request_from_str (line 244) | fn test_request_from_str() -> anyhow::Result<()> {
  function test_invalid_requests (line 278) | fn test_invalid_requests() {
  function test_request_matches (line 286) | fn test_request_matches() -> anyhow::Result<()> {
  function test_request_satisfied_by_install_info (line 311) | fn test_request_satisfied_by_install_info() -> anyhow::Result<()> {
  function test_satisfied_by_channel (line 341) | fn test_satisfied_by_channel() -> anyhow::Result<()> {
  function test_satisfied_by_any_with_stable_channel (line 359) | fn test_satisfied_by_any_with_stable_channel() -> anyhow::Result<()> {
  function test_satisfied_by_any_without_channel (line 375) | fn test_satisfied_by_any_without_channel() -> anyhow::Result<()> {

FILE: crates/prek/src/languages/script.rs
  type Script (line 16) | pub(crate) struct Script;
  method install (line 19) | async fn install(
  method check_health (line 28) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 32) | async fn run(

FILE: crates/prek/src/languages/swift.rs
  type Swift (line 19) | pub(crate) struct Swift;
  type SwiftInfo (line 21) | pub(crate) struct SwiftInfo {
  function query_swift_info (line 26) | pub(crate) async fn query_swift_info() -> Result<SwiftInfo> {
  function normalize_version (line 50) | fn normalize_version(version_str: &str) -> String {
  function parse_swift_version (line 60) | fn parse_swift_version(output: &str) -> Option<Version> {
  function build_dir (line 80) | fn build_dir(env_path: &Path) -> PathBuf {
  constant BIN_PATH_KEY (line 84) | const BIN_PATH_KEY: &str = "swift_bin_path";
  method install (line 87) | async fn install(
  method check_health (line 163) | async fn check_health(&self, info: &InstallInfo) -> Result<()> {
  method run (line 175) | async fn run(
  function test_parse_macos_format (line 235) | fn test_parse_macos_format() {
  function test_parse_linux_format (line 245) | fn test_parse_linux_format() {
  function test_parse_multiline_output (line 255) | fn test_parse_multiline_output() {
  function test_parse_linux_multiline (line 266) | fn test_parse_linux_multiline() {
  function test_parse_invalid_output (line 277) | fn test_parse_invalid_output() {
  function test_parse_version_without_patch (line 284) | fn test_parse_version_without_patch() {
  function test_parse_dev_version (line 301) | fn test_parse_dev_version() {

FILE: crates/prek/src/languages/system.rs
  type System (line 15) | pub(crate) struct System;
  method install (line 18) | async fn install(
  method check_health (line 27) | async fn check_health(&self, _info: &InstallInfo) -> Result<()> {
  method run (line 31) | async fn run(

FILE: crates/prek/src/languages/version.rs
  type Error (line 14) | pub(crate) enum Error {
  type LanguageRequest (line 20) | pub(crate) enum LanguageRequest {
    method is_any (line 34) | pub(crate) fn is_any(&self) -> bool {
    method allows_download (line 53) | pub(crate) fn allows_download(&self) -> bool {
    method parse (line 60) | pub(crate) fn parse(lang: Language, request: &str) -> Result<Self, Err...
    method satisfied_by (line 90) | pub(crate) fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
  type SemverRequest (line 106) | pub(crate) struct SemverRequest(semver::VersionReq);
    method satisfied_by (line 119) | fn satisfied_by(&self, install_info: &InstallInfo) -> bool {
  type Err (line 109) | type Err = Error;
  method from_str (line 111) | fn from_str(request: &str) -> Result<Self, Self::Err> {
  function try_into_u64_slice (line 124) | pub(crate) fn try_into_u64_slice(version: &str) -> Result<Vec<u64>, std:...

FILE: crates/prek/src/main.rs
  type Level (line 58) | pub(crate) enum Level {
  type LogFile (line 72) | enum LogFile {
    method from_args (line 79) | fn from_args(log_file: Option<PathBuf>, no_log_file: bool) -> Self {
    method is_disabled (line 89) | fn is_disabled(&self) -> bool {
  function setup_logging (line 94) | fn setup_logging(level: Level, log_file: LogFile, store: &Store) -> Resu...
  function run (line 148) | async fn run(cli: Cli) -> Result<ExitStatus> {
  function main (line 487) | fn main() -> ExitCode {

FILE: crates/prek/src/printer.rs
  type Printer (line 27) | pub enum Printer {
    method target (line 42) | pub fn target(self) -> ProgressDrawTarget {
    method stdout_important (line 55) | pub(crate) fn stdout_important(self) -> Stdout {
    method stdout (line 66) | pub(crate) fn stdout(self) -> Stdout {
    method stderr (line 77) | pub(crate) fn stderr(self) -> Stderr {
  type Stdout (line 89) | pub enum Stdout {
    method write_str (line 95) | fn write_str(&mut self, s: &str) -> std::fmt::Result {
  type Stderr (line 111) | pub enum Stderr {
    method write_str (line 117) | fn write_str(&mut self, s: &str) -> std::fmt::Result {

FILE: crates/prek/src/process.rs
  type Error (line 52) | pub enum Error {
  type StatusError (line 74) | pub struct StatusError {
  method fmt (line 80) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Cmd (line 114) | pub struct Cmd {
    method new (line 124) | pub fn new(command: impl AsRef<OsStr>, summary: impl Into<String>) -> ...
    method stdout_to_stderr (line 141) | pub fn stdout_to_stderr(&mut self) -> &mut Self {
    method check (line 156) | pub fn check(&mut self, checked: bool) -> &mut Self {
    method run (line 166) | pub async fn run(&mut self) -> Result<(), Error> {
    method spawn (line 173) | pub fn spawn(&mut self) -> Result<tokio::process::Child, Error> {
    method output (line 183) | pub async fn output(&mut self) -> Result<Output, Error> {
    method pty_output (line 194) | pub async fn pty_output(&mut self) -> Result<Output, Error> {
    method pty_output (line 199) | pub async fn pty_output(&mut self) -> Result<Output, Error> {
    method pty_output_inner (line 209) | async fn pty_output_inner(&mut self) -> Result<Output, Error> {
    method status (line 283) | pub async fn status(&mut self) -> Result<ExitStatus, Error> {
    method arg (line 317) | pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
    method args (line 323) | pub fn args<I, S>(&mut self, args: I) -> &mut Self
    method env (line 333) | pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self
    method envs (line 343) | pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
    method env_remove (line 354) | pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Self {
    method env_clear (line 360) | pub fn env_clear(&mut self) -> &mut Self {
    method current_dir (line 366) | pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Self {
    method stdin (line 372) | pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
    method stdout (line 378) | pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
    method stderr (line 384) | pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
    method get_program (line 390) | pub fn get_program(&self) -> &OsStr {
    method get_args (line 395) | pub fn get_args(&self) -> CommandArgs<'_> {
    method get_envs (line 400) | pub fn get_envs(&self) -> CommandEnvs<'_> {
    method get_current_dir (line 405) | pub fn get_current_dir(&self) -> Option<&Path> {
    method remove_git_envs (line 410) | pub fn remove_git_envs(&mut self) -> &mut Self {
    method check_status (line 421) | pub fn check_status(&self, status: ExitStatus) -> Result<(), Error> {
    method check_output (line 435) | pub fn check_output(&self, output: &Output) -> Result<(), Error> {
    method maybe_check_status (line 451) | pub fn maybe_check_status(&self, status: ExitStatus) -> Result<(), Err...
    method maybe_check_output (line 460) | pub fn maybe_check_output(&self, output: &Output) -> Result<(), Error> {
    method log_command (line 469) | pub fn log_command(&self) {
  function drain_ready_pty (line 295) | async fn drain_ready_pty(
  function skip_args (line 475) | fn skip_args(cmd: &OsStr, cur: &OsStr, next: Option<&&OsStr>) -> usize {
  method fmt (line 499) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  function pty_output_captures_trailing_output_after_fast_exit (line 536) | async fn pty_output_captures_trailing_output_after_fast_exit() {

FILE: crates/prek/src/profiler.rs
  function start_profiling (line 4) | pub(crate) fn start_profiling() -> Option<pprof::ProfilerGuard<'static>> {
  function finish_profiling (line 19) | pub(crate) fn finish_profiling(profiler_guard: Option<pprof::ProfilerGua...

FILE: crates/prek/src/resource_limit.rs
  type OpenFileLimitError (line 42) | pub enum OpenFileLimitError {
  constant MAX_NOFILE_LIMIT (line 67) | const MAX_NOFILE_LIMIT: u64 = 0x0010_0000;
  function adjust_open_file_limit (line 79) | pub fn adjust_open_file_limit() -> Result<u64, OpenFileLimitError> {

FILE: crates/prek/src/run.rs
  function resolve_concurrency (line 24) | fn resolve_concurrency(no_concurrency: bool, max_concurrency: Option<&st...
  function target_concurrency (line 54) | fn target_concurrency(serial: bool) -> usize {
  type Partitions (line 59) | struct Partitions<'a> {
  constant POINTER_SIZE_CONSERVATIVE (line 69) | const POINTER_SIZE_CONSERVATIVE: usize = 8;
  constant ARG_HEADROOM (line 73) | const ARG_HEADROOM: usize = 2048;
  function environment_variable_size (line 78) | fn environment_variable_size<O: AsRef<OsStr>>(key: O, value: O) -> usize {
  function arg_size (line 88) | fn arg_size<O: AsRef<OsStr>>(arg: O) -> usize {
  function platform_max_cli_length (line 119) | fn platform_max_cli_length() -> usize {
  function env_size (line 140) | fn env_size(override_envs: &FxHashMap<String, String>) -> usize {
  function split (line 162) | fn split(
  type Item (line 216) | type Item = &'a [&'a Path];
  method next (line 218) | fn next(&mut self) -> Option<Self::Item> {
  function run_by_batch (line 259) | pub(crate) async fn run_by_batch<T, F>(
  function create_test_partitions (line 297) | fn create_test_partitions<'a>(
  function test_partitions_normal_filenames (line 311) | fn test_partitions_normal_filenames() {
  function test_partitions_empty_filenames (line 326) | fn test_partitions_empty_filenames() {
  function test_partitions_long_filename_in_middle_panics (line 342) | fn test_partitions_long_filename_in_middle_panics() {
  function test_partitions_respects_max_per_batch (line 361) | fn test_partitions_respects_max_per_batch() {
  function test_resolve_concurrency_defaults_to_cpu (line 381) | fn test_resolve_concurrency_defaults_to_cpu() {
  function test_resolve_concurrency_max_caps_value (line 386) | fn test_resolve_concurrency_max_caps_value() {
  function test_resolve_concurrency_max_above_cpu (line 391) | fn test_resolve_concurrency_max_above_cpu() {
  function test_resolve_concurrency_max_zero_floors_to_one (line 396) | fn test_resolve_concurrency_max_zero_floors_to_one() {
  function test_resolve_concurrency_max_invalid_falls_back (line 401) | fn test_resolve_concurrency_max_invalid_falls_back() {
  function test_resolve_concurrency_max_empty_falls_back (line 406) | fn test_resolve_concurrency_max_empty_falls_back() {
  function test_resolve_concurrency_no_concurrency (line 411) | fn test_resolve_concurrency_no_concurrency() {
  function test_resolve_concurrency_no_concurrency_overrides_max (line 416) | fn test_resolve_concurrency_no_concurrency_overrides_max() {
  function test_partitions_respects_cli_length_limit (line 421) | fn test_partitions_respects_cli_length_limit() {

FILE: crates/prek/src/schema.rs
  type RemoveNullTypes (line 8) | struct RemoveNullTypes;
    method transform (line 11) | fn transform(&mut self, schema: &mut schemars::Schema) {
  function strip_null_acceptance (line 17) | fn strip_null_acceptance(schema: &mut schemars::Schema) {
  method inline_schema (line 124) | fn inline_schema() -> bool {
  method schema_name (line 128) | fn schema_name() -> Cow<'static, str> {
  method json_schema (line 132) | fn json_schema(generator: &mut schemars::generate::SchemaGenerator) -> s...
  method schema_name (line 143) | fn schema_name() -> Cow<'static, str> {
  method json_schema (line 147) | fn json_schema(_gen: &mut schemars::generate::SchemaGenerator) -> schema...
  method schema_name (line 182) | fn schema_name() -> std::borrow::Cow<'static, str> {
  method json_schema (line 186) | fn json_schema(_gen: &mut schemars::generate::SchemaGenerator) -> schema...
  function predefined_hook_schema (line 200) | fn predefined_hook_schema(
  method schema_name (line 239) | fn schema_name() -> Cow<'static, str> {
  method json_schema (line 243) | fn json_schema(schema_gen: &mut schemars::SchemaGenerator) -> schemars::...
  method schema_name (line 252) | fn schema_name() -> Cow<'static, str> {
  method json_schema (line 256) | fn json_schema(r#gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
  function schema_repo_local (line 264) | pub(crate) fn schema_repo_local(
  function schema_repo_meta (line 274) | pub(crate) fn schema_repo_meta(_gen: &mut schemars::generate::SchemaGene...
  function schema_repo_builtin (line 282) | pub(crate) fn schema_repo_builtin(
  function schema_repo_remote (line 292) | pub(crate) fn schema_repo_remote(
  method schema_name (line 305) | fn schema_name() -> Cow<'static, str> {
  method json_schema (line 309) | fn json_schema(r#gen: &mut schemars::generate::SchemaGenerator) -> schem...
  constant ROOT_DIR (line 338) | const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
  type Mode (line 340) | enum Mode {
  function generate (line 351) | fn generate() -> String {
  function generate_json_schema (line 361) | fn generate_json_schema() -> anyhow::Result<()> {

FILE: crates/prek/src/store.rs
  type PendingClone (line 23) | struct PendingClone<'a> {
  type FirstClonePass (line 27) | enum FirstClonePass<'a> {
  type Error (line 41) | pub enum Error {
  function expand_tilde (line 57) | fn expand_tilde(path: PathBuf) -> PathBuf {
  constant REPO_MARKER (line 66) | pub(crate) const REPO_MARKER: &str = ".prek-repo.json";
  type Store (line 70) | pub struct Store {
    method from_path (line 75) | pub(crate) fn from_path(path: impl Into<PathBuf>) -> Self {
    method from_settings (line 80) | pub(crate) fn from_settings() -> Result<Self, Error> {
    method path (line 97) | pub(crate) fn path(&self) -> &Path {
    method init (line 102) | pub(crate) fn init(self) -> Result<Self, Error> {
    method clone_repo_to_temp (line 119) | async fn clone_repo_to_temp(
    method persist_cloned_repo (line 135) | async fn persist_cloned_repo(
    method clone_repos (line 157) | pub(crate) async fn clone_repos<'a>(
    method clone_repo (line 275) | pub(crate) async fn clone_repo(
    method installed_hooks (line 289) | pub(crate) async fn installed_hooks(&self) -> Vec<Arc<InstallInfo>> {
    method lock_async (line 324) | pub(crate) async fn lock_async(&self) -> Result<LockedFile, std::io::E...
    method repo_path (line 329) | pub(crate) fn repo_path(&self, repo: &RemoteRepo) -> PathBuf {
    method repo_key (line 334) | pub(crate) fn repo_key(repo: &RemoteRepo) -> String {
    method repos_dir (line 340) | pub(crate) fn repos_dir(&self) -> PathBuf {
    method hooks_dir (line 344) | pub(crate) fn hooks_dir(&self) -> PathBuf {
    method patches_dir (line 348) | pub(crate) fn patches_dir(&self) -> PathBuf {
    method tools_dir (line 352) | pub(crate) fn tools_dir(&self) -> PathBuf {
    method cache_dir (line 356) | pub(crate) fn cache_dir(&self) -> PathBuf {
    method tools_path (line 361) | pub(crate) fn tools_path(&self, tool: ToolBucket) -> PathBuf {
    method cache_path (line 365) | pub(crate) fn cache_path(&self, tool: CacheBucket) -> PathBuf {
    method scratch_path (line 370) | pub(crate) fn scratch_path(&self) -> PathBuf {
    method log_file (line 374) | pub(crate) fn log_file(&self) -> PathBuf {
    method config_tracking_file (line 378) | pub(crate) fn config_tracking_file(&self) -> PathBuf {
    method tracked_configs (line 386) | pub(crate) fn tracked_configs(&self) -> Result<FxHashSet<PathBuf>, Err...
    method track_configs (line 415) | pub(crate) fn track_configs<'a>(
    method update_tracked_configs (line 432) | pub(crate) fn update_tracked_configs(&self, configs: &FxHashSet<PathBu...
  type ToolBucket (line 443) | pub(crate) enum ToolBucket {
  type CacheBucket (line 456) | pub(crate) enum CacheBucket {
  function to_hex (line 466) | fn to_hex(num: u64) -> String {

FILE: crates/prek/src/version.rs
  type CommitInfo (line 31) | pub(crate) struct CommitInfo {
  type VersionInfo (line 41) | pub(crate) struct VersionInfo {
    method fmt (line 52) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function from (line 67) | fn from(val: VersionInfo) -> Self {
  function version (line 73) | pub fn version() -> VersionInfo {

FILE: crates/prek/src/warnings.rs
  function enable (line 37) | pub fn enable() {
  function disable (line 42) | pub fn disable() {

FILE: crates/prek/src/workspace.rs
  type Error (line 28) | pub(crate) enum Error {
  type HookInitReporter (line 51) | pub(crate) trait HookInitReporter {
    method on_clone_start (line 52) | fn on_clone_start(&self, repo: &str) -> usize;
    method on_clone_complete (line 53) | fn on_clone_complete(&self, id: usize);
    method on_complete (line 54) | fn on_complete(&self);
  type Project (line 58) | pub(crate) struct Project {
    method fmt (line 72) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    method from_config_file (line 109) | pub(crate) fn from_config_file(
    method find_config (line 155) | fn find_config(path: &Path) -> Option<PathBuf> {
    method find_all_configs (line 165) | fn find_all_configs(path: &Path) -> Vec<(&'static str, PathBuf)> {
    method from_directory (line 177) | pub(crate) fn from_directory(path: &Path) -> Result<Self, Error> {
    method discover (line 201) | pub(crate) fn discover(config_file: Option<&Path>, dir: &Path) -> Resu...
    method with_relative_path (line 214) | pub(crate) fn with_relative_path(&mut self, relative_path: PathBuf) {
    method with_idx (line 218) | fn with_idx(&mut self, idx: usize) {
    method config (line 222) | pub(crate) fn config(&self) -> &Config {
    method config_file (line 228) | pub(crate) fn config_file(&self) -> &Path {
    method path (line 233) | pub(crate) fn path(&self) -> &Path {
    method relative_path (line 241) | pub(crate) fn relative_path(&self) -> &Path {
    method is_root (line 245) | pub(crate) fn is_root(&self) -> bool {
    method depth (line 249) | pub(crate) fn depth(&self) -> usize {
    method idx (line 253) | pub(crate) fn idx(&self) -> usize {
    method init_hooks (line 258) | pub(crate) async fn init_hooks(
    method init_repos (line 274) | async fn init_repos(
    method internal_init_hooks (line 328) | async fn internal_init_hooks(self: Arc<Self>) -> Result<Vec<Hook>, Err...
  method fmt (line 83) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  method eq (line 93) | fn eq(&self, other: &Self) -> bool {
  method hash (line 101) | fn hash<H: Hasher>(&self, state: &mut H) {
  type CachedConfigFile (line 411) | struct CachedConfigFile {
  type WorkspaceCache (line 422) | pub(crate) struct WorkspaceCache {
    constant CURRENT_VERSION (line 434) | const CURRENT_VERSION: u32 = 1;
    constant MAX_CACHE_AGE (line 436) | const MAX_CACHE_AGE: u64 = 60 * 60;
    method new (line 439) | fn new(workspace_root: PathBuf, projects: &[Project]) -> Self {
    method is_valid (line 461) | fn is_valid(&self) -> bool {
    method cache_path (line 511) | fn cache_path(store: &Store, workspace_root: &Path) -> PathBuf {
    method load (line 523) | fn load(store: &Store, workspace_root: &Path, refresh: bool) -> Option...
    method save (line 555) | fn save(&self, store: &Store) -> Result<()> {
    method cached_config_paths (line 573) | pub(crate) fn cached_config_paths(store: &Store) -> FxHashSet<PathBuf> {
  type Workspace (line 629) | pub(crate) struct Workspace {
    method find_root (line 638) | pub(crate) fn find_root(config_file: Option<&Path>, dir: &Path) -> Res...
    method discover (line 660) | pub(crate) fn discover(
    method discover_fresh (line 762) | fn discover_fresh(root: &Path, selectors: Option<&Selectors>) -> Resul...
    method sort_and_index_projects (line 860) | fn sort_and_index_projects(projects: &mut [Project]) {
    method root (line 877) | pub(crate) fn root(&self) -> &Path {
    method projects (line 881) | pub(crate) fn projects(&self) -> &[Arc<Project>] {
    method all_projects (line 885) | pub(crate) fn all_projects(&self) -> &[Project] {
    method init_repos (line 890) | async fn init_repos(
    method init_hooks (line 956) | pub(crate) async fn init_hooks(
    method check_configs_staged (line 975) | pub(crate) async fn check_configs_staged(&self) -> Result<()> {

FILE: crates/prek/src/yaml.rs
  function serialize_yaml_scalar (line 10) | pub(crate) fn serialize_yaml_scalar(value: &str, quote: &str) -> anyhow:...
  function is_simple_plain (line 27) | fn is_simple_plain(value: &str) -> bool {
  function escape_single_quoted (line 37) | fn escape_single_quoted(value: &str) -> String {
  function escape_double_quoted (line 42) | fn escape_double_quoted(value: &str) -> String {
  function serialize_yaml_scalar_plain (line 65) | fn serialize_yaml_scalar_plain() {
  function serialize_yaml_scalar_quotes_and_escapes (line 96) | fn serialize_yaml_scalar_quotes_and_escapes() {

FILE: crates/prek/tests/auto_update.rs
  constant BASE_TIMESTAMP (line 12) | const BASE_TIMESTAMP: u64 = 1_000_000_000;
  constant INCREMENTING_STEP_SECS (line 13) | const INCREMENTING_STEP_SECS: u64 = 100;
  constant FIXED_STEP_SECS (line 14) | const FIXED_STEP_SECS: u64 = 0;
  function create_local_git_repo (line 17) | fn create_local_git_repo(context: &TestContext, repo_name: &str, tags: &...
  function create_local_git_repo_fixed_ts (line 23) | fn create_local_git_repo_fixed_ts(
  function create_local_git_repo_with_timestamps (line 31) | fn create_local_git_repo_with_timestamps(
  function auto_update_basic (line 113) | fn auto_update_basic() -> Result<()> {
  function auto_update_already_up_to_date (line 156) | fn auto_update_already_up_to_date() -> Result<()> {
  function auto_update_does_not_rewrite_config_when_up_to_date (line 201) | fn auto_update_does_not_rewrite_config_when_up_to_date() -> Result<()> {
  function auto_update_multiple_repos_mixed (line 244) | fn auto_update_multiple_repos_mixed() -> Result<()> {
  function test_resolve_revision_ignores_git_dir_env_var (line 307) | fn test_resolve_revision_ignores_git_dir_env_var() -> Result<()> {
  function auto_update_specific_repos (line 356) | fn auto_update_specific_repos() -> Result<()> {
  function auto_update_bleeding_edge (line 438) | fn auto_update_bleeding_edge() -> Result<()> {
  function auto_update_freeze (line 486) | fn auto_update_freeze() -> Result<()> {
  function auto_update_freeze_uses_dereferenced_commit_for_annotated_tags (line 544) | fn auto_update_freeze_uses_dereferenced_commit_for_annotated_tags() -> R...
  function auto_update_preserve_quote_style (line 603) | fn auto_update_preserve_quote_style() -> Result<()> {
  function auto_update_with_existing_frozen_comment (line 680) | fn auto_update_with_existing_frozen_comment() -> Result<()> {
  function auto_update_local_repo_ignored (line 731) | fn auto_update_local_repo_ignored() -> Result<()> {
  function missing_hook_ids (line 787) | fn missing_hook_ids() -> Result<()> {
  function auto_update_workspace (line 842) | fn auto_update_workspace() -> Result<()> {
  function prefer_similar_tags (line 942) | fn prefer_similar_tags() -> Result<()> {
  function auto_update_dry_run (line 1021) | fn auto_update_dry_run() -> Result<()> {
  function quoting_float_like_version_number (line 1064) | fn quoting_float_like_version_number() -> Result<()> {
  function auto_update_with_invalid_config_file (line 1109) | fn auto_update_with_invalid_config_file() -> Result<()> {
  function auto_update_toml (line 1139) | fn auto_update_toml() -> Result<()> {
  function auto_update_toml_with_comment (line 1188) | fn auto_update_toml_with_comment() -> Result<()> {
  function auto_update_freeze_toml (line 1276) | fn auto_update_freeze_toml() -> Result<()> {
  function auto_update_equal_timestamp_tags_picks_highest_version (line 1339) | fn auto_update_equal_timestamp_tags_picks_highest_version() -> Result<()> {
  function auto_update_equal_timestamp_prefers_semver_over_nonsemver (line 1388) | fn auto_update_equal_timestamp_prefers_semver_over_nonsemver() -> Result...
  function auto_update_mixed_timestamps_with_equal_subgroups (line 1438) | fn auto_update_mixed_timestamps_with_equal_subgroups() -> Result<()> {
  function auto_update_freeze_toml_with_comment (line 1507) | fn auto_update_freeze_toml_with_comment() -> Result<()> {

FILE: crates/prek/tests/builtin_hooks.rs
  function builtin_hooks_not_create_env (line 17) | fn builtin_hooks_not_create_env() {
  function builtin_hooks_unknown_hook (line 50) | fn builtin_hooks_unknown_hook() {
  function end_of_file_fixer_hook (line 80) | fn end_of_file_fixer_hook() -> Result<()> {
  function check_yaml_hook (line 153) | fn check_yaml_hook() -> Result<()> {
  function check_yaml_multiple_document (line 218) | fn check_yaml_multiple_document() -> Result<()> {
  function check_json_hook (line 270) | fn check_json_hook() -> Result<()> {
  function mixed_line_ending_hook (line 328) | fn mixed_line_ending_hook() -> Result<()> {
  function check_added_large_files_hook (line 484) | fn check_added_large_files_hook() -> Result<()> {
  function tracked_file_exceeds_large_file_limit (line 587) | fn tracked_file_exceeds_large_file_limit() -> Result<()> {
  function builtin_hooks_workspace_mode (line 624) | fn builtin_hooks_workspace_mode() -> Result<()> {
  function fix_byte_order_marker_hook (line 842) | fn fix_byte_order_marker_hook() -> Result<()> {
  function check_symlinks_hook_unix (line 906) | fn check_symlinks_hook_unix() -> Result<()> {
  function check_symlinks_hook_windows (line 970) | fn check_symlinks_hook_windows() -> Result<()> {
  function detect_private_key_hook (line 1039) | fn detect_private_key_hook() -> Result<()> {
  function check_merge_conflict_hook (line 1129) | fn check_merge_conflict_hook() -> Result<()> {
  function check_merge_conflict_without_assume_flag (line 1208) | fn check_merge_conflict_without_assume_flag() -> Result<()> {
  function check_xml_hook (line 1247) | fn check_xml_hook() -> Result<()> {
  function check_xml_with_features (line 1346) | fn check_xml_with_features() -> Result<()> {
  function no_commit_to_branch_hook (line 1403) | fn no_commit_to_branch_hook() -> Result<()> {
  function no_commit_to_branch_hook_with_custom_branches (line 1476) | fn no_commit_to_branch_hook_with_custom_branches() -> Result<()> {
  function no_commit_to_branch_hook_with_patterns (line 1550) | fn no_commit_to_branch_hook_with_patterns() -> Result<()> {
  function check_executables_have_shebangs_hook (line 1682) | fn check_executables_have_shebangs_hook() -> Result<()> {
  function check_executables_have_shebangs_win (line 1766) | fn check_executables_have_shebangs_win() -> Result<()> {
  function check_executables_have_shebangs_various_cases (line 1822) | fn check_executables_have_shebangs_various_cases() -> Result<()> {
  function check_executables_have_shebangs_various_cases_win (line 1916) | fn check_executables_have_shebangs_various_cases_win() -> Result<()> {
  function is_case_sensitive_filesystem (line 1983) | fn is_case_sensitive_filesystem(context: &TestContext) -> Result<bool> {
  function check_case_conflict_hook (line 1993) | fn check_case_conflict_hook() -> Result<()> {
  function check_case_conflict_directory (line 2056) | fn check_case_conflict_directory() -> Result<()> {
  function check_case_conflict_among_new_files (line 2100) | fn check_case_conflict_among_new_files() -> Result<()> {
  function check_json5 (line 2146) | fn check_json5() -> Result<()> {
  function builtin_hooks_ignore_system_path_binaries (line 2223) | fn builtin_hooks_ignore_system_path_binaries() -> Result<()> {

FILE: crates/prek/tests/cache.rs
  function cache_dir (line 12) | fn cache_dir() {
  function cache_gc_verbose_shows_removed_entries (line 27) | fn cache_gc_verbose_shows_removed_entries() {
  function cache_clean (line 106) | fn cache_clean() -> anyhow::Result<()> {
  function cache_size (line 145) | fn cache_size() -> anyhow::Result<()> {
  function cache_gc_removes_unreferenced_entries (line 185) | fn cache_gc_removes_unreferenced_entries() -> anyhow::Result<()> {
  function cache_gc_prunes_unused_tool_versions (line 254) | fn cache_gc_prunes_unused_tool_versions() -> anyhow::Result<()> {
  function cache_gc_prunes_tool_versions_without_positive_identification (line 408) | fn cache_gc_prunes_tool_versions_without_positive_identification() -> an...
  function cache_gc_keeps_local_hook_env (line 491) | fn cache_gc_keeps_local_hook_env() -> anyhow::Result<()> {
  function write_config_tracking_file (line 564) | fn write_config_tracking_file(
  function write_workspace_cache_file (line 577) | fn write_workspace_cache_file(
  function cache_gc_bootstraps_tracking_from_workspace_cache (line 615) | fn cache_gc_bootstraps_tracking_from_workspace_cache() -> anyhow::Result...
  function cache_gc_drops_missing_tracked_config (line 647) | fn cache_gc_drops_missing_tracked_config() -> anyhow::Result<()> {
  function cache_gc_keeps_tracked_config_on_parse_error (line 692) | fn cache_gc_keeps_tracked_config_on_parse_error() -> anyhow::Result<()> {
  function cache_gc_dry_run_does_not_remove_entries (line 729) | fn cache_gc_dry_run_does_not_remove_entries() -> anyhow::Result<()> {

FILE: crates/prek/tests/common/mod.rs
  function git_cmd (line 15) | pub fn git_cmd(dir: impl AsRef<Path>) -> Command {
  type TestContext (line 26) | pub struct TestContext {
    method new (line 39) | pub fn new() -> Self {
    method new_at (line 51) | pub fn new_at(path: PathBuf) -> Self {
    method from_root (line 63) | fn from_root(root: tempfile::TempDir, temp_dir: ChildPath) -> Self {
    method test_bucket_dir (line 102) | pub fn test_bucket_dir() -> PathBuf {
    method path_pattern (line 115) | fn path_pattern(path: impl AsRef<Path>) -> String {
    method path_patterns (line 128) | pub fn path_patterns(path: impl AsRef<Path>) -> Vec<String> {
    method read (line 147) | pub fn read(&self, file: impl AsRef<Path>) -> String {
    method command (line 152) | pub fn command(&self) -> Command {
    method run (line 180) | pub fn run(&self) -> Command {
    method validate_config (line 186) | pub fn validate_config(&self) -> Command {
    method validate_manifest (line 192) | pub fn validate_manifest(&self) -> Command {
    method install (line 198) | pub fn install(&self) -> Command {
    method prepare_hooks (line 204) | pub fn prepare_hooks(&self) -> Command {
    method uninstall (line 210) | pub fn uninstall(&self) -> Command {
    method sample_config (line 216) | pub fn sample_config(&self) -> Command {
    method list (line 222) | pub fn list(&self) -> Command {
    method auto_update (line 228) | pub fn auto_update(&self) -> Command {
    method try_repo (line 234) | pub fn try_repo(&self) -> Command {
    method filters (line 241) | pub fn filters(&self) -> Vec<(&str, &str)> {
    method work_dir (line 252) | pub fn work_dir(&self) -> &ChildPath {
    method home_dir (line 257) | pub fn home_dir(&self) -> &ChildPath {
    method init_project (line 262) | pub fn init_project(&self) {
    method git_add (line 272) | pub fn git_add(&self, path: impl AsRef<OsStr>) {
    method git_commit (line 281) | pub fn git_commit(&self, message: &str) {
    method git_tag (line 292) | pub fn git_tag(&self, tag: &str) {
    method git_reset (line 303) | pub fn git_reset(&self, target: &str) {
    method git_rm (line 312) | pub fn git_rm(&self, path: &str) {
    method git_clean (line 326) | pub fn git_clean(&self) {
    method git_branch (line 335) | pub fn git_branch(&self, branch_name: &str) {
    method git_checkout (line 344) | pub fn git_checkout(&self, branch_name: &str) {
    method write_pre_commit_config (line 353) | pub fn write_pre_commit_config(&self, content: &str) {
    method setup_workspace (line 362) | pub fn setup_workspace(&self, project_paths: &[&str], config: &str) ->...
    method with_filtered_cache_size (line 382) | pub fn with_filtered_cache_size(mut self) -> Self {
    method with_filtered_cache_clean_summary (line 396) | pub fn with_filtered_cache_clean_summary(mut self) -> Self {
  constant INSTA_FILTERS (line 406) | pub const INSTA_FILTERS: &[(&str, &str)] = &[
  function remove_bin_from_path (line 440) | pub(crate) fn remove_bin_from_path(bin: &str, path: Option<OsString>) ->...

FILE: crates/prek/tests/hook_impl.rs
  function hook_impl (line 17) | fn hook_impl() {
  function hook_impl_pre_push (line 66) | fn hook_impl_pre_push() -> anyhow::Result<()> {
  function hook_impl_runs_legacy_hook (line 184) | fn hook_impl_runs_legacy_hook() -> anyhow::Result<()> {
  function hook_impl_pre_push_runs_legacy_and_prek (line 243) | fn hook_impl_pre_push_runs_legacy_and_prek() -> anyhow::Result<()> {
  function set_executable (line 322) | fn set_executable(path: &Path) -> anyhow::Result<()> {
  function run_worktree (line 331) | fn run_worktree() -> anyhow::Result<()> {
  function git_dir_respected (line 398) | fn git_dir_respected() {
  function workspace_hook_impl_root (line 450) | fn workspace_hook_impl_root() -> anyhow::Result<()> {
  function workspace_hook_impl_subdirectory (line 528) | fn workspace_hook_impl_subdirectory() -> anyhow::Result<()> {
  function workspace_hook_impl_worktree_subdirectory (line 596) | fn workspace_hook_impl_worktree_subdirectory() -> anyhow::Result<()> {
  function workspace_hook_impl_no_project_found (line 674) | fn workspace_hook_impl_no_project_found() -> anyhow::Result<()> {
  function hook_impl_does_not_fail_when_no_hooks_match_stage (line 786) | fn hook_impl_does_not_fail_when_no_hooks_match_stage() -> anyhow::Result...
  function workspace_hook_impl_with_selectors (line 848) | fn workspace_hook_impl_with_selectors() -> anyhow::Result<()> {

FILE: crates/prek/tests/identify.rs
  function identify_text_with_missing_paths (line 10) | fn identify_text_with_missing_paths() -> anyhow::Result<()> {
  function identify_json_with_missing_paths (line 43) | fn identify_json_with_missing_paths() -> anyhow::Result<()> {

FILE: crates/prek/tests/install.rs
  function install (line 13) | fn install() -> anyhow::Result<()> {
  function install_with_quiet_flag (line 170) | fn install_with_quiet_flag() {
  function install_with_silent_flag (line 205) | fn install_with_silent_flag() {
  function install_with_verbose_flag (line 240) | fn install_with_verbose_flag() {
  function install_with_no_progress_flag (line 276) | fn install_with_no_progress_flag() {
  function install_with_git_dir (line 312) | fn install_with_git_dir() {
  function install_with_git_dir_allows_hooks_path_set (line 357) | fn install_with_git_dir_allows_hooks_path_set() {
  function install_uses_standard_permissions_by_default (line 391) | fn install_uses_standard_permissions_by_default() {
  function install_uses_group_permissions_for_shared_repository (line 412) | fn install_uses_group_permissions_for_shared_repository() {
  function install_uses_explicit_shared_repository_mode (line 439) | fn install_uses_explicit_shared_repository_mode() {
  function install_with_hooks (line 463) | fn install_with_hooks() -> anyhow::Result<()> {
  function install_with_legacy_install_hooks_flag_alias (line 525) | fn install_with_legacy_install_hooks_flag_alias() -> anyhow::Result<()> {
  function install_with_existing_legacy_hook (line 558) | fn install_with_existing_legacy_hook() -> anyhow::Result<()> {
  function install_hooks_only (line 606) | fn install_hooks_only() -> anyhow::Result<()> {
  function install_with_legacy_install_hooks_subcommand_alias (line 652) | fn install_with_legacy_install_hooks_subcommand_alias() -> anyhow::Resul...
  function uninstall (line 687) | fn uninstall() -> anyhow::Result<()> {
  function uninstall_all_managed_hooks (line 768) | fn uninstall_all_managed_hooks() -> anyhow::Result<()> {
  function uninstall_remove_legacy_hook (line 807) | fn uninstall_remove_legacy_hook() -> anyhow::Result<()> {
  function init_template_dir (line 867) | fn init_template_dir() -> anyhow::Result<()> {
  function util_init_template_dir (line 972) | fn util_init_template_dir() {
  function init_template_dir_non_git_repo (line 1010) | fn init_template_dir_non_git_repo() {
  function workspace_install (line 1045) | fn workspace_install() -> anyhow::Result<()> {
  function workspace_install_hooks (line 1212) | fn workspace_install_hooks() -> anyhow::Result<()> {
  function workspace_install_only_root_hook_types (line 1263) | fn workspace_install_only_root_hook_types() -> anyhow::Result<()> {
  function workspace_uninstall (line 1321) | fn workspace_uninstall() -> anyhow::Result<()> {
  function workspace_init_template_dir (line 1366) | fn workspace_init_template_dir() -> anyhow::Result<()> {
  function install_invalid_config_warning (line 1435) | fn install_invalid_config_warning() {

FILE: crates/prek/tests/languages/bun.rs
  function basic_bun (line 10) | fn basic_bun() {
  function additional_dependencies (line 45) | fn additional_dependencies() {
  function language_version (line 110) | fn language_version() -> Result<()> {

FILE: crates/prek/tests/languages/deno.rs
  function basic_deno (line 9) | fn basic_deno() {
  function script_file (line 44) | fn script_file() {
  function builtin_commands (line 88) | fn builtin_commands() {
  function remote_hook (line 132) | fn remote_hook() {
  function remote_hook_with_additional_dependencies (line 164) | fn remote_hook_with_additional_dependencies() {
  function remote_hook_with_local_file_additional_dependency (line 197) | fn remote_hook_with_local_file_additional_dependency() {
  function additional_dependencies (line 229) | fn additional_dependencies() {
  function additional_dependencies_local_file (line 281) | fn additional_dependencies_local_file() {
  function language_version (line 326) | fn language_version() {
  function without_system_deno (line 446) | fn without_system_deno() {
  function version_range (line 478) | fn version_range() {
  function hook_failure (line 525) | fn hook_failure() {
  function script_with_permissions (line 562) | fn script_with_permissions() {

FILE: crates/prek/tests/languages/docker.rs
  function docker (line 7) | fn docker() {
  function workspace_docker (line 41) | fn workspace_docker() -> anyhow::Result<()> {

FILE: crates/prek/tests/languages/docker_image.rs
  function docker_image (line 12) | fn docker_image() -> Result<()> {
  function docker_image_does_not_resolve_entry (line 90) | fn docker_image_does_not_resolve_entry() -> Result<()> {

FILE: crates/prek/tests/languages/fail.rs
  function fail (line 8) | fn fail() -> Result<()> {

FILE: crates/prek/tests/languages/golang.rs
  function language_version (line 11) | fn language_version() -> anyhow::Result<()> {
  function remote_hook (line 146) | fn remote_hook() {
  function local_additional_deps (line 242) | fn local_additional_deps() -> anyhow::Result<()> {
  function remote_go_mod_metadata_sets_language_version (line 326) | fn remote_go_mod_metadata_sets_language_version() -> anyhow::Result<()> {

FILE: crates/prek/tests/languages/haskell.rs
  function local_hook (line 7) | fn local_hook() -> anyhow::Result<()> {
  function additional_dependencies (line 82) | fn additional_dependencies() {
  function remote_hook (line 120) | fn remote_hook() {

FILE: crates/prek/tests/languages/julia.rs
  function local_hook (line 4) | fn local_hook() {
  function additional_dependencies (line 52) | fn additional_dependencies() {
  function project_toml (line 87) | fn project_toml() -> anyhow::Result<()> {
  function script_file (line 133) | fn script_file() -> anyhow::Result<()> {
  function remote_hook (line 176) | fn remote_hook() {

FILE: crates/prek/tests/languages/lua.rs
  function health_check (line 6) | fn health_check() {
  function language_version (line 55) | fn language_version() {
  function hook_stderr (line 88) | fn hook_stderr() -> anyhow::Result<()> {
  function script_with_files (line 127) | fn script_with_files() -> anyhow::Result<()> {
  function lua_environment (line 184) | fn lua_environment() {
  function additional_dependencies (line 242) | fn additional_dependencies() {
  function remote_hook (line 278) | fn remote_hook() {

FILE: crates/prek/tests/languages/node.rs
  function language_version (line 10) | fn language_version() -> anyhow::Result<()> {
  function additional_dependencies (line 137) | fn additional_dependencies() {
  function additional_dependencies_without_system_node (line 202) | fn additional_dependencies_without_system_node() -> anyhow::Result<()> {
  function npm_version (line 237) | fn npm_version() {

FILE: crates/prek/tests/languages/pygrep.rs
  function basic_case_sensitive (line 9) | fn basic_case_sensitive() -> Result<()> {
  function case_insensitive (line 63) | fn case_insensitive() -> Result<()> {
  function multiline_mode (line 105) | fn multiline_mode() -> Result<()> {
  function negate_mode (line 147) | fn negate_mode() -> Result<()> {
  function negate_multiline_mode (line 187) | fn negate_multiline_mode() -> Result<()> {
  function invalid_regex (line 229) | fn invalid_regex() {
  function python_regex_quirks (line 262) | fn python_regex_quirks() -> Result<()> {
  function complex_regex_patterns (line 301) | fn complex_regex_patterns() -> Result<()> {
  function case_insensitive_multiline (line 341) | fn case_insensitive_multiline() -> Result<()> {
  function pattern_not_found (line 382) | fn pattern_not_found() -> Result<()> {
  function invalid_args (line 415) | fn invalid_args() -> Result<()> {

FILE: crates/prek/tests/languages/python.rs
  function language_version (line 12) | fn language_version() -> anyhow::Result<()> {
  function invalid_version (line 146) | fn invalid_version() {
  function can_not_download (line 179) | fn can_not_download() {
  function additional_dependencies (line 228) | fn additional_dependencies() {
  function additional_dependencies_in_remote_repo (line 264) | fn additional_dependencies_in_remote_repo() -> anyhow::Result<()> {
  function hook_stderr (line 330) | fn hook_stderr() -> anyhow::Result<()> {
  function pep723_script (line 370) | fn pep723_script() -> anyhow::Result<()> {
  function git_env_vars_not_leaked_to_pip_install (line 434) | fn git_env_vars_not_leaked_to_pip_install() -> anyhow::Result<()> {
  function health_check_with_symlinked_toolchain (line 484) | fn health_check_with_symlinked_toolchain() -> anyhow::Result<()> {

FILE: crates/prek/tests/languages/ruby.rs
  function system_ruby (line 7) | fn system_ruby() {
  function language_version_default (line 81) | fn language_version_default() {
  function specific_ruby_available (line 123) | fn specific_ruby_available() {
  function specific_ruby_unavailable (line 212) | fn specific_ruby_unavailable() {
  function additional_gem_dependencies (line 268) | fn additional_gem_dependencies() -> anyhow::Result<()> {
  function gemspec_workflow (line 356) | fn gemspec_workflow() -> anyhow::Result<()> {
  function environment_isolation (line 430) | fn environment_isolation() -> anyhow::Result<()> {
  function local_hook_with_gemspec (line 593) | fn local_hook_with_gemspec() -> anyhow::Result<()> {
  function native_gem_dependency (line 699) | fn native_gem_dependency() -> anyhow::Result<()> {
  function multiple_gemspecs (line 754) | fn multiple_gemspecs() -> anyhow::Result<()> {
  function prebuilt_vs_compiled_gems (line 879) | fn prebuilt_vs_compiled_gems() -> anyhow::Result<()> {
  function process_files (line 976) | fn process_files() -> anyhow::Result<()> {
  function auto_download (line 1040) | fn auto_download() -> anyhow::Result<()> {

FILE: crates/prek/tests/languages/rust.rs
  function language_version (line 10) | fn language_version() -> Result<()> {
  function rustup_installer (line 109) | fn rustup_installer() {
  function additional_dependencies_cli (line 143) | fn additional_dependencies_cli() {
  function remote_hooks (line 179) | fn remote_hooks() {
  function remote_hook_non_workspace (line 212) | fn remote_hook_non_workspace() {
  function remote_hooks_with_lib_deps (line 245) | fn remote_hooks_with_lib_deps() {

FILE: crates/prek/tests/languages/script.rs
  function script_run (line 15) | fn script_run() {
  function workspace_script_run (line 55) | fn workspace_script_run() -> Result<()> {
  function local_repo_bash_shebang (line 136) | fn local_repo_bash_shebang() -> Result<()> {
  function windows_script_run (line 179) | fn windows_script_run() -> Result<()> {

FILE: crates/prek/tests/languages/swift.rs
  function local_hook_system_command (line 9) | fn local_hook_system_command() {
  function language_version_rejected (line 48) | fn language_version_rejected() {
  function health_check (line 84) | fn health_check() {
  function local_package_build (line 138) | fn local_package_build() -> anyhow::Result<()> {

FILE: crates/prek/tests/languages/unimplemented.rs
  function unimplemented_language (line 4) | fn unimplemented_language() {

FILE: crates/prek/tests/languages/unsupported.rs
  function unsupported_language (line 4) | fn unsupported_language() -> anyhow::Result<()> {

FILE: crates/prek/tests/list.rs
  function list_basic (line 7) | fn list_basic() {
  function list_verbose (line 40) | fn list_verbose() {
  function list_with_hook_ids_filter (line 126) | fn list_with_hook_ids_filter() {
  function list_with_language_filter (line 174) | fn list_with_language_filter() {
  function list_with_stage_filter (line 220) | fn list_with_stage_filter() {
  function list_with_aliases (line 271) | fn list_with_aliases() {
  function list_empty_config (line 320) | fn list_empty_config() {
  function list_no_config_file (line 344) | fn list_no_config_file() {
  function list_json_output (line 362) | fn list_json_output() {
  function workspace_list (line 471) | fn workspace_list() -> anyhow::Result<()> {
  function list_with_selectors (line 662) | fn list_with_selectors() -> anyhow::Result<()> {

FILE: crates/prek/tests/list_builtins.rs
  function list_builtins_basic (line 6) | fn list_builtins_basic() {
  function list_builtins_verbose (line 35) | fn list_builtins_verbose() {
  function list_builtins_json (line 95) | fn list_builtins_json() {

FILE: crates/prek/tests/meta_hooks.rs
  function meta_hooks (line 9) | fn meta_hooks() -> anyhow::Result<()> {
  function meta_hooks_unknown_hook (line 74) | fn meta_hooks_unknown_hook() {
  function check_useless_excludes_remote (line 104) | fn check_useless_excludes_remote() -> anyhow::Result<()> {
  function meta_hooks_workspace (line 156) | fn meta_hooks_workspace() -> anyhow::Result<()> {
  function check_useless_excludes_workspace_paths_are_project_relative (line 226) | fn check_useless_excludes_workspace_paths_are_project_relative() -> anyh...

FILE: crates/prek/tests/run.rs
  function run_basic (line 16) | fn run_basic() -> Result<()> {
  function run_glob_patterns_with_multiple_hooks (line 77) | fn run_glob_patterns_with_multiple_hooks() -> Result<()> {
  function run_in_non_git_repo (line 133) | fn run_in_non_git_repo() {
  function invalid_config (line 156) | fn invalid_config() {
  function same_repo (line 272) | fn same_repo() -> Result<()> {
  function local (line 319) | fn local() {
  function multiple_hook_ids (line 348) | fn multiple_hook_ids() {
  function priorities_respected (line 470) | fn priorities_respected() {
  function priority_fail_fast_stops_later_groups (line 513) | fn priority_fail_fast_stops_later_groups() {
  function priority_group_modified_files_is_group_failure_and_output_is_indented (line 558) | fn priority_group_modified_files_is_group_failure_and_output_is_indented...
  function config_not_staged (line 628) | fn config_not_staged() -> Result<()> {
  function config_outside_repo (line 659) | fn config_outside_repo() -> Result<()> {
  function cjk_hook_name (line 695) | fn cjk_hook_name() {
  function skips (line 728) | fn skips() {
  function stage (line 779) | fn stage() {
  function fallback_to_manual_stage (line 838) | fn fallback_to_manual_stage() {
  function files_and_exclude (line 921) | fn files_and_exclude() -> Result<()> {
  function file_types (line 1022) | fn file_types() -> Result<()> {
  function fail_fast (line 1095) | fn fail_fast() {
  function fail_fast_cli_flag (line 1149) | fn fail_fast_cli_flag() {
  function subdirectory (line 1200) | fn subdirectory() -> Result<()> {
  function log_file (line 1253) | fn log_file() {
  function pass_env_vars (line 1287) | fn pass_env_vars() {
  function staged_files_only (line 1318) | fn staged_files_only() -> Result<()> {
  function restore_on_interrupt (line 1374) | fn restore_on_interrupt() -> Result<()> {
  function merge_conflicts (line 1428) | fn merge_conflicts() -> Result<()> {
  function local_python_hook (line 1501) | fn local_python_hook() {
  function invalid_entry (line 1533) | fn invalid_entry() {
  function init_nonexistent_repo (line 1563) | fn init_nonexistent_repo() {
  function types_directory (line 1608) | fn types_directory() -> Result<()> {
  function run_last_commit (line 1668) | fn run_last_commit() -> Result<()> {
  function run_multiple_files (line 1750) | fn run_multiple_files() -> Result<()> {
  function run_no_files (line 1786) | fn run_no_files() {
  function run_directory (line 1817) | fn run_directory() -> Result<()> {
  function minimum_prek_version (line 1948) | fn minimum_prek_version() {
  function color (line 1994) | fn color() -> Result<()> {
  function shebang_script (line 2055) | fn shebang_script() -> Result<()> {
  function git_commit_a (line 2100) | fn git_commit_a() -> Result<()> {
  function git_commit_a_currently_fails_when_hook_writes_to_temp_git_index (line 2172) | fn git_commit_a_currently_fails_when_hook_writes_to_temp_git_index() -> ...
  function write_pre_commit_config (line 2270) | fn write_pre_commit_config(path: &Path, hooks: &[(&str, &str)]) -> Resul...
  function selectors_completion (line 2298) | fn selectors_completion() -> Result<()> {
  function reuse_env (line 2435) | fn reuse_env() -> Result<()> {
  function dry_run (line 2515) | fn dry_run() {
  function alternate_config_file (line 2547) | fn alternate_config_file() -> Result<()> {
  function prek_toml (line 2642) | fn prek_toml() -> Result<()> {
  function show_diff_on_failure (line 2680) | fn show_diff_on_failure() -> Result<()> {
  function run_quiet (line 2825) | fn run_quiet() {
  function run_quiet_env (line 2871) | fn run_quiet_env() {
  function run_log_file (line 2917) | fn run_log_file() {
  function system_language_version (line 2974) | fn system_language_version() {
  function empty_entry (line 3062) | fn empty_entry() {
  function run_with_stdin_closed (line 3092) | fn run_with_stdin_closed() {
  function version_info (line 3137) | fn version_info() {
  function expands_tilde_in_prek_home (line 3162) | fn expands_tilde_in_prek_home() -> Result<()> {
  function run_with_tree_object_as_ref (line 3209) | fn run_with_tree_object_as_ref() -> Result<()> {
  function pass_filenames_1_limits_batch_size (line 3261) | fn pass_filenames_1_limits_batch_size() -> Result<()> {
  function pass_filenames_2_limits_batch_size (line 3302) | fn pass_filenames_2_limits_batch_size() -> Result<()> {

FILE: crates/prek/tests/sample_config.rs
  function sample_config (line 8) | fn sample_config() -> anyhow::Result<()> {
  function sample_config_toml (line 101) | fn sample_config_toml() {
  function sample_config_format (line 129) | fn sample_config_format() {
  function respect_format (line 183) | fn respect_format() {
  function respect_format_if_filename_missing (line 211) | fn respect_format_if_filename_missing() {

FILE: crates/prek/tests/skipped_hooks.rs
  function all_hooks_skipped_no_matching_files (line 19) | fn all_hooks_skipped_no_matching_files() -> Result<()> {
  function dry_run_skips_all_hooks (line 68) | fn dry_run_skips_all_hooks() -> Result<()> {
  function mixed_skipped_and_executed_hooks (line 110) | fn mixed_skipped_and_executed_hooks() -> Result<()> {
  function all_hooks_skipped_multiple_priority_groups (line 165) | fn all_hooks_skipped_multiple_priority_groups() -> Result<()> {

FILE: crates/prek/tests/try_repo.rs
  function create_hook_repo (line 11) | fn create_hook_repo(context: &TestContext, repo_name: &str) -> Result<Pa...
  function create_failing_hook_repo (line 70) | fn create_failing_hook_repo(context: &TestContext, repo_name: &str) -> R...
  function try_repo_basic (line 117) | fn try_repo_basic() -> Result<()> {
  function try_repo_failing_hook (line 150) | fn try_repo_failing_hook() -> Result<()> {
  function try_repo_specific_hook (line 185) | fn try_repo_specific_hook() -> Result<()> {
  function try_repo_specific_rev (line 218) | fn try_repo_specific_rev() -> Result<()> {
  function try_repo_uncommitted_changes (line 283) | fn try_repo_uncommitted_changes() -> Result<()> {
  function try_repo_relative_path (line 339) | fn try_repo_relative_path() -> Result<()> {

FILE: crates/prek/tests/validate.rs
  function validate_config (line 9) | fn validate_config() -> anyhow::Result<()> {
  function invalid_config_error (line 69) | fn invalid_config_error() {
  function validate_manifest (line 120) | fn validate_manifest() -> anyhow::Result<()> {
  function unexpected_keys_warning (line 188) | fn unexpected_keys_warning() {

FILE: crates/prek/tests/workspace.rs
  function basic_discovery (line 12) | fn basic_discovery() -> Result<()> {
  function config_not_staged (line 209) | fn config_not_staged() -> Result<()> {
  function run_with_selectors (line 296) | fn run_with_selectors() -> Result<()> {
  function skips (line 613) | fn skips() -> Result<()> {
  function workspace_no_projects (line 857) | fn workspace_no_projects() {
  function gitignore_respected (line 877) | fn gitignore_respected() -> Result<()> {
  function nested_project_exclude_is_relative (line 938) | fn nested_project_exclude_is_relative() -> Result<()> {
  function reference_files_across_projects (line 1013) | fn reference_files_across_projects() -> Result<()> {
  function submodule_discovery (line 1050) | fn submodule_discovery() -> Result<()> {
  function cookiecutter_template_directories_are_skipped (line 1144) | fn cookiecutter_template_directories_are_skipped() -> Result<()> {
  function orphan_projects (line 1193) | fn orphan_projects() -> Result<()> {
  function relative_repo_path_resolution (line 1373) | fn relative_repo_path_resolution() -> Result<()> {

FILE: crates/prek/tests/yaml_to_toml.rs
  constant YAML_CONFIG (line 9) | const YAML_CONFIG: &str = r#"
  function yaml_to_toml_writes_default_output (line 58) | fn yaml_to_toml_writes_default_output() -> anyhow::Result<()> {
  function yaml_to_toml_force_overwrite (line 154) | fn yaml_to_toml_force_overwrite() -> anyhow::Result<()> {
  function yaml_to_toml_rejects_invalid_config (line 197) | fn yaml_to_toml_rejects_invalid_config() -> anyhow::Result<()> {
  function yaml_to_toml_same_output (line 229) | fn yaml_to_toml_same_output() -> anyhow::Result<()> {
  function yaml_to_toml_discovers_pre_commit_config_yaml (line 261) | fn yaml_to_toml_discovers_pre_commit_config_yaml() -> anyhow::Result<()> {
  function yaml_to_toml_discovers_pre_commit_config_yml (line 291) | fn yaml_to_toml_discovers_pre_commit_config_yml() -> anyhow::Result<()> {
  function yaml_to_toml_prefers_yaml_over_yml (line 321) | fn yaml_to_toml_prefers_yaml_over_yml() -> anyhow::Result<()> {
  function yaml_to_toml_error_when_no_config_found (line 371) | fn yaml_to_toml_error_when_no_config_found() {

FILE: python/prek/__main__.py
  function _run (line 6) | def _run() -> None:

FILE: python/prek/_find_prek.py
  class PrekNotFound (line 28) | class PrekNotFound(FileNotFoundError): ...
  function find_prek_bin (line 31) | def find_prek_bin() -> str:
  function _module_path (line 75) | def _module_path() -> str | None:
  function _matching_parents (line 80) | def _matching_parents(path: str | None, match: str) -> str | None:
  function _join (line 106) | def _join(path: str | None, *parts: str) -> str | None:
  function _user_scheme (line 112) | def _user_scheme() -> str:

FILE: scripts/update-macports-portfile.py
  function run (line 20) | def run(cmd: list[str], *, capture: bool = False) -> str:
  function repo_root (line 32) | def repo_root() -> Path:
  function read_version (line 37) | def read_version(cargo_toml: Path) -> str:
  function replace_github_setup_version (line 45) | def replace_github_setup_version(portfile_text: str, version: str) -> str:
  function download_distfile (line 58) | def download_distfile(version: str) -> Path:
  function openssl_digest (line 68) | def openssl_digest(algorithm: str, file_path: Path) -> str:
  function update_checksums_block (line 75) | def update_checksums_block(portfile_text: str, rmd160: str, sha256: str,...
  function ensure_cargo2port (line 103) | def ensure_cargo2port() -> None:
  function generated_cargo_crates (line 118) | def generated_cargo_crates(c
Condensed preview — 256 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,493K chars).
[
  {
    "path": ".config/nextest.toml",
    "chars": 1891,
    "preview": "[profile.ci-core]\n# Exclude language-specific integration tests from the main CI runs (except unimplemented/unsupported/"
  },
  {
    "path": ".config/taplo.toml",
    "chars": 36,
    "preview": "[formatting]\nalign_comments = false\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 1456,
    "preview": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the\n// README at: https://github.co"
  },
  {
    "path": ".gitattributes",
    "chars": 191,
    "preview": "# Ensure consistent line endings across platforms (avoid LF -> CRLF on Windows)\n* text=auto eol=lf\n\nprek.schema.json lin"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 8,
    "preview": "* @j178\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yaml",
    "chars": 1852,
    "preview": "name: Bug report\ndescription: Create a report to help us improve prek\nbody:\n  - type: textarea\n    attributes:\n      lab"
  },
  {
    "path": ".github/codecov.yml",
    "chars": 335,
    "preview": "coverage:\n  status:\n    project:\n      default:\n        target: auto\n        threshold: 1%\n        informational: true\n "
  },
  {
    "path": ".github/copilot-instructions.md",
    "chars": 3281,
    "preview": "# Copilot instructions for `prek`\n\n## Code requirements\n\n- Concise, idiomatic Rust (2024 edition).\n- Proper error handli"
  },
  {
    "path": ".github/renovate.json5",
    "chars": 4464,
    "preview": "{\n  $schema: 'https://docs.renovatebot.com/renovate-schema.json',\n  extends: [\n    'config:recommended',\n    // https://"
  },
  {
    "path": ".github/workflows/build-binaries.yml",
    "chars": 17097,
    "preview": "# Build prek on all platforms.\n#\n# Generates both wheels (for PyPI) and archived binaries (for GitHub releases).\n# Assum"
  },
  {
    "path": ".github/workflows/build-docker.yml",
    "chars": 7351,
    "preview": "# Build and publish a Docker image.\n#\n# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, "
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 26095,
    "preview": "name: CI\n\non:\n  push:\n    branches: [master]\n  pull_request:\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.work"
  },
  {
    "path": ".github/workflows/performance.yml",
    "chars": 5813,
    "preview": "name: Performance\n\non:\n  workflow_call:\n    inputs:\n      save-rust-cache:\n        required: false\n        type: string\n"
  },
  {
    "path": ".github/workflows/publish-crates.yml",
    "chars": 1023,
    "preview": "name: \"Publish to crates.io\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n\n"
  },
  {
    "path": ".github/workflows/publish-docs.yml",
    "chars": 1781,
    "preview": "name: Deploy Documentation\n\non:\n  workflow_dispatch:\n    inputs:\n      ref:\n        description: \"The commit SHA, tag, o"
  },
  {
    "path": ".github/workflows/publish-homebrew.yml",
    "chars": 1874,
    "preview": "name: \"Publish Homebrew formula\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: stri"
  },
  {
    "path": ".github/workflows/publish-npm.yml",
    "chars": 1458,
    "preview": "name: \"Publish to npmjs registry\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: str"
  },
  {
    "path": ".github/workflows/publish-prek-action.yml",
    "chars": 2715,
    "preview": "name: \"Publish prek-action known versions\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        "
  },
  {
    "path": ".github/workflows/publish-pypi.yml",
    "chars": 672,
    "preview": "name: \"Publish to PyPI\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n\njobs:"
  },
  {
    "path": ".github/workflows/publish-winget.yml",
    "chars": 1341,
    "preview": "name: \"Publish to winget\"\n\non:\n  workflow_dispatch:\n    inputs:\n      tag:\n        description: \"The release tag to publ"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 13359,
    "preview": "# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist\n#\n# Copyright 2022-2024, axodotdev\n# SPDX-"
  },
  {
    "path": ".github/workflows/setup-dev-drive.ps1",
    "chars": 1114,
    "preview": "# This creates a 10GB dev drive, and exports all required environment\n# variables so that rustup, prek and others all us"
  },
  {
    "path": ".github/workflows/sync-identify.yml",
    "chars": 1183,
    "preview": "name: \"Sync pre-commit identify tags\"\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 0 * * *\"\n\npermissions: {}\n\njob"
  },
  {
    "path": ".github/workflows/zizmor.yml",
    "chars": 512,
    "preview": "name: Run zizmor\n\non:\n  push:\n    branches: [\"master\"]\n  pull_request:\n    branches: [\"**\"]\n\npermissions: {}\n\njobs:\n  zi"
  },
  {
    "path": ".github/zizmor.yml",
    "chars": 452,
    "preview": "# Configuration for the zizmor static analysis tool, run via pre-commit in CI\n# https://woodruffw.github.io/zizmor/confi"
  },
  {
    "path": ".gitignore",
    "chars": 179,
    "preview": "/target\n\n.cache\n__pycache__/\nsite/\n\n# Insta snapshots.\n*.pending-snap\n\n# JetBrains IDE\n.idea\n\n# Vscode IDE\n.vscode\n\n# ma"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 1686,
    "preview": "fail_fast: true\ndefault_install_hook_types: [pre-push]\nexclude:\n  glob: '**/snapshots/**'\n\nrepos:\n  - repo: builtin\n    "
  },
  {
    "path": "CHANGELOG.md",
    "chars": 74682,
    "preview": "# Changelog\n\n## 0.3.6\n\nReleased on 2026-03-16.\n\n### Enhancements\n\n- Allow selectors for hook ids containing colons ([#17"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3642,
    "preview": "# Contributing to prek\n\nThanks for your interest in improving **prek**! This guide walks through the development environ"
  },
  {
    "path": "Cargo.toml",
    "chars": 6156,
    "preview": "[workspace]\nmembers = [\"crates/*\"]\nresolver = \"3\"\n\n[workspace.package]\nversion = \"0.3.6\"\nedition = \"2024\"\nrust-version ="
  },
  {
    "path": "Dockerfile",
    "chars": 1523,
    "preview": "FROM --platform=$BUILDPLATFORM ubuntu AS build\nENV HOME=\"/root\"\nWORKDIR $HOME\n\nRUN apt update \\\n  && apt install -y --no"
  },
  {
    "path": "LICENSE",
    "chars": 1061,
    "preview": "MIT License\n\nCopyright (c) 2024 j178\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
  },
  {
    "path": "README.md",
    "chars": 14024,
    "preview": "<div align=\"center\">\n\n<img width=\"180\" alt=\"prek\" src=\"https://raw.githubusercontent.com/j178/prek/master/docs/assets/lo"
  },
  {
    "path": "clippy.toml",
    "chars": 59,
    "preview": "disallowed-methods = [\"std::env::var\", \"std::env::var_os\"]\n"
  },
  {
    "path": "crates/prek/Cargo.toml",
    "chars": 4112,
    "preview": "[package]\nname = \"prek\"\nauthors = [\"j178 <hi@j178.dev>\"]\ndescription = \"Better `pre-commit`, re-engineered in Rust\"\nread"
  },
  {
    "path": "crates/prek/build.rs",
    "chars": 5123,
    "preview": "/* MIT License\n\nCopyright (c) 2023 Astral Software Inc.\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "crates/prek/src/archive.rs",
    "chars": 11984,
    "preview": "// MIT License\n//\n// Copyright (c) 2023 Astral Software Inc.\n//\n// Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "crates/prek/src/cleanup.rs",
    "chars": 472,
    "preview": "use std::sync::Mutex;\n\nstatic CLEANUP_HOOKS: Mutex<Vec<Box<dyn Fn() + Send>>> = Mutex::new(Vec::new());\n\n/// Run all cle"
  },
  {
    "path": "crates/prek/src/cli/auto_update.rs",
    "chars": 29914,
    "preview": "use std::fmt::Write;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::time::{SystemTime, UNIX_EPOCH};\n\n"
  },
  {
    "path": "crates/prek/src/cli/cache_clean.rs",
    "chars": 7821,
    "preview": "use std::fmt::Write;\nuse std::fs::FileType;\nuse std::io;\nuse std::path::Path;\n\nuse anyhow::Result;\nuse owo_colors::OwoCo"
  },
  {
    "path": "crates/prek/src/cli/cache_gc.rs",
    "chars": 24667,
    "preview": "use std::fmt::Write;\nuse std::fmt::{Display, Formatter};\nuse std::ops::AddAssign;\nuse std::path::Path;\n\nuse anyhow::Resu"
  },
  {
    "path": "crates/prek/src/cli/cache_size.rs",
    "chars": 2849,
    "preview": "use std::fmt::Write;\nuse std::path::Path;\n\nuse anyhow::Result;\n\nuse crate::cli::ExitStatus;\nuse crate::printer::Printer;"
  },
  {
    "path": "crates/prek/src/cli/completion.rs",
    "chars": 9894,
    "preview": "use std::collections::{BTreeMap, BTreeSet};\nuse std::ffi::OsStr;\nuse std::path::Path;\n\nuse clap::builder::StyledStr;\nuse"
  },
  {
    "path": "crates/prek/src/cli/hook_impl.rs",
    "chars": 12290,
    "preview": "use std::ffi::OsString;\nuse std::fmt::Write;\nuse std::ops::RangeInclusive;\nuse std::path::PathBuf;\nuse std::process::Std"
  },
  {
    "path": "crates/prek/src/cli/identify.rs",
    "chars": 1786,
    "preview": "use std::fmt::Write;\nuse std::path::PathBuf;\n\nuse itertools::Itertools;\nuse owo_colors::OwoColorize;\nuse prek_identify::"
  },
  {
    "path": "crates/prek/src/cli/install.rs",
    "chars": 15280,
    "preview": "use std::fmt::Write as _;\nuse std::io::Write;\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\n\nuse anyhow::{Context,"
  },
  {
    "path": "crates/prek/src/cli/list.rs",
    "chars": 4535,
    "preview": "use std::fmt::Write;\nuse std::path::PathBuf;\n\nuse anyhow::Context;\nuse owo_colors::OwoColorize;\nuse serde::Serialize;\n\nu"
  },
  {
    "path": "crates/prek/src/cli/list_builtins.rs",
    "chars": 1843,
    "preview": "use std::fmt::Write;\n\nuse owo_colors::OwoColorize;\nuse serde::Serialize;\nuse strum::IntoEnumIterator;\n\nuse crate::cli::{"
  },
  {
    "path": "crates/prek/src/cli/mod.rs",
    "chars": 42123,
    "preview": "use std::ffi::OsString;\nuse std::path::PathBuf;\nuse std::process::ExitCode;\n\nuse clap::builder::styling::{AnsiColor, Eff"
  },
  {
    "path": "crates/prek/src/cli/reporter.rs",
    "chars": 8740,
    "preview": "use std::borrow::Cow;\nuse std::sync::{Arc, Mutex, Weak};\nuse std::time::Duration;\n\nuse indicatif::{MultiProgress, Progre"
  },
  {
    "path": "crates/prek/src/cli/run/filter.rs",
    "chars": 13300,
    "preview": "use std::path::{Path, PathBuf};\n\nuse anyhow::{Context, Result};\nuse itertools::{Either, Itertools};\nuse path_clean::Path"
  },
  {
    "path": "crates/prek/src/cli/run/keeper.rs",
    "chars": 7784,
    "preview": "use std::path::{Path, PathBuf};\nuse std::process::Command;\nuse std::sync::Mutex;\n\nuse anstream::eprintln;\nuse anyhow::Re"
  },
  {
    "path": "crates/prek/src/cli/run/mod.rs",
    "chars": 247,
    "preview": "pub(crate) use filter::{CollectOptions, FileFilter, collect_files};\npub(crate) use run::{install_hooks, run};\npub(crate)"
  },
  {
    "path": "crates/prek/src/cli/run/run.rs",
    "chars": 33711,
    "preview": "use std::fmt::Write as _;\nuse std::io::Write as _;\nuse std::path::PathBuf;\nuse std::rc::Rc;\nuse std::sync::{Arc, LazyLoc"
  },
  {
    "path": "crates/prek/src/cli/run/selector.rs",
    "chars": 24175,
    "preview": "use std::borrow::Cow;\nuse std::fmt::Display;\nuse std::path::{Path, PathBuf};\nuse std::sync::{Arc, Mutex};\n\nuse crate::ho"
  },
  {
    "path": "crates/prek/src/cli/sample_config.rs",
    "chars": 3405,
    "preview": "use std::fmt::Write as _;\nuse std::io::Write;\nuse std::path::{Path, PathBuf};\n\nuse anyhow::Result;\nuse owo_colors::OwoCo"
  },
  {
    "path": "crates/prek/src/cli/self_update.rs",
    "chars": 6690,
    "preview": "// MIT License\n//\n// Copyright (c) 2023 Astral Software Inc.\n//\n// Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "crates/prek/src/cli/try_repo.rs",
    "chars": 7010,
    "preview": "use std::borrow::Cow;\nuse std::fmt::Write;\nuse std::path::{Path, PathBuf};\n\nuse anyhow::{Context, Result};\nuse owo_color"
  },
  {
    "path": "crates/prek/src/cli/validate.rs",
    "chars": 2191,
    "preview": "use std::error::Error;\nuse std::fmt::Write;\nuse std::iter;\nuse std::path::PathBuf;\n\nuse anyhow::Result;\nuse owo_colors::"
  },
  {
    "path": "crates/prek/src/cli/yaml_to_toml.rs",
    "chars": 7487,
    "preview": "use std::fmt::Write as _;\nuse std::io::Write;\nuse std::path::{Path, PathBuf};\n\nuse anyhow::{Context, Result};\nuse owo_co"
  },
  {
    "path": "crates/prek/src/config.rs",
    "chars": 73415,
    "preview": "use std::collections::{BTreeMap, BTreeSet};\nuse std::error::Error as _;\nuse std::fmt::Display;\nuse std::ops::RangeInclus"
  },
  {
    "path": "crates/prek/src/fs.rs",
    "chars": 13535,
    "preview": "// MIT License\n//\n// Copyright (c) 2023 Astral Software Inc.\n//\n// Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "crates/prek/src/git.rs",
    "chars": 23993,
    "preview": "use std::borrow::Cow;\nuse std::collections::HashSet;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::s"
  },
  {
    "path": "crates/prek/src/hook.rs",
    "chars": 39976,
    "preview": "use std::borrow::Cow;\nuse std::ffi::OsStr;\nuse std::fmt::{Display, Formatter};\nuse std::ops::Deref;\nuse std::path::{Path"
  },
  {
    "path": "crates/prek/src/hooks/builtin_hooks/check_json5.rs",
    "chars": 3326,
    "preview": "use std::path::Path;\n\nuse crate::hook::Hook;\nuse crate::hooks::pre_commit_hooks::check_json::JsonValue;\nuse crate::hooks"
  },
  {
    "path": "crates/prek/src/hooks/builtin_hooks/mod.rs",
    "chars": 12158,
    "preview": "use std::path::Path;\nuse std::str::FromStr;\n\nuse anyhow::Result;\nuse prek_identify::tags;\n\nuse crate::cli::reporter::Hoo"
  },
  {
    "path": "crates/prek/src/hooks/meta_hooks.rs",
    "chars": 11418,
    "preview": "use std::io::Write;\nuse std::path::Path;\nuse std::str::FromStr;\n\nuse anyhow::{Context, Result};\nuse itertools::Itertools"
  },
  {
    "path": "crates/prek/src/hooks/mod.rs",
    "chars": 2251,
    "preview": "use std::future::Future;\nuse std::path::Path;\nuse std::str::FromStr;\nuse std::sync::LazyLock;\n\nuse prek_consts::env_vars"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_added_large_files.rs",
    "chars": 2051,
    "preview": "use std::path::{Path, PathBuf};\n\nuse clap::Parser;\nuse rustc_hash::FxHashSet;\n\nuse crate::git::{get_added_files, get_lfs"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_case_conflict.rs",
    "chars": 5187,
    "preview": "use std::collections::hash_map::Entry;\nuse std::path::Path;\n\nuse anyhow::Result;\nuse rustc_hash::FxHashMap;\nuse rustc_ha"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_executables_have_shebangs.rs",
    "chars": 7408,
    "preview": "use std::path::Path;\n\nuse futures::StreamExt;\nuse owo_colors::OwoColorize;\nuse rustc_hash::FxHashSet;\nuse tokio::io::Asy"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_json.rs",
    "chars": 7748,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse rustc_hash::FxHashMap;\nuse serde::{Deserialize, Deserializer};\n\nuse crate:"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_merge_conflict.rs",
    "chars": 9139,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse clap::Parser;\nuse tokio::io::AsyncBufReadExt;\n\nuse crate::git::get_git_dir"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_symlinks.rs",
    "chars": 5308,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\n\nuse crate::hook::Hook;\nuse crate::hooks::run_concurrent_file_checks;\nuse crat"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_toml.rs",
    "chars": 4879,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\n\nuse crate::hook::Hook;\nuse crate::hooks::run_concurrent_file_checks;\nuse crat"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_xml.rs",
    "chars": 7558,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\n\nuse crate::hook::Hook;\nuse crate::hooks::run_concurrent_file_checks;\nuse crat"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/check_yaml.rs",
    "chars": 6884,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse clap::Parser;\n\nuse crate::hook::Hook;\nuse crate::hooks::run_concurrent_fil"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/detect_private_key.rs",
    "chars": 5792,
    "preview": "use std::path::Path;\nuse std::sync::LazyLock;\n\nuse aho_corasick::AhoCorasick;\nuse anyhow::Result;\nuse tokio::io::AsyncRe"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/fix_byte_order_marker.rs",
    "chars": 7564,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom};\n\nuse cra"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/fix_end_of_file.rs",
    "chars": 9316,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWriteEx"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/fix_trailing_whitespace.rs",
    "chars": 16927,
    "preview": "use std::ops::Deref;\nuse std::path::Path;\nuse std::str::FromStr;\n\nuse anyhow::Result;\nuse bstr::ByteSlice;\nuse clap::Par"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/mixed_line_ending.rs",
    "chars": 9887,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse bstr::ByteSlice;\nuse clap::{Parser, ValueEnum};\nuse rustc_hash::FxHashMap;"
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/mod.rs",
    "chars": 3582,
    "preview": "use std::path::Path;\n\nuse anyhow::Result;\nuse tracing::debug;\n\nuse crate::hook::Hook;\n\nmod check_added_large_files;\nmod "
  },
  {
    "path": "crates/prek/src/hooks/pre_commit_hooks/no_commit_to_branch.rs",
    "chars": 1808,
    "preview": "use clap::Parser;\nuse fancy_regex::Regex;\n\nuse crate::git::git_cmd;\nuse crate::hook::Hook;\nuse anyhow::{Context, Result}"
  },
  {
    "path": "crates/prek/src/http.rs",
    "chars": 8164,
    "preview": "use std::path::{Path, PathBuf};\nuse std::sync::LazyLock;\n\nuse anyhow::{Context, Result};\nuse futures::TryStreamExt;\nuse "
  },
  {
    "path": "crates/prek/src/install_source.rs",
    "chars": 7274,
    "preview": "use std::ffi::OsStr;\nuse std::path::{Component, Path, PathBuf};\n\n/// Represents how prek was installed on the system.\n#["
  },
  {
    "path": "crates/prek/src/languages/bun/bun.rs",
    "chars": 5662,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_consts::env_v"
  },
  {
    "path": "crates/prek/src/languages/bun/installer.rs",
    "chars": 9735,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::fmt::Display;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse s"
  },
  {
    "path": "crates/prek/src/languages/bun/mod.rs",
    "chars": 134,
    "preview": "#[allow(clippy::module_inception)]\nmod bun;\nmod installer;\nmod version;\n\npub(crate) use bun::Bun;\npub(crate) use version"
  },
  {
    "path": "crates/prek/src/languages/bun/version.rs",
    "chars": 7024,
    "preview": "use std::fmt::Display;\nuse std::ops::Deref;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\n\nuse serde::Deseriali"
  },
  {
    "path": "crates/prek/src/languages/deno/deno.rs",
    "chars": 9820,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_consts::env_v"
  },
  {
    "path": "crates/prek/src/languages/deno/installer.rs",
    "chars": 10412,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::fmt::Display;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse s"
  },
  {
    "path": "crates/prek/src/languages/deno/mod.rs",
    "chars": 160,
    "preview": "#[allow(clippy::module_inception)]\nmod deno;\npub(crate) mod installer;\npub(crate) mod version;\n\npub(crate) use deno::Den"
  },
  {
    "path": "crates/prek/src/languages/deno/version.rs",
    "chars": 6614,
    "preview": "use std::fmt::Display;\nuse std::ops::Deref;\nuse std::path::Path;\nuse std::str::FromStr;\n\nuse serde::Deserialize;\n\nuse cr"
  },
  {
    "path": "crates/prek/src/languages/docker.rs",
    "chars": 27965,
    "preview": "use std::borrow::Cow;\nuse std::collections::BTreeSet;\nuse std::collections::hash_map::DefaultHasher;\nuse std::fs;\nuse st"
  },
  {
    "path": "crates/prek/src/languages/docker_image.rs",
    "chars": 2405,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::Result;\n\nuse crate::cli::reporter::{HookI"
  },
  {
    "path": "crates/prek/src/languages/fail.rs",
    "chars": 1104,
    "preview": "use std::io::Write;\nuse std::path::Path;\nuse std::sync::Arc;\n\nuse anyhow::Result;\n\nuse crate::cli::reporter::{HookInstal"
  },
  {
    "path": "crates/prek/src/languages/golang/golang.rs",
    "chars": 6354,
    "preview": "use std::ops::Deref;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::Context;\n"
  },
  {
    "path": "crates/prek/src/languages/golang/gomod.rs",
    "chars": 7495,
    "preview": "use std::io;\nuse std::path::Path;\n\nuse anyhow::Result;\nuse tracing::trace;\n\nuse crate::config::Language;\nuse crate::hook"
  },
  {
    "path": "crates/prek/src/languages/golang/installer.rs",
    "chars": 10437,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::fmt::Display;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse s"
  },
  {
    "path": "crates/prek/src/languages/golang/mod.rs",
    "chars": 200,
    "preview": "#[allow(clippy::module_inception)]\nmod golang;\nmod gomod;\nmod installer;\nmod version;\n\npub(crate) use golang::Golang;\npu"
  },
  {
    "path": "crates/prek/src/languages/golang/version.rs",
    "chars": 8011,
    "preview": "use std::fmt::Display;\nuse std::ops::Deref;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\n\nuse serde::Deseriali"
  },
  {
    "path": "crates/prek/src/languages/haskell.rs",
    "chars": 5199,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::{Arc, LazyLock};\n\nuse anyhow::{Context, Result};\nuse mea::o"
  },
  {
    "path": "crates/prek/src/languages/julia.rs",
    "chars": 4713,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse tracing::debug;\n\nu"
  },
  {
    "path": "crates/prek/src/languages/lua.rs",
    "chars": 7669,
    "preview": "use std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_co"
  },
  {
    "path": "crates/prek/src/languages/mod.rs",
    "chars": 18223,
    "preview": "use std::ffi::OsStr;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse std::sync::Arc;\n\nuse anyhow::Result;\nuse"
  },
  {
    "path": "crates/prek/src/languages/node/installer.rs",
    "chars": 11383,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::fmt::Display;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse s"
  },
  {
    "path": "crates/prek/src/languages/node/mod.rs",
    "chars": 138,
    "preview": "mod installer;\n#[allow(clippy::module_inception)]\nmod node;\nmod version;\n\npub(crate) use node::Node;\npub(crate) use vers"
  },
  {
    "path": "crates/prek/src/languages/node/node.rs",
    "chars": 6857,
    "preview": "use std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_co"
  },
  {
    "path": "crates/prek/src/languages/node/version.rs",
    "chars": 11994,
    "preview": "use std::fmt::Display;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\n\nuse serde::{Deserialize, Deserializer, Se"
  },
  {
    "path": "crates/prek/src/languages/pygrep/mod.rs",
    "chars": 79,
    "preview": "#[allow(clippy::module_inception)]\nmod pygrep;\n\npub(crate) use pygrep::Pygrep;\n"
  },
  {
    "path": "crates/prek/src/languages/pygrep/pygrep.rs",
    "chars": 9558,
    "preview": "use std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_co"
  },
  {
    "path": "crates/prek/src/languages/pygrep/script.py",
    "chars": 5229,
    "preview": "from __future__ import annotations\n\nimport json\nimport io\nimport re\nimport sys\nfrom concurrent.futures import ThreadPool"
  },
  {
    "path": "crates/prek/src/languages/python/mod.rs",
    "chars": 611,
    "preview": "use anyhow::Result;\n\nuse crate::hook::Hook;\n\nmod pep723;\nmod pyproject;\n#[allow(clippy::module_inception)]\nmod python;\nm"
  },
  {
    "path": "crates/prek/src/languages/python/pep723.rs",
    "chars": 9421,
    "preview": "// MIT License\n//\n// Copyright (c) 2025 Astral Software Inc.\n//\n// Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "crates/prek/src/languages/python/pyproject.rs",
    "chars": 5031,
    "preview": "use std::io;\nuse std::path::Path;\n\nuse anyhow::Result;\nuse serde::Deserialize;\nuse tracing::trace;\n\nuse crate::config::L"
  },
  {
    "path": "crates/prek/src/languages/python/python.rs",
    "chars": 15124,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync"
  },
  {
    "path": "crates/prek/src/languages/python/uv.rs",
    "chars": 25262,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\nuse std::sync::LazyLock;"
  },
  {
    "path": "crates/prek/src/languages/python/version.rs",
    "chars": 9019,
    "preview": "//! Implement `-p <python_spec>` argument parser of `virutualenv` from\n//! <https://github.com/pypa/virtualenv/blob/216d"
  },
  {
    "path": "crates/prek/src/languages/ruby/gem.rs",
    "chars": 14783,
    "preview": "use std::ffi::OsStr;\nuse std::path::{Path, PathBuf};\nuse std::time::Duration;\n\nuse anyhow::{Context, Result};\nuse future"
  },
  {
    "path": "crates/prek/src/languages/ruby/installer.rs",
    "chars": 32753,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::path::{Path, PathBuf};\n\nuse anyhow::{Context, Result};\nuse itertools::Iter"
  },
  {
    "path": "crates/prek/src/languages/ruby/mod.rs",
    "chars": 358,
    "preview": "#![warn(dead_code)]\n#![warn(clippy::missing_errors_doc)]\n#![warn(clippy::missing_panics_doc)]\n#![warn(clippy::must_use_c"
  },
  {
    "path": "crates/prek/src/languages/ruby/ruby.rs",
    "chars": 6919,
    "preview": "use std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_co"
  },
  {
    "path": "crates/prek/src/languages/ruby/version.rs",
    "chars": 7366,
    "preview": "use std::fmt;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\n\nuse crate::hook::InstallInfo;\nuse crate::languages"
  },
  {
    "path": "crates/prek/src/languages/rust/installer.rs",
    "chars": 7032,
    "preview": "use std::fmt::Display;\nuse std::path::{Path, PathBuf};\n\nuse anyhow::{Context, Result};\nuse itertools::Itertools;\nuse pre"
  },
  {
    "path": "crates/prek/src/languages/rust/mod.rs",
    "chars": 150,
    "preview": "mod installer;\n#[allow(clippy::module_inception)]\nmod rust;\nmod rustup;\nmod version;\n\npub(crate) use rust::Rust;\npub(cra"
  },
  {
    "path": "crates/prek/src/languages/rust/rust.rs",
    "chars": 32468,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::ffi::OsStr;\nuse std::ops::Deref;\nuse std::path::{Path, PathBuf};\nuse std::"
  },
  {
    "path": "crates/prek/src/languages/rust/rustup.rs",
    "chars": 9768,
    "preview": "use std::env::consts::EXE_EXTENSION;\nuse std::path::{Path, PathBuf};\nuse std::sync::LazyLock;\n\nuse anyhow::{Context, Res"
  },
  {
    "path": "crates/prek/src/languages/rust/version.rs",
    "chars": 12975,
    "preview": "use std::fmt::Display;\nuse std::ops::Deref;\nuse std::path::Path;\nuse std::str::FromStr;\n\nuse crate::hook::InstallInfo;\nu"
  },
  {
    "path": "crates/prek/src/languages/script.rs",
    "chars": 2562,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::Result;\n\nuse crate::cli::reporter::{HookI"
  },
  {
    "path": "crates/prek/src/languages/swift.rs",
    "chars": 10460,
    "preview": "use std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::{Context, Result};\nuse prek_co"
  },
  {
    "path": "crates/prek/src/languages/system.rs",
    "chars": 2089,
    "preview": "use std::path::Path;\nuse std::process::Stdio;\nuse std::sync::Arc;\n\nuse anyhow::Result;\n\nuse crate::cli::reporter::{HookI"
  },
  {
    "path": "crates/prek/src/languages/version.rs",
    "chars": 4914,
    "preview": "use std::str::FromStr;\n\nuse crate::config::Language;\nuse crate::hook::InstallInfo;\nuse crate::languages::bun::BunRequest"
  },
  {
    "path": "crates/prek/src/main.rs",
    "chars": 16584,
    "preview": "use std::fmt::Write;\nuse std::path::PathBuf;\nuse std::process::ExitCode;\nuse std::str::FromStr;\nuse std::sync::Mutex;\n\nu"
  },
  {
    "path": "crates/prek/src/printer.rs",
    "chars": 4306,
    "preview": "// MIT License\n//\n// Copyright (c) 2023 Astral Software Inc.\n//\n// Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "crates/prek/src/process.rs",
    "chars": 17972,
    "preview": "// Copyright (c) 2023 Axo Developer Co.\n//\n// Permission is hereby granted, free of charge, to any\n// person obtaining a"
  },
  {
    "path": "crates/prek/src/profiler.rs",
    "chars": 1203,
    "preview": "use tracing::error;\n\n/// Creates a profiler guard and returns it.\npub(crate) fn start_profiling() -> Option<pprof::Profi"
  },
  {
    "path": "crates/prek/src/resource_limit.rs",
    "chars": 4532,
    "preview": "// MIT License\n// Copyright (c) 2025 Astral Software Inc.\n// Permission is hereby granted, free of charge, to any person"
  },
  {
    "path": "crates/prek/src/run.rs",
    "chars": 13973,
    "preview": "use std::cmp::max;\nuse std::ffi::OsStr;\nuse std::path::Path;\nuse std::sync::LazyLock;\n\nuse anstream::ColorChoice;\nuse fu"
  },
  {
    "path": "crates/prek/src/schema.rs",
    "chars": 13525,
    "preview": "use crate::config::{\n    BuiltinHook, BuiltinRepo, FilePattern, LocalRepo, MetaHook, MetaRepo, PassFilenames,\n    Remote"
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__language_version.snap",
    "chars": 4949,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nOk(\n    Config {\n        repos: [\n            Local(\n      "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__meta_hooks-5.snap",
    "chars": 5171,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Meta(\n            MetaRepo {\n"
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__numeric_rev_is_parsed_as_string.snap",
    "chars": 1799,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: config\n---\nConfig {\n    repos: [\n        Remote(\n            RemoteRep"
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__parse_hooks-3.snap",
    "chars": 1750,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__parse_repos-2.snap",
    "chars": 1982,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__parse_repos-3.snap",
    "chars": 1972,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__parse_repos-4.snap",
    "chars": 1794,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Remote(\n            RemoteRep"
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__parse_repos-6.snap",
    "chars": 1794,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Remote(\n            RemoteRep"
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__parse_repos.snap",
    "chars": 1755,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: result\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__read_config_with_merge_keys.snap",
    "chars": 3456,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: config\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__read_config_with_nested_merge_keys.snap",
    "chars": 2561,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: config\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__read_manifest.snap",
    "chars": 4165,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: manifest\n---\nManifest {\n    hooks: [\n        ManifestHook {\n          "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__read_toml_config.snap",
    "chars": 4715,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: config\n---\nConfig {\n    repos: [\n        Local(\n            LocalRepo "
  },
  {
    "path": "crates/prek/src/snapshots/prek__config__tests__read_yaml_config.snap",
    "chars": 11606,
    "preview": "---\nsource: crates/prek/src/config.rs\nexpression: config\n---\nConfig {\n    repos: [\n        Remote(\n            RemoteRep"
  },
  {
    "path": "crates/prek/src/store.rs",
    "chars": 14866,
    "preview": "use std::hash::{DefaultHasher, Hash, Hasher};\nuse std::io::Write;\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\n\nu"
  },
  {
    "path": "crates/prek/src/version.rs",
    "chars": 3634,
    "preview": "/* MIT License\r\n\r\nCopyright (c) 2023 Astral Software Inc.\r\n\r\nPermission is hereby granted, free of charge, to any person"
  },
  {
    "path": "crates/prek/src/warnings.rs",
    "chars": 3022,
    "preview": "// MIT License\n//\n// Copyright (c) 2023 Astral Software Inc.\n//\n// Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "crates/prek/src/workspace.rs",
    "chars": 34869,
    "preview": "use std::borrow::Cow;\nuse std::fmt::Display;\nuse std::hash::{DefaultHasher, Hash, Hasher};\nuse std::path::{Path, PathBuf"
  },
  {
    "path": "crates/prek/src/yaml.rs",
    "chars": 4149,
    "preview": "// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or t"
  },
  {
    "path": "crates/prek/tests/auto_update.rs",
    "chars": 42346,
    "preview": "use anyhow::Result;\nuse assert_cmd::assert::OutputAssertExt;\nuse assert_fs::fixture::ChildPath;\nuse assert_fs::prelude::"
  },
  {
    "path": "crates/prek/tests/builtin_hooks.rs",
    "chars": 65656,
    "preview": "#[cfg(unix)]\nuse prek_consts::env_vars::EnvVars;\n#[cfg(unix)]\nuse std::os::unix::fs::PermissionsExt;\n\nuse anyhow::Result"
  },
  {
    "path": "crates/prek/tests/cache.rs",
    "chars": 23230,
    "preview": "use assert_fs::assert::PathAssert;\nuse assert_fs::fixture::{ChildPath, PathChild, PathCreateDir};\nuse assert_fs::prelude"
  },
  {
    "path": "crates/prek/tests/common/mod.rs",
    "chars": 14379,
    "preview": "#![allow(dead_code, unreachable_pub)]\n\nuse std::ffi::{OsStr, OsString};\nuse std::path::{Path, PathBuf};\nuse std::process"
  },
  {
    "path": "crates/prek/tests/fixtures/go.yaml",
    "chars": 444,
    "preview": "repos:\n  - repo: local\n    hooks:\n      - id: golang\n        name: golang\n        language: golang\n        entry: gofump"
  },
  {
    "path": "crates/prek/tests/fixtures/issue227.yaml",
    "chars": 106,
    "preview": "repos:\n  - repo: https://github.com/tox-dev/tox-ini-fmt\n    rev: 1.5.0\n    hooks:\n      - id: tox-ini-fmt\n"
  },
  {
    "path": "crates/prek/tests/fixtures/issue253/biome.json",
    "chars": 105,
    "preview": "{\n    \"root\": false,\n    \"formatter\": {\n        \"indentStyle\": \"space\",\n        \"indentWidth\": 4\n    }\n}\n"
  },
  {
    "path": "crates/prek/tests/fixtures/issue253/input.json",
    "chars": 32,
    "preview": "{ \"hello\": { \"name\": \"world\"} }\n"
  },
  {
    "path": "crates/prek/tests/fixtures/issue253/issue253.yaml",
    "chars": 166,
    "preview": "repos:\n  - repo: https://github.com/biomejs/pre-commit\n    rev: v0.6.1\n    hooks:\n      - id: biome-check\n        additi"
  },
  {
    "path": "crates/prek/tests/fixtures/issue265.yaml",
    "chars": 139,
    "preview": "repos:\n  - repo: https://github.com/Lucas-C/pre-commit-hooks\n    rev: v1.4.2\n    hooks:\n      - id: remove-crlf\n        "
  },
  {
    "path": "crates/prek/tests/fixtures/node-dependencies.yaml",
    "chars": 249,
    "preview": "repos:\n  - repo: local\n    hooks:\n      - id: node\n        name: node\n        language: node\n        entry: cowsay Hello"
  },
  {
    "path": "crates/prek/tests/fixtures/node-version.yaml",
    "chars": 416,
    "preview": "repos:\n  - repo: local\n    hooks:\n      - id: node\n        name: node\n        language: node\n        entry: node -p 'pro"
  },
  {
    "path": "crates/prek/tests/fixtures/python-version.yaml",
    "chars": 264,
    "preview": "repos:\n  - repo: local\n    hooks:\n      - id: python-3.11\n        name: Python 3.11\n        entry: python -c \"import sys"
  },
  {
    "path": "crates/prek/tests/fixtures/repeated-repos.yaml",
    "chars": 239,
    "preview": "repos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v5.0.0\n    hooks:\n      - id: trailing-whitespa"
  },
  {
    "path": "crates/prek/tests/fixtures/uv-pre-commit-config.yaml",
    "chars": 1080,
    "preview": "fail_fast: true\n\nexclude: |\n  (?x)^(\n    .*/(snapshots)/.*|\n  )$\n\nrepos:\n  - repo: https://github.com/abravalheri/valida"
  },
  {
    "path": "crates/prek/tests/fixtures/uv-pre-commit-hooks.yaml",
    "chars": 896,
    "preview": "- id: pip-compile\n  name: pip-compile\n  description: \"Automatically run 'uv pip compile' on your requirements\"\n  entry: "
  },
  {
    "path": "crates/prek/tests/hook_impl.rs",
    "chars": 23937,
    "preview": "#[cfg(unix)]\nuse std::os::unix::fs::PermissionsExt;\n#[cfg(unix)]\nuse std::path::Path;\n\nuse assert_cmd::assert::OutputAss"
  },
  {
    "path": "crates/prek/tests/identify.rs",
    "chars": 1856,
    "preview": "#[cfg(unix)]\nuse crate::common::{TestContext, cmd_snapshot};\n#[cfg(unix)]\nuse assert_fs::fixture::{FileWriteStr, PathChi"
  },
  {
    "path": "crates/prek/tests/install.rs",
    "chars": 42953,
    "preview": "use crate::common::{TestContext, cmd_snapshot, git_cmd};\nuse assert_cmd::assert::OutputAssertExt;\nuse assert_fs::assert:"
  },
  {
    "path": "crates/prek/tests/languages/bun.rs",
    "chars": 6325,
    "preview": "use anyhow::Result;\nuse assert_fs::assert::PathAssert;\nuse assert_fs::fixture::PathChild;\nuse prek_consts::env_vars::Env"
  },
  {
    "path": "crates/prek/tests/languages/deno.rs",
    "chars": 16739,
    "preview": "use assert_fs::assert::PathAssert;\nuse assert_fs::fixture::{FileWriteStr, PathChild};\nuse prek_consts::env_vars::EnvVars"
  },
  {
    "path": "crates/prek/tests/languages/docker.rs",
    "chars": 2535,
    "preview": "use assert_fs::fixture::{FileWriteStr, PathChild};\n\nuse crate::common::{TestContext, cmd_snapshot};\n\n/// GitHub Action o"
  },
  {
    "path": "crates/prek/tests/languages/docker_image.rs",
    "chars": 3984,
    "preview": "use std::os::unix::fs::PermissionsExt;\n\nuse anyhow::Result;\nuse assert_cmd::Command;\nuse assert_fs::fixture::{FileWriteS"
  },
  {
    "path": "crates/prek/tests/languages/fail.rs",
    "chars": 1117,
    "preview": "use anyhow::Result;\nuse assert_fs::prelude::*;\n\nuse crate::common::{TestContext, cmd_snapshot};\n\n/// GitHub Action only "
  },
  {
    "path": "crates/prek/tests/languages/golang.rs",
    "chars": 11076,
    "preview": "use assert_fs::assert::PathAssert;\nuse assert_fs::fixture::{FileWriteStr, PathChild, PathCreateDir};\nuse prek_consts::en"
  },
  {
    "path": "crates/prek/tests/languages/haskell.rs",
    "chars": 3739,
    "preview": "use assert_fs::fixture::{FileWriteStr, PathChild};\nuse prek_consts::env_vars::EnvVars;\n\nuse crate::common::{TestContext,"
  },
  {
    "path": "crates/prek/tests/languages/julia.rs",
    "chars": 4990,
    "preview": "use crate::common::{TestContext, cmd_snapshot};\n\n#[test]\nfn local_hook() {\n    let context = TestContext::new();\n    con"
  },
  {
    "path": "crates/prek/tests/languages/lua.rs",
    "chars": 7809,
    "preview": "use assert_fs::fixture::{FileWriteStr, PathChild};\n\nuse crate::common::{TestContext, cmd_snapshot};\n\n#[test]\nfn health_c"
  },
  {
    "path": "crates/prek/tests/languages/main.rs",
    "chars": 365,
    "preview": "#[path = \"../common/mod.rs\"]\nmod common;\n\nmod bun;\nmod deno;\n#[cfg(all(feature = \"docker\", target_os = \"linux\"))]\nmod do"
  },
  {
    "path": "crates/prek/tests/languages/node.rs",
    "chars": 7670,
    "preview": "use assert_fs::assert::PathAssert;\nuse assert_fs::fixture::PathChild;\nuse prek_consts::env_vars::EnvVars;\n\nuse crate::co"
  },
  {
    "path": "crates/prek/tests/languages/pygrep.rs",
    "chars": 11739,
    "preview": "use anyhow::Result;\n\nuse assert_fs::prelude::*;\n\nuse crate::common::{TestContext, cmd_snapshot};\n\n/// Test basic pygrep "
  },
  {
    "path": "crates/prek/tests/languages/python.rs",
    "chars": 16623,
    "preview": "use assert_fs::assert::PathAssert;\nuse assert_fs::fixture::{FileWriteStr, PathChild};\nuse prek_consts::PRE_COMMIT_HOOKS_"
  },
  {
    "path": "crates/prek/tests/languages/ruby.rs",
    "chars": 37400,
    "preview": "use assert_fs::fixture::{FileWriteStr, PathChild, PathCreateDir};\n\nuse crate::common::{TestContext, cmd_snapshot, git_cm"
  },
  {
    "path": "crates/prek/tests/languages/rust.rs",
    "chars": 7789,
    "preview": "use anyhow::Result;\nuse assert_fs::assert::PathAssert;\nuse assert_fs::fixture::PathChild;\nuse prek_consts::env_vars::Env"
  },
  {
    "path": "crates/prek/tests/languages/script.rs",
    "chars": 5822,
    "preview": "use anyhow::Result;\nuse assert_fs::fixture::{FileWriteStr, PathChild};\n\nuse crate::common::{TestContext, cmd_snapshot};\n"
  },
  {
    "path": "crates/prek/tests/languages/swift.rs",
    "chars": 5469,
    "preview": "use assert_fs::fixture::{FileWriteStr, PathChild, PathCreateDir};\nuse prek_consts::PRE_COMMIT_HOOKS_YAML;\nuse prek_const"
  },
  {
    "path": "crates/prek/tests/languages/unimplemented.rs",
    "chars": 871,
    "preview": "use crate::common::{TestContext, cmd_snapshot};\n\n#[test]\nfn unimplemented_language() {\n    let context = TestContext::ne"
  },
  {
    "path": "crates/prek/tests/languages/unsupported.rs",
    "chars": 1495,
    "preview": "/// Test `language: unsupported` and `language: unsupported_script` works.\n#[cfg(unix)]\n#[test]\nfn unsupported_language("
  },
  {
    "path": "crates/prek/tests/list.rs",
    "chars": 19274,
    "preview": "use crate::common::{TestContext, cmd_snapshot};\nuse indoc::indoc;\n\nmod common;\n\n#[test]\nfn list_basic() {\n    let contex"
  },
  {
    "path": "crates/prek/tests/list_builtins.rs",
    "chars": 4906,
    "preview": "use crate::common::{TestContext, cmd_snapshot};\n\nmod common;\n\n#[test]\nfn list_builtins_basic() {\n    let context = TestC"
  },
  {
    "path": "crates/prek/tests/meta_hooks.rs",
    "chars": 8515,
    "preview": "mod common;\n\nuse crate::common::{TestContext, cmd_snapshot};\n\nuse assert_fs::fixture::{FileWriteStr, PathChild, PathCrea"
  }
]

// ... and 56 more files (download for full content)

About this extraction

This page contains the full source code of the j178/prek GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 256 files (2.3 MB), approximately 606.0k tokens, and a symbol index with 2219 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!