Skip to content
Draft
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
58 changes: 43 additions & 15 deletions src/cli/config_merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::borrow::Cow;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tracing::{debug, debug_span, trace, warn};

use crate::localization::{self, keys};

Expand Down Expand Up @@ -45,9 +46,11 @@ fn env_config_path<F>(var_os: F, var_name: &str) -> Option<PathBuf>
where
F: Fn(&str) -> Option<std::ffi::OsString>,
{
var_os(var_name)
let path = var_os(var_name)
.filter(|value| !value.is_empty())
.map(PathBuf::from)
.map(PathBuf::from);
trace!(var_name, found = path.is_some(), path = ?path, "read config path variable");
path
}

#[expect(
Expand All @@ -58,11 +61,21 @@ fn resolve_config_path<F>(cli: &Cli, var_os: F) -> Option<PathBuf>
where
F: Fn(&str) -> Option<std::ffi::OsString>,
{
cli.config
.as_ref()
.cloned()
.or_else(|| env_config_path(&var_os, CONFIG_ENV_VAR))
.or_else(|| env_config_path(var_os, CONFIG_ENV_VAR_LEGACY))
let (selector, resolved_path) = cli.config.as_ref().cloned().map_or_else(
|| {
env_config_path(&var_os, CONFIG_ENV_VAR).map_or_else(
|| {
env_config_path(var_os, CONFIG_ENV_VAR_LEGACY)
.map_or(("none", None), |path| (CONFIG_ENV_VAR_LEGACY, Some(path)))
},
|path| (CONFIG_ENV_VAR, Some(path)),
)
},
|path| ("cli_flag", Some(path)),
);

debug!(selector, path = ?resolved_path, "resolved config path");
resolved_path
}

fn load_layers_from_path(path: &Path) -> OrthoResult<Vec<MergeLayer<'static>>> {
Expand All @@ -72,14 +85,21 @@ fn load_layers_from_path(path: &Path) -> OrthoResult<Vec<MergeLayer<'static>>> {
.into_iter()
.map(|(value, layer_path)| MergeLayer::file(Cow::Owned(value), Some(layer_path)))
.collect()),
Ok(None) => Err(Arc::new(OrthoError::File {
path: path.to_path_buf(),
source: Box::new(io::Error::new(
io::ErrorKind::NotFound,
"explicit configuration file not found",
)),
})),
Err(err) => Err(err),
Ok(None) => {
let error = Arc::new(OrthoError::File {
path: path.to_path_buf(),
source: Box::new(io::Error::new(
io::ErrorKind::NotFound,
"explicit configuration file not found",
)),
});
warn!(path = ?path, error = %error, "explicit config load failed");
Err(error)
}
Err(error) => {
warn!(path = ?path, error = %error, "explicit config load failed");
Err(error)
}
}
}

Expand Down Expand Up @@ -148,10 +168,14 @@ fn diag_json_from_layer(value: &serde_json::Value) -> Option<bool> {
/// load failures so startup diagnostic-mode selection reports the same
/// configuration errors as the full merge path.
fn collect_diag_file_layers(cli: &Cli) -> OrthoResult<Vec<MergeLayer<'static>>> {
let _span = debug_span!("collect_diag_file_layers").entered();

if let Some(path) = resolve_config_path(cli, |name| std::env::var_os(name)) {
debug!(path = ?path, "using explicit config path");
return load_layers_from_path(&path);
}

debug!("using config discovery");
let discovery = config_discovery(cli.directory.as_deref());
let file_layers = discovery.compose_layers().value;
let project_file = project_scope_file_str(cli.directory.as_deref());
Expand All @@ -160,8 +184,10 @@ fn collect_diag_file_layers(cli: &Cli) -> OrthoResult<Vec<MergeLayer<'static>>>
.is_some_and(|p| project_file.as_deref() == Some(p.as_str()))
});
if first_pass_found_project {
debug!(project_file = ?project_file, "discovery included project-scope layers");
Ok(file_layers)
} else {
debug!(project_file = ?project_file, "appending project-scope layers");
project_scope_layers(cli.directory.as_deref())
.map(|project_layers| file_layers.into_iter().chain(project_layers).collect())
}
Expand Down Expand Up @@ -243,10 +269,12 @@ fn push_file_layers(
cli: &Cli,
) {
if let Some(path) = resolve_config_path(cli, |name| std::env::var_os(name)) {
debug!(path = ?path, "using explicit config path");
push_layers_result(composer, errors, load_layers_from_path(&path));
return;
}

debug!("using config discovery");
let discovery = config_discovery(cli.directory.as_deref());
let mut file_layers = discovery.compose_layers();
errors.append(&mut file_layers.required_errors);
Expand Down
Loading