diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-01 21:49:37 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-01 21:49:37 +0900 |
| commit | 740eb5b55804134c1977dd39cd8170e2fa615d35 (patch) | |
| tree | 99bb3bf28a60ffac1db8fa6e523eb1828d40007b /crates/mozart/src/commands/install.rs | |
| parent | 2f857cc1ddfde54553829ea5b3a3ac8b59f7f63a (diff) | |
| download | php-mozart-740eb5b55804134c1977dd39cd8170e2fa615d35.tar.gz php-mozart-740eb5b55804134c1977dd39cd8170e2fa615d35.tar.zst php-mozart-740eb5b55804134c1977dd39cd8170e2fa615d35.zip | |
feat(core): reject root composer.json that requires its own name
Mirrors Composer\Package\Loader\RootPackageLoader::load(): if the root
package's "name" appears as a key in its own "require" or "require-dev"
map, fail loudly before reaching the resolver. Without this, Mozart
would silently let the request hit Packagist (which has no entry for
the root's vendor/name) and report a misleading "could not be found"
error.
Wired into install::execute (when a lock file is present) and
update::execute (the no-lock fallback path). Carries the same wording
as Composer's RuntimeException so a future EXPECT-OUTPUT comparison
will match.
Also extends the installer test harness: when a fixture sets
EXPECT-EXCEPTION but no EXPECT-EXIT-CODE, assert that Mozart exits
non-zero. Full exception-class matching remains a follow-up (see
.ken/test_design.md ยง7.2).
Closes the gap exercised by the install-self-from-root installer
fixture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart/src/commands/install.rs')
| -rw-r--r-- | crates/mozart/src/commands/install.rs | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/crates/mozart/src/commands/install.rs b/crates/mozart/src/commands/install.rs index f920f02..b9ff1af 100644 --- a/crates/mozart/src/commands/install.rs +++ b/crates/mozart/src/commands/install.rs @@ -809,6 +809,7 @@ pub async fn execute( } let root_pkg = mozart_core::package::read_from_file(&composer_json_path)?; + root_pkg.validate_root_does_not_self_require()?; let missing = lock.get_missing_requirement_info(&root_pkg, dev_mode); if !missing.is_empty() { for line in &missing { |
