diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-05 19:38:29 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-05 19:38:29 +0900 |
| commit | 884d9ab32bbca7a8ec5c7ee7d42cbde0e7e6babf (patch) | |
| tree | e04e25f506f0174572b4634601ab9b317220d9e5 /crates/mozart/src | |
| parent | 49b0884701a84731652fc934d428932ff6029bd4 (diff) | |
| download | php-mozart-884d9ab32bbca7a8ec5c7ee7d42cbde0e7e6babf.tar.gz php-mozart-884d9ab32bbca7a8ec5c7ee7d42cbde0e7e6babf.tar.zst php-mozart-884d9ab32bbca7a8ec5c7ee7d42cbde0e7e6babf.zip | |
refactor(core): replace ComposerConfig with typed Config struct
Config uses serde with kebab-case field mapping; known properties are
strongly-typed fields and unknown keys flow into an extra BTreeMap.
resolve_references is moved to the new config module.
Diffstat (limited to 'crates/mozart/src')
| -rw-r--r-- | crates/mozart/src/commands/archive.rs | 13 | ||||
| -rw-r--r-- | crates/mozart/src/commands/config.rs | 139 | ||||
| -rw-r--r-- | crates/mozart/src/commands/dump_autoload.rs | 20 | ||||
| -rw-r--r-- | crates/mozart/src/commands/exec.rs | 7 | ||||
| -rw-r--r-- | crates/mozart/src/commands/run_script.rs | 21 |
5 files changed, 71 insertions, 129 deletions
diff --git a/crates/mozart/src/commands/archive.rs b/crates/mozart/src/commands/archive.rs index a075ade..4386e16 100644 --- a/crates/mozart/src/commands/archive.rs +++ b/crates/mozart/src/commands/archive.rs @@ -104,15 +104,10 @@ pub async fn execute( let (config_archive_format, config_archive_dir) = match composer.as_ref() { Some(c) => { let cfg = c.config(); - let fmt = cfg - .get("archive-format") - .and_then(|v| v.as_str()) - .map(|s| s.to_string()); - let dir = cfg - .get("archive-dir") - .and_then(|v| v.as_str()) - .map(|s| s.to_string()); - (fmt, dir) + ( + Some(cfg.archive_format.clone()), + Some(cfg.archive_dir.clone()), + ) } None => (None, None), }; diff --git a/crates/mozart/src/commands/config.rs b/crates/mozart/src/commands/config.rs index 71a5981..40336f3 100644 --- a/crates/mozart/src/commands/config.rs +++ b/crates/mozart/src/commands/config.rs @@ -60,7 +60,7 @@ pub struct ConfigArgs { pub source: bool, } -pub use mozart_core::composer::{ComposerConfig, resolve_references}; +use mozart_core::config::{Config, resolve_references}; /// Classification of config key value types for validation and normalization. #[derive(Debug)] @@ -754,17 +754,17 @@ fn execute_read( console: &mozart_core::console::Console, ) -> anyhow::Result<()> { // Build the effective config for config-section keys. - let mut config = ComposerConfig::defaults(); + let mut config = Config::default(); if args.global { let global_config_path = composer_home().join("config.json"); let overrides = load_config_section(&global_config_path)?; - config.merge(&overrides); + config.merge(&overrides)?; } else { let wd = cli.working_dir()?; let composer_json = wd.join("composer.json"); let overrides = load_config_section(&composer_json)?; - config.merge(&overrides); + config.merge(&overrides)?; } resolve_references(&mut config); @@ -772,27 +772,13 @@ fn execute_read( // If --absolute is requested, resolve *-dir values to absolute paths. if args.absolute { let wd = cli.working_dir()?; - let keys: Vec<String> = config.values.keys().cloned().collect(); - for key in keys { - if key.ends_with("-dir") - && let Some(serde_json::Value::String(s)) = config.values.get(&key).cloned() - { - let p = std::path::Path::new(&s); - if p.is_relative() { - let abs = wd.join(p); - config.values.insert( - key, - serde_json::Value::String(abs.to_string_lossy().into_owned()), - ); - } - } - } + config.make_dirs_absolute(&wd); } if args.list { - for (key, value) in &config.values { + for (key, value) in config.entries() { console.write_stdout( - &format!("[{}] {}", key, render_value(value)), + &format!("[{}] {}", key, render_value(&value)), mozart_core::console::Verbosity::Quiet, ); } @@ -853,8 +839,10 @@ fn execute_read( // 4. Standard config key lookup match config.get(key) { Some(value) => { - console - .write_stdout(&render_value(value), mozart_core::console::Verbosity::Quiet); + console.write_stdout( + &render_value(&value), + mozart_core::console::Verbosity::Quiet, + ); } None => { return Err(anyhow!("Setting \"{}\" does not exist.", key)); @@ -872,7 +860,7 @@ mod tests { #[test] fn test_defaults_contain_expected_keys() { - let cfg = ComposerConfig::defaults(); + let cfg = Config::default(); let required_keys = [ "process-timeout", @@ -908,127 +896,109 @@ mod tests { ]; for key in &required_keys { - assert!(cfg.values.contains_key(*key), "defaults missing key: {key}"); + assert!(cfg.get(*key).is_some(), "defaults missing key: {key}"); } } #[test] fn test_defaults_values_correct() { - let cfg = ComposerConfig::defaults(); + let cfg = Config::default(); - assert_eq!(cfg.values["process-timeout"], serde_json::json!(300)); - assert_eq!(cfg.values["preferred-install"], serde_json::json!("dist")); - assert_eq!(cfg.values["vendor-dir"], serde_json::json!("vendor")); - assert_eq!( - cfg.values["github-protocols"], - serde_json::json!(["https", "ssh", "git"]) - ); - assert_eq!(cfg.values["secure-http"], serde_json::json!(true)); - assert_eq!(cfg.values["lock"], serde_json::json!(true)); - assert_eq!(cfg.values["autoloader-suffix"], serde_json::Value::Null); + assert_eq!(cfg.process_timeout, 300); + assert_eq!(cfg.preferred_install, serde_json::json!("dist")); + assert_eq!(cfg.vendor_dir, "vendor"); + assert_eq!(cfg.github_protocols, vec!["https", "ssh", "git"]); + assert_eq!(cfg.secure_http, true); + assert_eq!(cfg.lock, true); + assert_eq!(cfg.autoloader_suffix, None); } #[test] fn test_merge_overrides_existing_key() { - let mut cfg = ComposerConfig::defaults(); + let mut cfg = Config::default(); let mut overrides = BTreeMap::new(); overrides.insert("vendor-dir".to_string(), serde_json::json!("packages")); overrides.insert("sort-packages".to_string(), serde_json::json!(true)); - cfg.merge(&overrides); + cfg.merge(&overrides).unwrap(); - assert_eq!(cfg.values["vendor-dir"], serde_json::json!("packages")); - assert_eq!(cfg.values["sort-packages"], serde_json::json!(true)); + assert_eq!(cfg.vendor_dir, "packages"); + assert_eq!(cfg.sort_packages, true); } #[test] fn test_merge_adds_new_key() { - let mut cfg = ComposerConfig::defaults(); + let mut cfg = Config::default(); let mut overrides = BTreeMap::new(); overrides.insert("custom-key".to_string(), serde_json::json!("custom-value")); - cfg.merge(&overrides); + cfg.merge(&overrides).unwrap(); - assert_eq!(cfg.values["custom-key"], serde_json::json!("custom-value")); + assert_eq!(cfg.extra["custom-key"], serde_json::json!("custom-value")); } #[test] fn test_merge_empty_overrides_leaves_defaults_intact() { - let mut cfg = ComposerConfig::defaults(); - let original_vendor = cfg.values["vendor-dir"].clone(); + let mut cfg = Config::default(); + let original_vendor = cfg.vendor_dir.clone(); - cfg.merge(&BTreeMap::new()); + cfg.merge(&BTreeMap::new()).unwrap(); - assert_eq!(cfg.values["vendor-dir"], original_vendor); + assert_eq!(cfg.vendor_dir, original_vendor); } #[test] fn test_reference_resolution_bin_dir() { - let mut cfg = ComposerConfig::defaults(); + let mut cfg = Config::default(); // bin-dir default is "{$vendor-dir}/bin"; vendor-dir default is "vendor" resolve_references(&mut cfg); - assert_eq!(cfg.values["bin-dir"], serde_json::json!("vendor/bin")); + assert_eq!(cfg.bin_dir, "vendor/bin"); } #[test] fn test_reference_resolution_custom_vendor_dir() { - let mut cfg = ComposerConfig::defaults(); + let mut cfg = Config::default(); - // Override vendor-dir before resolving - cfg.values - .insert("vendor-dir".to_string(), serde_json::json!("lib")); + cfg.vendor_dir = "lib".to_string(); resolve_references(&mut cfg); - assert_eq!(cfg.values["bin-dir"], serde_json::json!("lib/bin")); + assert_eq!(cfg.bin_dir, "lib/bin"); } #[test] fn test_reference_resolution_cache_dirs() { - let mut cfg = ComposerConfig::defaults(); + let mut cfg = Config::default(); // Inject a predictable home so the test is environment-independent. - cfg.values.insert( - "cache-dir".to_string(), - serde_json::json!("/home/user/.cache/composer"), - ); + cfg.cache_dir = "/home/user/.cache/composer".to_string(); resolve_references(&mut cfg); - assert_eq!( - cfg.values["cache-files-dir"], - serde_json::json!("/home/user/.cache/composer/files") - ); - assert_eq!( - cfg.values["cache-repo-dir"], - serde_json::json!("/home/user/.cache/composer/repo") - ); - assert_eq!( - cfg.values["cache-vcs-dir"], - serde_json::json!("/home/user/.cache/composer/vcs") - ); + assert_eq!(cfg.cache_files_dir, "/home/user/.cache/composer/files"); + assert_eq!(cfg.cache_repo_dir, "/home/user/.cache/composer/repo"); + assert_eq!(cfg.cache_vcs_dir, "/home/user/.cache/composer/vcs"); } #[test] fn test_reference_resolution_no_change_for_non_string() { - let mut cfg = ComposerConfig::defaults(); - let before = cfg.values["process-timeout"].clone(); + let mut cfg = Config::default(); + let before = cfg.process_timeout; resolve_references(&mut cfg); - // Numeric values should be untouched. - assert_eq!(cfg.values["process-timeout"], before); + assert_eq!(cfg.process_timeout, before); } #[test] fn test_get_existing_key() { - let cfg = ComposerConfig::defaults(); + let cfg = Config::default(); let value = cfg.get("vendor-dir"); assert!(value.is_some()); - assert_eq!(value.unwrap(), &serde_json::json!("vendor")); + assert_eq!(value.unwrap(), serde_json::json!("vendor")); } #[test] fn test_get_nonexistent_key_returns_none() { - let cfg = ComposerConfig::defaults(); + let cfg = Config::default(); assert!(cfg.get("does-not-exist").is_none()); } @@ -1118,17 +1088,14 @@ mod tests { .unwrap(); let overrides = load_config_section(&composer_json).unwrap(); - let mut cfg = ComposerConfig::defaults(); - cfg.merge(&overrides); + let mut cfg = Config::default(); + cfg.merge(&overrides).unwrap(); resolve_references(&mut cfg); - assert_eq!(cfg.values["vendor-dir"], serde_json::json!("custom_vendor")); - assert_eq!(cfg.values["sort-packages"], serde_json::json!(true)); + assert_eq!(cfg.vendor_dir, "custom_vendor"); + assert_eq!(cfg.sort_packages, true); // bin-dir should have resolved against the overridden vendor-dir - assert_eq!( - cfg.values["bin-dir"], - serde_json::json!("custom_vendor/bin") - ); + assert_eq!(cfg.bin_dir, "custom_vendor/bin"); } #[test] diff --git a/crates/mozart/src/commands/dump_autoload.rs b/crates/mozart/src/commands/dump_autoload.rs index c7af429..a86cf21 100644 --- a/crates/mozart/src/commands/dump_autoload.rs +++ b/crates/mozart/src/commands/dump_autoload.rs @@ -78,23 +78,11 @@ pub async fn execute( } } - let optimize = args.optimize - || composer_config - .get("optimize-autoloader") - .and_then(|v| v.as_bool()) - .unwrap_or(false); - let classmap_authoritative = args.classmap_authoritative - || composer_config - .get("classmap-authoritative") - .and_then(|v| v.as_bool()) - .unwrap_or(false); + let optimize = args.optimize || composer_config.optimize_autoloader; + let classmap_authoritative = + args.classmap_authoritative || composer_config.classmap_authoritative; let apcu_prefix = args.apcu_prefix.clone(); - let apcu = apcu_prefix.is_some() - || args.apcu - || composer_config - .get("apcu-autoloader") - .and_then(|v| v.as_bool()) - .unwrap_or(false); + let apcu = apcu_prefix.is_some() || args.apcu || composer_config.apcu_autoloader; let do_optimize = optimize || classmap_authoritative; if args.strict_psr && !do_optimize { diff --git a/crates/mozart/src/commands/exec.rs b/crates/mozart/src/commands/exec.rs index f802721..9d79bee 100644 --- a/crates/mozart/src/commands/exec.rs +++ b/crates/mozart/src/commands/exec.rs @@ -117,12 +117,7 @@ pub async fn execute( fn resolve_bin_dir(working_dir: &Path, composer: &Composer) -> PathBuf { // bin-dir's `{$vendor-dir}` placeholder is already resolved by Composer::load. - let bin_dir = composer - .config() - .get("bin-dir") - .and_then(|v| v.as_str()) - .unwrap_or("vendor/bin"); - working_dir.join(bin_dir) + working_dir.join(&composer.config().bin_dir) } /// Returns a vec of (name, is_local) tuples for all available binaries. diff --git a/crates/mozart/src/commands/run_script.rs b/crates/mozart/src/commands/run_script.rs index 4292809..7e5cbe4 100644 --- a/crates/mozart/src/commands/run_script.rs +++ b/crates/mozart/src/commands/run_script.rs @@ -110,12 +110,14 @@ pub async fn execute( let timeout = match args.timeout { Some(0) => None, Some(secs) => Some(Duration::from_secs(secs)), - None => composer - .config() - .get("process-timeout") - .and_then(|v| v.as_u64()) - .filter(|s| *s != 0) - .map(Duration::from_secs), + None => { + let t = composer.config().process_timeout; + if t != 0 { + Some(Duration::from_secs(t)) + } else { + None + } + } }; let dev_mode = !args.no_dev; @@ -445,12 +447,7 @@ fn wait_with_timeout( fn resolve_bin_dir(working_dir: &Path, composer: &mozart_core::composer::Composer) -> PathBuf { // bin-dir's `{$vendor-dir}` placeholder is already resolved by Composer::load. - let bin_dir = composer - .config() - .get("bin-dir") - .and_then(|v| v.as_str()) - .unwrap_or("vendor/bin"); - working_dir.join(bin_dir) + working_dir.join(&composer.config().bin_dir) } fn is_php_callback(entry: &str) -> bool { |
