| Age | Commit message (Collapse) | Author |
|
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>
|
|
Composer's InstalledFilesystemRepository::write() dumps the full
package via ArrayDumper, so flags like `abandoned` and
`default-branch` (which Mozart parks in LockedPackage::extra_fields)
should round-trip from composer.lock into vendor/composer/installed.json.
locked_to_installed_entry was zeroing the destination's extra_fields,
silently stripping these flags every time installed.json got
rewritten.
Carry the extra_fields map across verbatim. The
install-forces-reinstall-if-abandon-changes installer fixture is
already exit-0 green at the harness layer; this aligns the actual
end-state with Composer's EXPECT-INSTALLED so a future EXPECT-INSTALLED
comparison won't re-flag this gap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's `Locker` treats `content-hash` as optional with BC support
(see Locker::isLocked() / isFresh() lines 142-147): if a lock predates
the field — or, in the case of installer fixtures, deliberately omits
it — Composer simply considers the lock "not fresh" against any
composer.json. Mozart's deserializer was strict, rejecting the lock
with `missing field content-hash` before any of the install-time
checks could run.
Default the field to empty via `#[serde(default)]`. With an empty
hash, `is_fresh()` returns false (matching Composer's BC behavior, so
the freshness warning still fires) and downstream code that overwrites
`content_hash` continues to work unchanged.
Closes the parsing barrier exercised by the
updating-dev-from-lock-removes-old-deps installer fixture. Note:
matching Composer's exact operations trace ("Upgrading a/devpackage
…", alias-removal lines) requires a `compute_operations` that compares
package source references — out of scope for this change and tracked
in .ken/test_design.md §7.2 under "EXPECT (operations trace) 比較".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
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>
|
|
Mirrors Composer's platform-requirements check during
Installer::doInstall(): merge platform requires from the lock's
platform/platform-dev fields with the root composer.json
require/require-dev (composer.json wins on duplicate keys), then
verify them against the detected runtime platform. If any are missing
or unsatisfied, print the standard "Your lock file does not contain a
compatible set of packages" message followed by Problem 1..N entries
and exit with DEPENDENCY_RESOLUTION_FAILED (2) instead of silently
proceeding to "Nothing to install" with exit 0. Closes the gap
exercised by the outdated-lock-file-with-new-platform-reqs-fails
installer fixture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Mirrors Composer's Installer::doInstall() check: before installing from
an existing composer.lock, walk every root require (and require-dev in
dev mode) and confirm the lock contains a satisfying package. If any
are missing or fail the constraint, print the standard bullet-list
diagnostic and exit with LOCK_FILE_INVALID (4) instead of blindly
attempting to install and failing later with a misleading "no dist or
source information" error. Closes the gap exercised by the
outdated-lock-file-fails-install installer fixture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's FilesystemRepository::initialize branches on
isset($data['packages']) — object form is v2, bare array is v1 —
and treats dev-package-names/dev as optional. Mirror that in
InstalledPackages::read so Mozart consumes shared .test fixtures
(which use v1) without harness preprocessing, and so installs over
v1-era vendor directories keep working. Drop the v1→v2 wrapper
that was added to mozart-test-harness for the same reason.
Removes #[ignore] from update_to_empty_from_locked (2/187 green).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's RootPackageLoader assigns the root name "__root__" when
composer.json omits the "name" field. Mozart was failing deserialization
in that case, blocking any installer fixture with a nameless root
manifest. Apply the same serde default and unignore
update-to-empty-from-blank as the first green entry on the .test
scoreboard.
|
|
Add per-fixture #[test] entries (187 total) via a small declarative
macro that reads files directly from the composer submodule. For now
each test only asserts the file parses; execution and EXPECT-* checks
will be layered on as the harness gains comparison helpers.
|
|
The install command succeeds with a warning when no lock file exists,
rather than failing with a suggestion to run update.
|
|
Add 23 integration tests using assert_cmd and predicates covering
about, validate, show, licenses, install, config, init, and
dump-autoload commands with shared test helpers and fixture projects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|