use std::collections::HashMap;
use crate::error::Result;
pub(super) fn parse_params(raw: &[String]) -> HashMap<String, String> {
raw.iter()
.filter_map(|s| s.split_once('='))
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect()
}
pub(super) fn resolve_init_source(
source: Option<String>,
source_env: Option<String>,
source_file: Option<String>,
) -> Result<(String, crate::init::SourceProvenance)> {
use crate::init::SourceProvenance;
if let Some(url) = source {
return Ok((url, SourceProvenance::Inline));
}
if let Some(var) = source_env {
let url = std::env::var(&var)
.map_err(|_| anyhow::anyhow!("--source-env '{}' is not set in the environment", var))?;
return Ok((url, SourceProvenance::Env(var)));
}
if let Some(path) = source_file {
let raw = std::fs::read_to_string(&path)
.map_err(|e| anyhow::anyhow!("cannot read --source-file '{}': {}", path, e))?;
return Ok((raw.trim().to_string(), SourceProvenance::File(path)));
}
anyhow::bail!("--source, --source-env, or --source-file is required")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_params_basic() {
let input = vec!["KEY=value".to_string()];
let result = parse_params(&input);
assert_eq!(result.get("KEY").unwrap(), "value");
}
#[test]
fn parse_params_equals_in_value() {
let input = vec!["FILTER=x=1 AND y=2".to_string()];
let result = parse_params(&input);
assert_eq!(result.get("FILTER").unwrap(), "x=1 AND y=2");
}
#[test]
fn parse_params_multiple() {
let input = vec!["A=1".to_string(), "B=2".to_string()];
let result = parse_params(&input);
assert_eq!(result.len(), 2);
assert_eq!(result.get("A").unwrap(), "1");
assert_eq!(result.get("B").unwrap(), "2");
}
#[test]
fn parse_params_empty_input() {
let result = parse_params(&[]);
assert!(result.is_empty());
}
#[test]
fn parse_params_no_equals_skipped() {
let input = vec!["NO_EQUALS_HERE".to_string()];
let result = parse_params(&input);
assert!(result.is_empty());
}
#[test]
fn parse_params_empty_value() {
let input = vec!["KEY=".to_string()];
let result = parse_params(&input);
assert_eq!(result.get("KEY").unwrap(), "");
}
#[test]
fn parse_params_duplicate_last_wins() {
let input = vec!["K=first".to_string(), "K=second".to_string()];
let result = parse_params(&input);
assert_eq!(result.get("K").unwrap(), "second");
}
#[test]
fn json_error_output_is_valid_json() {
let err = anyhow::anyhow!("connection refused");
let output = serde_json::json!({"error": format!("{err:#}")}).to_string();
let parsed: serde_json::Value = serde_json::from_str(&output).expect("must be valid JSON");
assert_eq!(parsed["error"], "connection refused");
}
}