config: add per-command and global impure knobs; bump deps
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Icadc94f1e1ca1c007feee7766c60847c6a6a6964
This commit is contained in:
parent
8836eacb95
commit
e385c74b57
6 changed files with 321 additions and 25 deletions
99
Cargo.lock
generated
99
Cargo.lock
generated
|
|
@ -25,9 +25,9 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.11.0"
|
version = "2.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
|
|
@ -37,9 +37,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.6.0"
|
version = "4.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
|
@ -57,18 +57,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_complete"
|
name = "clap_complete"
|
||||||
version = "4.6.0"
|
version = "4.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb"
|
checksum = "3ff7a1dccbdd8b078c2bdebff47e404615151534d5043da397ec50286816f9cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.6.0"
|
version = "4.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
|
checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -117,6 +117,7 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"toml",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
@ -152,9 +153,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.3.0"
|
version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
|
|
@ -186,9 +187,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
|
|
@ -204,12 +205,12 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.16.1",
|
"hashbrown 0.17.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
@ -228,9 +229,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.184"
|
version = "0.2.185"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
|
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
|
|
@ -343,9 +344,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.27"
|
version = "1.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
|
|
@ -390,6 +391,15 @@ dependencies = [
|
||||||
"zmij",
|
"zmij",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shell-words"
|
name = "shell-words"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
|
@ -457,6 +467,37 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "1.1.2+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_parser",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "1.1.1+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_parser"
|
||||||
|
version = "1.1.2+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||||
|
dependencies = [
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|
@ -493,11 +534,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasip2"
|
name = "wasip2"
|
||||||
version = "1.0.2+wasi-0.2.9"
|
version = "1.0.3+wasi-0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen 0.57.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -506,7 +547,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen 0.51.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -567,6 +608,12 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|
@ -576,6 +623,12 @@ dependencies = [
|
||||||
"wit-bindgen-rust-macro",
|
"wit-bindgen-rust-macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.57.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen-core"
|
name = "wit-bindgen-core"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ serde_json = "1.0.149"
|
||||||
tempfile = "3.27.0"
|
tempfile = "3.27.0"
|
||||||
textwrap = "0.16.2"
|
textwrap = "0.16.2"
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
|
toml = { default-features = false, features = [ "parse", "serde" ], version = "1.1.2" }
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
yansi = "1.0.1"
|
yansi = "1.0.1"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,6 @@ serde_json.workspace = true
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
textwrap.workspace = true
|
textwrap.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
|
toml.workspace = true
|
||||||
walkdir.workspace = true
|
walkdir.workspace = true
|
||||||
yansi.workspace = true
|
yansi.workspace = true
|
||||||
|
|
|
||||||
236
eh/src/config.rs
Normal file
236
eh/src/config.rs
Normal file
|
|
@ -0,0 +1,236 @@
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
env,
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct Config {
|
||||||
|
/// When `Some(true)`, pass `--impure` to every Nix command.
|
||||||
|
/// When `Some(false)`, block automatic impure retries for every command.
|
||||||
|
/// When absent (`None`), retry behaviour is automatic (default).
|
||||||
|
#[serde(default)]
|
||||||
|
pub impure: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub commands: HashMap<String, CommandConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Per-command configuration.
|
||||||
|
#[derive(Debug, Deserialize, Default, Clone)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct CommandConfig {
|
||||||
|
/// When `Some(true)`, pass `--impure` to the underlying Nix command.
|
||||||
|
/// When `Some(false)`, block automatic impure retries for this command.
|
||||||
|
/// When absent (`None`), the global setting is used; if that is also absent,
|
||||||
|
/// retry behaviour is automatic (default).
|
||||||
|
#[serde(default)]
|
||||||
|
pub impure: Option<bool>,
|
||||||
|
/// Additional environment variables to set for the Nix command.
|
||||||
|
#[serde(default)]
|
||||||
|
pub env: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
/// Return the [`CommandConfig`] for `command`.
|
||||||
|
///
|
||||||
|
/// Resolution order: per-command `impure` takes precedence over the global
|
||||||
|
/// `impure`. Neither being set means automatic retry behaviour.
|
||||||
|
pub fn for_command(&self, command: &str) -> CommandConfig {
|
||||||
|
let mut cmd = self.commands.get(command).cloned().unwrap_or_default();
|
||||||
|
// Per-command setting wins; fall back to global.
|
||||||
|
if cmd.impure.is_none() {
|
||||||
|
cmd.impure = self.impure;
|
||||||
|
}
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load configuration from the first `.eh.toml` found by walking up from the
|
||||||
|
/// current directory, or from `~/.config/eh/config.toml` as a global
|
||||||
|
/// fallback. Returns a default (empty) config if no file is found or if
|
||||||
|
/// parsing fails.
|
||||||
|
pub fn load() -> Config {
|
||||||
|
if let Some(path) = find_project_config()
|
||||||
|
&& let Some(cfg) = load_from_file(&path)
|
||||||
|
{
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(path) = global_config_path()
|
||||||
|
&& let Some(cfg) = load_from_file(&path)
|
||||||
|
{
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_project_config() -> Option<PathBuf> {
|
||||||
|
let mut dir = env::current_dir().ok()?;
|
||||||
|
loop {
|
||||||
|
let candidate = dir.join(".eh.toml");
|
||||||
|
if candidate.exists() {
|
||||||
|
return Some(candidate);
|
||||||
|
}
|
||||||
|
if !dir.pop() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global_config_path() -> Option<PathBuf> {
|
||||||
|
let home = env::var("HOME").ok()?;
|
||||||
|
Some(
|
||||||
|
PathBuf::from(home)
|
||||||
|
.join(".config")
|
||||||
|
.join("eh")
|
||||||
|
.join("config.toml"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_from_file(path: &Path) -> Option<Config> {
|
||||||
|
let content = fs::read_to_string(path).ok()?;
|
||||||
|
match toml::de::from_str::<Config>(&content) {
|
||||||
|
Ok(cfg) => Some(cfg),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"eh: warning: failed to parse config file {}: {}",
|
||||||
|
path.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_config_defaults() {
|
||||||
|
let cfg: Config = toml::from_str("").unwrap();
|
||||||
|
assert!(cfg.impure.is_none());
|
||||||
|
assert!(cfg.commands.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_command_config_impure_true() {
|
||||||
|
let cfg: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
[commands.build]
|
||||||
|
impure = true
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(cfg.for_command("build").impure, Some(true));
|
||||||
|
assert_eq!(cfg.for_command("run").impure, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_command_config_impure_false() {
|
||||||
|
let cfg: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
[commands.build]
|
||||||
|
impure = false
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(cfg.for_command("build").impure, Some(false));
|
||||||
|
assert_eq!(cfg.for_command("run").impure, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_global_impure_propagates_to_unconfigured_commands() {
|
||||||
|
let cfg: Config = toml::from_str("impure = true").unwrap();
|
||||||
|
// Commands with no per-command entry inherit global.
|
||||||
|
assert_eq!(cfg.for_command("build").impure, Some(true));
|
||||||
|
assert_eq!(cfg.for_command("nonexistent").impure, Some(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_global_impure_false_propagates_to_unconfigured_commands() {
|
||||||
|
let cfg: Config = toml::from_str("impure = false").unwrap();
|
||||||
|
assert_eq!(cfg.for_command("build").impure, Some(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_per_command_impure_overrides_global() {
|
||||||
|
// Per-command setting wins over global.
|
||||||
|
let cfg: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
impure = false
|
||||||
|
|
||||||
|
[commands.build]
|
||||||
|
impure = true
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(cfg.for_command("build").impure, Some(true));
|
||||||
|
// Command without per-command entry falls back to global false.
|
||||||
|
assert_eq!(cfg.for_command("run").impure, Some(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_command_config_env() {
|
||||||
|
let cfg: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
[commands.develop]
|
||||||
|
env = { FOO = "bar", BAZ = "1" }
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let dev = cfg.for_command("develop");
|
||||||
|
assert_eq!(dev.env.get("FOO").map(String::as_str), Some("bar"));
|
||||||
|
assert_eq!(dev.env.get("BAZ").map(String::as_str), Some("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_command_config_env_table_syntax() {
|
||||||
|
let cfg: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
[commands.shell]
|
||||||
|
impure = true
|
||||||
|
|
||||||
|
[commands.shell.env]
|
||||||
|
MY_VAR = "hello"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let shell = cfg.for_command("shell");
|
||||||
|
assert_eq!(shell.impure, Some(true));
|
||||||
|
assert_eq!(shell.env.get("MY_VAR").map(String::as_str), Some("hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_for_command_missing_returns_default() {
|
||||||
|
let cfg = Config::default();
|
||||||
|
let cc = cfg.for_command("nonexistent");
|
||||||
|
assert_eq!(cc.impure, None);
|
||||||
|
assert!(cc.env.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unknown_top_level_key_is_rejected() {
|
||||||
|
let result = toml::de::from_str::<Config>("unknown_key = true");
|
||||||
|
assert!(result.is_err(), "unknown top-level keys should be rejected");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unknown_command_key_is_rejected() {
|
||||||
|
let result = toml::de::from_str::<Config>(
|
||||||
|
r#"
|
||||||
|
[commands.build]
|
||||||
|
typo_key = true
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
result.is_err(),
|
||||||
|
"unknown per-command keys should be rejected"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod config;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use eh::{Cli, Command, CommandFactory, Parser};
|
||||||
use yansi::Paint;
|
use yansi::Paint;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
|
@ -29,11 +30,13 @@ fn handle_command(command: &str, args: &[String]) -> error::Result<i32> {
|
||||||
let hash_extractor = util::RegexHashExtractor;
|
let hash_extractor = util::RegexHashExtractor;
|
||||||
let fixer = util::DefaultNixFileFixer;
|
let fixer = util::DefaultNixFileFixer;
|
||||||
let classifier = util::DefaultNixErrorClassifier;
|
let classifier = util::DefaultNixErrorClassifier;
|
||||||
|
let cfg = config::load();
|
||||||
|
let cmd_cfg = cfg.for_command(command);
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
"info" => commands::info::handle_info(args),
|
"info" => commands::info::handle_info(args, &cmd_cfg),
|
||||||
|
|
||||||
"update" => commands::update::handle_update(args),
|
"update" => commands::update::handle_update(args, &cmd_cfg),
|
||||||
"run" | "shell" | "build" | "develop" => {
|
"run" | "shell" | "build" | "develop" => {
|
||||||
commands::handle_nix_command(
|
commands::handle_nix_command(
|
||||||
command,
|
command,
|
||||||
|
|
@ -41,6 +44,7 @@ fn handle_command(command: &str, args: &[String]) -> error::Result<i32> {
|
||||||
&hash_extractor,
|
&hash_extractor,
|
||||||
&fixer,
|
&fixer,
|
||||||
&classifier,
|
&classifier,
|
||||||
|
&cmd_cfg,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue