mod cla; mod cur; use crate::invalid_data_error; use serde_json::Value as JsonValue; use std::fs; use std::io; use std::path::Path; use std::path::PathBuf; use toml::Value as TomlValue; pub use cla::ClaSource; pub use cur::CurSource; #[derive(Debug, Clone, PartialEq, Eq)] pub struct InstructionSourceGroup { pub scope: PathBuf, pub sources: Vec, } fn read_json_file(path: &Path) -> io::Result> { if !path.is_file() { return Ok(None); } let raw = fs::read_to_string(path)?; let value = serde_json::from_str(&raw).map_err(|err| invalid_data_error(err.to_string()))?; Ok(Some(value)) } fn build_config( settings: &JsonValue, append_source_config: fn( &mut toml::map::Map, &serde_json::Map, ), ) -> io::Result { let Some(settings) = settings.as_object() else { return Err(invalid_data_error( "external agent settings root must be an object", )); }; let mut root = toml::map::Map::new(); if let Some(env) = settings.get("env").and_then(JsonValue::as_object) && !env.is_empty() { let mut shell_policy = toml::map::Map::new(); shell_policy.insert("inherit".to_string(), TomlValue::String("core".to_string())); shell_policy.insert( "set".to_string(), TomlValue::Table(json_object_to_env_toml_table(env)), ); root.insert( "shell_environment_policy".to_string(), TomlValue::Table(shell_policy), ); } append_source_config(&mut root, settings); Ok(TomlValue::Table(root)) } fn json_object_to_env_toml_table( object: &serde_json::Map, ) -> toml::map::Map { let mut table = toml::map::Map::new(); for (key, value) in object { if let Some(value) = json_env_value_to_string(value) { table.insert(key.clone(), TomlValue::String(value)); } } table } fn json_env_value_to_string(value: &JsonValue) -> Option { match value { JsonValue::String(value) => Some(value.clone()), JsonValue::Null => None, JsonValue::Bool(value) => Some(value.to_string()), JsonValue::Number(value) => Some(value.to_string()), JsonValue::Array(_) | JsonValue::Object(_) => None, } } fn is_non_empty_text_file(path: &Path) -> io::Result { if !path.is_file() { return Ok(false); } Ok(!fs::read_to_string(path)?.trim().is_empty()) }