aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart/src/commands/exec.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-05 15:12:57 +0900
committernsfisis <nsfisis@gmail.com>2026-05-05 15:12:57 +0900
commit2ad57b7efb685040b24d93aab5b81ddfbd0ebefb (patch)
tree9ee877ed2abc055cc91f2b7120a6122917fa6998 /crates/mozart/src/commands/exec.rs
parentd4df60e70a4581aba6308f803ec7f9473d2671d8 (diff)
downloadphp-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.rs42
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");