diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-01 22:26:16 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-01 22:26:16 +0900 |
| commit | 4d587407cc9471dc8bfc0544eac0f8c7041fba0d (patch) | |
| tree | 7b45b8e6e3dc5b1b3325b7cc6783375273a56784 /crates/mozart/src/commands/install.rs | |
| parent | 8a87adf120d5057b06d0474b293fab079e1ce967 (diff) | |
| download | php-mozart-4d587407cc9471dc8bfc0544eac0f8c7041fba0d.tar.gz php-mozart-4d587407cc9471dc8bfc0544eac0f8c7041fba0d.tar.zst php-mozart-4d587407cc9471dc8bfc0544eac0f8c7041fba0d.zip | |
feat(registry): support inline 'type: package' repositories
Composer's PackageRepository lets composer.json embed full package
metadata under repositories[].package, mirroring the on-disk
Packagist response shape. The vast majority of installer fixtures
under composer/tests/Composer/Test/Fixtures/installer (179 of 189)
rely on this — they declare every package they need inline rather
than hitting the network.
Three pieces wire this into Mozart:
1. mozart-core::package::RawRepository: relax `url` to Option<String>
(Composer enforces presence per repo type, not at JSON parse) and
add `package: Option<Value>` to receive the inline definition,
which can be a single object or an array.
2. mozart-registry::inline_package: a new module that walks
`&[RawRepository]`, picks out type=package entries, and reshapes
each `package` payload into a PackagistVersion (auto-computing
version_normalized when omitted, matching Packagist's output).
3. resolver::resolve and lockfile::generate_lock_file: feed inline
packages into the SAT pool builder and short-circuit the Packagist
fetch when generating the lock entry for a resolved inline package.
The package-name set is shared with the existing VCS-skip logic so
the seed and transitive loops don't double-fetch.
One additional install-time change: in install_from_lock, packages
that have neither dist nor source are now skipped silently instead
of bailing with "no dist or source information". This mirrors
Composer's MetapackageInstaller (no installer for type=metapackage)
and is also what Composer's own AllFunctionalTest exercises via
InstallationManagerMock — most inline-package fixtures define
synthetic packages with no download metadata, expecting the install
operation to be recorded but not actually run.
Net effect: installer fixture scoreboard jumps from 7/187 to 103/187.
The 84 fixtures still ignored hit issues unrelated to inline-package
plumbing — aliases, replace/provide chains, dev-reference handling,
allow-list updates, etc. — and are tracked separately.
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 | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/crates/mozart/src/commands/install.rs b/crates/mozart/src/commands/install.rs index a10dd69..1cc4e6f 100644 --- a/crates/mozart/src/commands/install.rs +++ b/crates/mozart/src/commands/install.rs @@ -608,18 +608,22 @@ pub async fn install_from_lock( continue; } + // A package with neither dist nor source has no install action. + // This covers Composer's `type: metapackage` (modeled explicitly + // as "no installer") and inline `type: package` definitions used + // in test fixtures that intentionally omit download metadata. + // Mozart records the operation and the installed.json entry but + // performs no filesystem work, mirroring Composer's + // MetapackageInstaller. + if pkg.dist.is_none() && pkg.source.is_none() { + continue; + } + let dist = pkg.dist.as_ref().ok_or_else(|| { - if pkg.source.is_some() { - anyhow::anyhow!( - "Package {} has no dist information. Use --prefer-source to install from VCS.", - pkg.name, - ) - } else { - anyhow::anyhow!( - "Package {} has no dist or source information", - pkg.name, - ) - } + anyhow::anyhow!( + "Package {} has no dist information. Use --prefer-source to install from VCS.", + pkg.name, + ) })?; let mut progress = make_progress(!config.no_progress, &pkg.name, &pkg.version); |
