diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-05 15:12:57 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-05 15:12:57 +0900 |
| commit | 2ad57b7efb685040b24d93aab5b81ddfbd0ebefb (patch) | |
| tree | 9ee877ed2abc055cc91f2b7120a6122917fa6998 /crates/mozart/src/commands/exec.rs | |
| parent | d4df60e70a4581aba6308f803ec7f9473d2671d8 (diff) | |
| download | php-mozart-2ad57b7efb685040b24d93aab5b81ddfbd0ebefb.tar.gz php-mozart-2ad57b7efb685040b24d93aab5b81ddfbd0ebefb.tar.zst php-mozart-2ad57b7efb685040b24d93aab5b81ddfbd0ebefb.zip | |
feat(core): add Composer struct mirroring requireComposer/tryComposer
Introduce mozart_core::composer::Composer with require()/try_load()
constructors and a config() accessor, modelled on PHP Composer's
BaseCommand::requireComposer / tryComposer. ComposerConfig and
composer_home move into mozart-core so Composer::load can resolve
placeholders consistently.
Migrate dump-autoload, archive, exec and run-script away from ad-hoc
composer.json reads. exec and run-script now fail when composer.json
is missing instead of silently falling back to "vendor/bin",
matching the upstream requireComposer contract.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart/src/commands/exec.rs')
| -rw-r--r-- | crates/mozart/src/commands/exec.rs | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/crates/mozart/src/commands/exec.rs b/crates/mozart/src/commands/exec.rs index eaaf465..5f1f0bc 100644 --- a/crates/mozart/src/commands/exec.rs +++ b/crates/mozart/src/commands/exec.rs @@ -1,4 +1,5 @@ use clap::Args; +use mozart_core::composer::Composer; use mozart_core::console_format; use std::path::{Path, PathBuf}; @@ -29,7 +30,9 @@ pub async fn execute( None => std::env::current_dir()?, }; - let bin_dir = resolve_bin_dir(&working_dir); + // ExecCommand uses requireComposer in Composer; composer.json must exist. + let composer = Composer::require(&working_dir)?; + let bin_dir = resolve_bin_dir(&working_dir, &composer); if args.list || args.binary.is_none() { let binaries = get_binaries(&working_dir, &bin_dir); @@ -119,20 +122,14 @@ pub async fn execute( // ─── Helpers ────────────────────────────────────────────────────────────────── -fn resolve_bin_dir(working_dir: &Path) -> PathBuf { - let composer_json_path = working_dir.join("composer.json"); - if let Ok(content) = std::fs::read_to_string(&composer_json_path) - && let Ok(parsed) = serde_json::from_str::<serde_json::Value>(&content) - { - let vendor_dir = parsed["config"]["vendor-dir"].as_str().unwrap_or("vendor"); - let bin_dir = parsed["config"]["bin-dir"].as_str().unwrap_or_default(); - if !bin_dir.is_empty() { - let resolved = bin_dir.replace("{$vendor-dir}", vendor_dir); - return working_dir.join(resolved); - } - return working_dir.join(vendor_dir).join("bin"); - } - working_dir.join("vendor/bin") +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) } /// Returns a vec of (name, is_local) tuples for all available binaries. @@ -208,7 +205,8 @@ mod tests { let composer_json = dir.path().join("composer.json"); fs::write(&composer_json, r#"{"name": "test/pkg", "require": {}}"#).unwrap(); - let result = resolve_bin_dir(dir.path()); + let composer = Composer::require(dir.path()).unwrap(); + let result = resolve_bin_dir(dir.path(), &composer); assert_eq!(result, dir.path().join("vendor/bin")); } @@ -222,7 +220,8 @@ mod tests { ) .unwrap(); - let result = resolve_bin_dir(dir.path()); + let composer = Composer::require(dir.path()).unwrap(); + let result = resolve_bin_dir(dir.path(), &composer); assert_eq!(result, dir.path().join("libs/bin")); } @@ -236,7 +235,8 @@ mod tests { ) .unwrap(); - let result = resolve_bin_dir(dir.path()); + let composer = Composer::require(dir.path()).unwrap(); + let result = resolve_bin_dir(dir.path(), &composer); assert_eq!(result, dir.path().join("scripts")); } @@ -250,7 +250,8 @@ mod tests { ) .unwrap(); - let result = resolve_bin_dir(dir.path()); + let composer = Composer::require(dir.path()).unwrap(); + let result = resolve_bin_dir(dir.path(), &composer); assert_eq!(result, dir.path().join("packages/commands")); } @@ -366,7 +367,8 @@ mod tests { ) .unwrap(); - let bin_dir = resolve_bin_dir(dir.path()); + let composer = Composer::require(dir.path()).unwrap(); + let bin_dir = resolve_bin_dir(dir.path(), &composer); // No binaries exist — looking up a name should find nothing let candidate = bin_dir.join("nonexistent-binary"); |
