diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/mozart-autoload/src/autoload.rs | 28 | ||||
| -rw-r--r-- | crates/mozart/src/commands/dump_autoload.rs | 86 | ||||
| -rw-r--r-- | crates/mozart/src/commands/install.rs | 28 | ||||
| -rw-r--r-- | crates/mozart/src/commands/reinstall.rs | 28 |
4 files changed, 136 insertions, 34 deletions
diff --git a/crates/mozart-autoload/src/autoload.rs b/crates/mozart-autoload/src/autoload.rs index 27f75ff..8d59db5 100644 --- a/crates/mozart-autoload/src/autoload.rs +++ b/crates/mozart-autoload/src/autoload.rs @@ -23,6 +23,13 @@ pub enum PlatformCheckMode { Disabled, } +/// Result of autoload generation, reporting statistics and warnings. +pub struct GenerateResult { + pub class_count: usize, + pub has_psr_violations: bool, + pub has_ambiguous_classes: bool, +} + /// Configuration for autoload generation. pub struct AutoloadConfig { /// Absolute path to the project root (where composer.json lives). @@ -44,6 +51,8 @@ pub struct AutoloadConfig { pub apcu_prefix: Option<String>, /// When true, return an error on PSR mapping violations detected during classmap scan. pub strict_psr: bool, + /// When true, return exit code 2 if ambiguous class mappings are detected. + pub strict_ambiguous: bool, /// How to handle platform requirement checks. pub platform_check: PlatformCheckMode, /// When true, skip all platform requirement checks. @@ -760,7 +769,7 @@ pub fn determine_suffix(working_dir: &Path, vendor_dir: &Path) -> anyhow::Result /// Generate all autoloader files for the given project. /// /// This is the main entry point called by `install` and `dump-autoload`. -pub fn generate(config: &AutoloadConfig) -> anyhow::Result<()> { +pub fn generate(config: &AutoloadConfig) -> anyhow::Result<GenerateResult> { // 1. Read installed.json let installed = InstalledPackages::read(&config.vendor_dir)?; @@ -838,6 +847,7 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<()> { } // Scan classmap dirs + let mut ambiguous_found = false; if !classmap_dirs.is_empty() { let scanned = scan_classmap_dirs( &classmap_dirs, @@ -846,6 +856,10 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<()> { &excluded, ); for (class, path_expr) in scanned { + if let Some(existing) = data.classmap.get(&class) + && existing != &path_expr { + ambiguous_found = true; + } // Also generate the static expression // We store the dynamic expression in data.classmap; static_data.classmap // will be populated similarly. For now we insert into both. @@ -869,6 +883,10 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<()> { ); psr_violations = violations; for (class, path_expr) in opt_dyn { + if let Some(existing) = data.classmap.get(&class) + && existing != &path_expr { + ambiguous_found = true; + } data.classmap.entry(class).or_insert(path_expr); } for (class, path_expr) in opt_static { @@ -1021,7 +1039,11 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<()> { generate_installed_php(&root_name, &root_type, &installed, config.dev_mode), )?; - Ok(()) + Ok(GenerateResult { + class_count: data.classmap.len(), + has_psr_violations: !psr_violations.is_empty(), + has_ambiguous_classes: ambiguous_found, + }) } // ───────────────────────────────────────────────────────────────────────────── @@ -1443,6 +1465,7 @@ mod tests { apcu: false, apcu_prefix: None, strict_psr: false, + strict_ambiguous: false, platform_check: PlatformCheckMode::Disabled, ignore_platform_reqs: false, }; @@ -1545,6 +1568,7 @@ mod tests { apcu: false, apcu_prefix: None, strict_psr: false, + strict_ambiguous: false, platform_check: PlatformCheckMode::Disabled, ignore_platform_reqs: false, }; diff --git a/crates/mozart/src/commands/dump_autoload.rs b/crates/mozart/src/commands/dump_autoload.rs index 43108ab..0828288 100644 --- a/crates/mozart/src/commands/dump_autoload.rs +++ b/crates/mozart/src/commands/dump_autoload.rs @@ -53,6 +53,11 @@ pub async fn execute( cli: &super::Cli, console: &mozart_core::console::Console, ) -> anyhow::Result<()> { + // A: --dev / --no-dev conflict detection + if args.dev && args.no_dev { + anyhow::bail!("You can not use both --no-dev and --dev as they conflict with each other."); + } + let working_dir = match &cli.working_dir { Some(dir) => PathBuf::from(dir), None => std::env::current_dir()?, @@ -61,6 +66,59 @@ pub async fn execute( let vendor_dir = working_dir.join("vendor"); let dev_mode = !args.no_dev; + // B: Read config-driven defaults from composer.json + let composer_json_path = working_dir.join("composer.json"); + let mut composer_config = super::config::ComposerConfig::defaults(); + if composer_json_path.exists() + && let Ok(content) = std::fs::read_to_string(&composer_json_path) + && let Ok(value) = serde_json::from_str::<serde_json::Value>(&content) + && let Some(cfg_obj) = value.get("config").and_then(|v| v.as_object()) { + let overrides: std::collections::BTreeMap<String, serde_json::Value> = cfg_obj + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); + composer_config.merge(&overrides); + } + + 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 apcu = args.apcu + || args.apcu_prefix.is_some() + || composer_config + .get("apcu-autoloader") + .and_then(|v| v.as_bool()) + .unwrap_or(false); + + // C: Validate --strict-psr and --strict-ambiguous require optimize + let effective_optimize = optimize || classmap_authoritative; + if args.strict_psr && !effective_optimize { + anyhow::bail!( + "--strict-psr mode only works with optimized autoloader, use --optimize or --classmap-authoritative." + ); + } + if args.strict_ambiguous && !effective_optimize { + anyhow::bail!( + "--strict-ambiguous mode only works with optimized autoloader, use --optimize or --classmap-authoritative." + ); + } + + // D: Pre-generation output message + if classmap_authoritative { + console.info("Generating optimized autoload files (authoritative)"); + } else if optimize { + console.info("Generating optimized autoload files"); + } else { + console.info("Generating autoload files"); + } + // Determine suffix: read from existing autoload.php, or from lock file, or generate let suffix = mozart_autoload::autoload::determine_suffix(&working_dir, &vendor_dir)?; @@ -69,21 +127,37 @@ pub async fn execute( return Ok(()); } - mozart_autoload::autoload::generate(&mozart_autoload::autoload::AutoloadConfig { + // E: AutoloadConfig construction using config-merged values + let autoload_config = mozart_autoload::autoload::AutoloadConfig { project_dir: working_dir, vendor_dir, dev_mode, suffix, - classmap_authoritative: args.classmap_authoritative, - optimize: args.optimize, - apcu: args.apcu, + classmap_authoritative, + optimize, + apcu, apcu_prefix: args.apcu_prefix.clone(), strict_psr: args.strict_psr, + strict_ambiguous: args.strict_ambiguous, platform_check: mozart_autoload::autoload::PlatformCheckMode::Full, ignore_platform_reqs: args.ignore_platform_reqs, - })?; + }; + + // F: Handle GenerateResult and post-generation messages + let result = mozart_autoload::autoload::generate(&autoload_config)?; - console.info("Generated autoload files"); + if effective_optimize || classmap_authoritative { + console.info(&format!( + "Generated optimized autoload files containing {} classes", + result.class_count + )); + } else { + console.info("Generated autoload files"); + } + + if args.strict_ambiguous && result.has_ambiguous_classes { + std::process::exit(2); + } Ok(()) } diff --git a/crates/mozart/src/commands/install.rs b/crates/mozart/src/commands/install.rs index 4105a7b..f29c992 100644 --- a/crates/mozart/src/commands/install.rs +++ b/crates/mozart/src/commands/install.rs @@ -476,19 +476,21 @@ pub async fn install_from_lock( let suffix = lock.content_hash.clone(); - mozart_autoload::autoload::generate(&mozart_autoload::autoload::AutoloadConfig { - project_dir: working_dir.to_path_buf(), - vendor_dir: vendor_dir.to_path_buf(), - dev_mode, - suffix, - classmap_authoritative: config.classmap_authoritative, - optimize: config.optimize_autoloader, - apcu: config.apcu_autoloader, - apcu_prefix: config.apcu_autoloader_prefix.clone(), - strict_psr: false, - platform_check: mozart_autoload::autoload::PlatformCheckMode::Full, - ignore_platform_reqs: config.ignore_platform_reqs, - })?; + let _result = + mozart_autoload::autoload::generate(&mozart_autoload::autoload::AutoloadConfig { + project_dir: working_dir.to_path_buf(), + vendor_dir: vendor_dir.to_path_buf(), + dev_mode, + suffix, + classmap_authoritative: config.classmap_authoritative, + optimize: config.optimize_autoloader, + apcu: config.apcu_autoloader, + apcu_prefix: config.apcu_autoloader_prefix.clone(), + strict_psr: false, + strict_ambiguous: false, + platform_check: mozart_autoload::autoload::PlatformCheckMode::Full, + ignore_platform_reqs: config.ignore_platform_reqs, + })?; eprintln!("Generated autoload files"); } diff --git a/crates/mozart/src/commands/reinstall.rs b/crates/mozart/src/commands/reinstall.rs index 313c70c..c6df20d 100644 --- a/crates/mozart/src/commands/reinstall.rs +++ b/crates/mozart/src/commands/reinstall.rs @@ -234,19 +234,21 @@ pub async fn execute( let dev_mode = !args.no_dev && installed.dev; let suffix = lock.content_hash.clone(); - mozart_autoload::autoload::generate(&mozart_autoload::autoload::AutoloadConfig { - project_dir: working_dir.to_path_buf(), - vendor_dir: vendor_dir.to_path_buf(), - dev_mode, - suffix, - classmap_authoritative: args.classmap_authoritative, - optimize: args.optimize_autoloader, - apcu: args.apcu_autoloader, - apcu_prefix: args.apcu_autoloader_prefix.clone(), - strict_psr: false, - platform_check: mozart_autoload::autoload::PlatformCheckMode::Full, - ignore_platform_reqs: args.ignore_platform_reqs, - })?; + let _result = + mozart_autoload::autoload::generate(&mozart_autoload::autoload::AutoloadConfig { + project_dir: working_dir.to_path_buf(), + vendor_dir: vendor_dir.to_path_buf(), + dev_mode, + suffix, + classmap_authoritative: args.classmap_authoritative, + optimize: args.optimize_autoloader, + apcu: args.apcu_autoloader, + apcu_prefix: args.apcu_autoloader_prefix.clone(), + strict_psr: false, + strict_ambiguous: false, + platform_check: mozart_autoload::autoload::PlatformCheckMode::Full, + ignore_platform_reqs: args.ignore_platform_reqs, + })?; console.info("Generated autoload files"); } |
