Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/prek-consts/src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ impl EnvVars {
pub const PREK_SKIP: &'static str = "PREK_SKIP";
pub const PREK_ALLOW_NO_CONFIG: &'static str = "PREK_ALLOW_NO_CONFIG";
pub const PREK_NO_CONCURRENCY: &'static str = "PREK_NO_CONCURRENCY";
pub const PREK_MAX_CONCURRENCY: &'static str = "PREK_MAX_CONCURRENCY";
pub const PREK_NO_FAST_PATH: &'static str = "PREK_NO_FAST_PATH";
pub const PREK_UV_SOURCE: &'static str = "PREK_UV_SOURCE";
pub const PREK_NATIVE_TLS: &'static str = "PREK_NATIVE_TLS";
Expand Down
75 changes: 68 additions & 7 deletions crates/prek/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use rustc_hash::FxHashMap;
use tracing::trace;

use crate::hook::Hook;
use crate::warn_user;

pub(crate) static USE_COLOR: LazyLock<bool> =
LazyLock::new(|| match anstream::Stderr::choice(&std::io::stderr()) {
Expand All @@ -19,14 +20,34 @@ pub(crate) static USE_COLOR: LazyLock<bool> =
ColorChoice::Auto => unreachable!(),
});

pub(crate) static CONCURRENCY: LazyLock<usize> = LazyLock::new(|| {
if EnvVars::is_set(EnvVars::PREK_NO_CONCURRENCY) {
1
} else {
std::thread::available_parallelism()
.map(std::num::NonZero::get)
.unwrap_or(1)
fn resolve_concurrency(no_concurrency: bool, max_concurrency: Option<&str>, cpu: usize) -> usize {
if no_concurrency {
return 1;
}

if let Some(v) = max_concurrency {
if let Ok(cap) = v.parse::<usize>() {
return cap.max(1);
}
warn_user!(
"Invalid value for {}: {v:?}, using default ({cpu})",
EnvVars::PREK_MAX_CONCURRENCY,
);
}

cpu
}

pub(crate) static CONCURRENCY: LazyLock<usize> = LazyLock::new(|| {
let cpu = std::thread::available_parallelism()
.map(std::num::NonZero::get)
.unwrap_or(1);

resolve_concurrency(
EnvVars::is_set(EnvVars::PREK_NO_CONCURRENCY),
EnvVars::var(EnvVars::PREK_MAX_CONCURRENCY).ok().as_deref(),
cpu,
)
});

fn target_concurrency(serial: bool) -> usize {
Expand Down Expand Up @@ -352,6 +373,46 @@ mod tests {
assert_eq!(total_files, 100);
}

#[test]
fn test_resolve_concurrency_defaults_to_cpu() {
assert_eq!(resolve_concurrency(false, None, 16), 16);
}

#[test]
fn test_resolve_concurrency_max_caps_value() {
assert_eq!(resolve_concurrency(false, Some("4"), 16), 4);
}

#[test]
fn test_resolve_concurrency_max_above_cpu() {
assert_eq!(resolve_concurrency(false, Some("32"), 8), 32);
}

#[test]
fn test_resolve_concurrency_max_zero_floors_to_one() {
assert_eq!(resolve_concurrency(false, Some("0"), 16), 1);
}

#[test]
fn test_resolve_concurrency_max_invalid_falls_back() {
assert_eq!(resolve_concurrency(false, Some("abc"), 16), 16);
}

#[test]
fn test_resolve_concurrency_max_empty_falls_back() {
assert_eq!(resolve_concurrency(false, Some(""), 16), 16);
}

#[test]
fn test_resolve_concurrency_no_concurrency() {
assert_eq!(resolve_concurrency(true, None, 16), 1);
}

#[test]
fn test_resolve_concurrency_no_concurrency_overrides_max() {
assert_eq!(resolve_concurrency(true, Some("8"), 16), 1);
}

#[test]
fn test_partitions_respects_cli_length_limit() {
// Create files that will exceed CLI length limit
Expand Down
2 changes: 2 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,8 @@ prek supports the following environment variables:

- `PREK_NO_CONCURRENCY` — Disable parallelism for installs and runs (If set, force concurrency to 1).

- `PREK_MAX_CONCURRENCY` — Set the maximum number of concurrent hooks (minimum 1). Defaults to the number of CPU cores when unset. Ignored when `PREK_NO_CONCURRENCY` is set. If you encounter "Too many open files" errors, lowering this value or raising the file descriptor limit with `ulimit -n` can help.

- `PREK_NO_FAST_PATH` — Disable Rust-native built-in hooks; always use the original hook implementation. See [Built-in Fast Hooks](builtin.md) for details.

- `PREK_UV_SOURCE` — Control how uv (Python package installer) is installed. Options:
Expand Down
Loading