From 99a33b951502d3e80eb70f53551413b9dc0f4d6c Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 2 May 2026 17:30:27 +0900 Subject: refactor(commands): split install/update into CLI execute + library run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Carve commands::install::execute and commands::update::execute into thin CLI-arg-driven wrappers + run() entry points that take (working_dir, args, console, repositories, executor) directly. The wrappers build a production RepositorySet (Packagist) + FilesystemExecutor from cli, then dispatch to run; in-process tests will call run directly with an empty RepositorySet (Composer's `'packagist' => false` test config) and a tracing InstallerExecutor. The install -> update fallback (no composer.lock present) now goes through update::run, forwarding the caller's repositories + executor so test mocks survive the edge. Also drop the now-dead InstallConfig::no_cache field — install_from_lock stopped consuming the cache when FilesystemExecutor was extracted in the earlier DI plumbing pass, so the field has no effect. All 136 enabled installer fixtures + 114 mozart-registry tests + 541 mozart lib tests still green; clippy clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/mozart/src/commands/create_project.rs | 1 - crates/mozart/src/commands/install.rs | 42 +++++++++++++++++++------- crates/mozart/src/commands/remove.rs | 2 -- crates/mozart/src/commands/require.rs | 1 - crates/mozart/src/commands/update.rs | 45 ++++++++++++++++++---------- 5 files changed, 60 insertions(+), 31 deletions(-) (limited to 'crates/mozart/src') diff --git a/crates/mozart/src/commands/create_project.rs b/crates/mozart/src/commands/create_project.rs index 01b337e..c2c4f92 100644 --- a/crates/mozart/src/commands/create_project.rs +++ b/crates/mozart/src/commands/create_project.rs @@ -522,7 +522,6 @@ pub async fn execute( apcu_autoloader_prefix: None, download_only: false, prefer_source: args.prefer_source, - no_cache: cli.no_cache, }, console, &mut executor, diff --git a/crates/mozart/src/commands/install.rs b/crates/mozart/src/commands/install.rs index 5053783..c8b0431 100644 --- a/crates/mozart/src/commands/install.rs +++ b/crates/mozart/src/commands/install.rs @@ -121,8 +121,6 @@ pub struct InstallConfig { pub download_only: bool, /// Prefer installing from VCS source rather than dist archives. pub prefer_source: bool, - /// Disable the files cache entirely. - pub no_cache: bool, } impl Default for InstallConfig { @@ -140,7 +138,6 @@ impl Default for InstallConfig { apcu_autoloader_prefix: None, download_only: false, prefer_source: false, - no_cache: false, } } } @@ -606,14 +603,37 @@ pub async fn install_from_lock( Ok(()) } +/// CLI entry point. Builds production [`mozart_registry::repository::RepositorySet`] +/// (Packagist) and [`FilesystemExecutor`] from `cli`, then dispatches to [`run`]. pub async fn execute( args: &InstallArgs, cli: &super::Cli, console: &mozart_core::console::Console, ) -> anyhow::Result<()> { - // Step 1: Resolve the working directory + let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache); + let repositories = std::sync::Arc::new( + mozart_registry::repository::RepositorySet::with_packagist( + mozart_registry::cache::Cache::repo(&cache_config), + ), + ); + let mut executor = FilesystemExecutor::new(mozart_registry::cache::Cache::files(&cache_config)); let working_dir = resolve_working_dir(cli); + run(&working_dir, args, console, repositories, &mut executor).await +} +/// Library entry point — pure logic, no `Cli` access. +/// +/// In-process tests construct an empty `RepositorySet` (Composer's +/// `'packagist' => false` test config) and a tracing `InstallerExecutor`, +/// then call this function directly to exercise the install flow without +/// spawning the binary. +pub async fn run( + working_dir: &Path, + args: &InstallArgs, + console: &mozart_core::console::Console, + repositories: std::sync::Arc, + executor: &mut dyn InstallerExecutor, +) -> anyhow::Result<()> { // Step 2: Validate arguments if args.prefer_install.is_some() && (args.prefer_source || args.prefer_dist) { return Err(mozart_core::exit_code::bail( @@ -691,7 +711,10 @@ pub async fn execute( root_reqs: false, bump_after_update: None, }; - return super::update::execute(&update_args, cli, console).await; + // Forward the caller's repositories + executor so in-process tests + // see their mocks honored across the install→update fallback edge. + return super::update::run(working_dir, &update_args, console, repositories, executor) + .await; } let lock = lockfile::LockFile::read_from_file(&lock_path)?; @@ -758,12 +781,10 @@ pub async fn execute( let vendor_dir = working_dir.join("vendor"); // Step 7: Delegate to shared install_from_lock() - let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache); - let files_cache = mozart_registry::cache::Cache::files(&cache_config); - let mut executor = FilesystemExecutor::new(files_cache); + let _ = repositories; // unused — install_from_lock has no resolver phase install_from_lock( &lock, - &working_dir, + working_dir, &vendor_dir, &InstallConfig { dev_mode, @@ -778,10 +799,9 @@ pub async fn execute( apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(), download_only: args.download_only, prefer_source, - no_cache: cli.no_cache, }, console, - &mut executor, + executor, ) .await } diff --git a/crates/mozart/src/commands/remove.rs b/crates/mozart/src/commands/remove.rs index 8794a10..e499af0 100644 --- a/crates/mozart/src/commands/remove.rs +++ b/crates/mozart/src/commands/remove.rs @@ -452,7 +452,6 @@ pub async fn execute( apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(), download_only: false, prefer_source: false, - no_cache: cli.no_cache, }, console, &mut executor, @@ -606,7 +605,6 @@ async fn remove_unused( apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(), download_only: false, prefer_source: false, - no_cache, }, console, &mut executor, diff --git a/crates/mozart/src/commands/require.rs b/crates/mozart/src/commands/require.rs index ead632f..50aa29f 100644 --- a/crates/mozart/src/commands/require.rs +++ b/crates/mozart/src/commands/require.rs @@ -872,7 +872,6 @@ pub async fn execute( apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(), download_only: false, prefer_source: args.prefer_source, - no_cache: cli.no_cache, }, console, &mut executor, diff --git a/crates/mozart/src/commands/update.rs b/crates/mozart/src/commands/update.rs index fd533fd..8a0bef7 100644 --- a/crates/mozart/src/commands/update.rs +++ b/crates/mozart/src/commands/update.rs @@ -720,17 +720,39 @@ fn major_minor(version: &str) -> (u64, u64) { // Main execute function // ───────────────────────────────────────────────────────────────────────────── +/// CLI entry point. Builds production [`RepositorySet`] (Packagist) and +/// [`FilesystemExecutor`] from `cli`, then dispatches to [`run`]. pub async fn execute( args: &UpdateArgs, cli: &super::Cli, console: &mozart_core::console::Console, ) -> anyhow::Result<()> { let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache); - let repo_cache = mozart_registry::cache::Cache::repo(&cache_config); - - // Step 1: Resolve the working directory + let repositories = std::sync::Arc::new( + mozart_registry::repository::RepositorySet::with_packagist( + mozart_registry::cache::Cache::repo(&cache_config), + ), + ); + let mut executor = mozart_registry::installer_executor::FilesystemExecutor::new( + mozart_registry::cache::Cache::files(&cache_config), + ); let working_dir = super::install::resolve_working_dir(cli); + run(&working_dir, args, console, repositories, &mut executor).await +} +/// Library entry point — pure logic, no CLI / Cli access. +/// +/// In-process tests construct a `RepositorySet` without `PackagistRepository` +/// (Composer's `'packagist' => false` test config) and a tracing +/// `InstallerExecutor`, then call this function directly to exercise the +/// update flow without spawning the binary. +pub async fn run( + working_dir: &std::path::Path, + args: &UpdateArgs, + console: &mozart_core::console::Console, + repositories: std::sync::Arc, + executor: &mut dyn mozart_registry::installer_executor::InstallerExecutor, +) -> anyhow::Result<()> { // Step 2: Handle deprecated flags if args.dev { console.info(&console_format!( @@ -863,9 +885,7 @@ pub async fn execute( platform: PlatformConfig::new(), ignore_platform_reqs: args.ignore_platform_reqs, ignore_platform_req_list: args.ignore_platform_req.clone(), - repositories: std::sync::Arc::new( - mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()), - ), + repositories: repositories.clone(), temporary_constraints, raw_repositories: composer_json.repositories.clone(), }; @@ -1023,9 +1043,7 @@ pub async fn execute( composer_json_content: composer_json_content.clone(), composer_json: composer_json.clone(), include_dev: dev_mode, - repositories: std::sync::Arc::new( - mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()), - ), + repositories: repositories.clone(), }) .await?; @@ -1222,13 +1240,9 @@ pub async fn execute( .map(|s| s.eq_ignore_ascii_case("source")) .unwrap_or(false); - let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache); - let files_cache = mozart_registry::cache::Cache::files(&cache_config); - let mut executor = - mozart_registry::installer_executor::FilesystemExecutor::new(files_cache); super::install::install_from_lock( &new_lock, - &working_dir, + working_dir, &vendor_dir, &super::install::InstallConfig { dev_mode, @@ -1243,10 +1257,9 @@ pub async fn execute( apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(), download_only: false, prefer_source, - no_cache: cli.no_cache, }, console, - &mut executor, + executor, ) .await?; } -- cgit v1.3.1