| Age | Commit message (Collapse) | Author |
|
|
|
Three Composer-compat bugs surfaced by the github_issues_9290 fixture,
fixed together since they form one resolution path:
- RawPackageData.repositories now accepts a JSON object keyed by name,
matching RepositoryFactory::createRepos which iterates either int-
or string-keyed arrays via PHP foreach.
- Version::parse fills every unspecified position of a `.x-dev` branch
with 9999999, mirroring VersionParser::normalizeBranch. Previously
`2.x-dev` parsed to 2.0.9999999.9999999-dev and failed to satisfy
^2.8.
- is_platform_package limits the `php-` family to the closed set
{64bit,ipv6,zts,debug} per PLATFORM_PACKAGE_REGEX. Vendor packages
like `php-http/client-common` are no longer misclassified.
Unblocks github_issues_7051, _8903, _9012, _9290.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Mozart silently ignored the `security-advisories` block on inline
`type: package` repositories and the `config.audit.block-insecure`
audit flag, so a `composer update` succeeded with packages a Composer
run would have refused to load. Mirror Composer's
`SecurityAdvisoryPoolFilter` for the slice that feeds the pool:
- Plumb a `security-advisories` field through `RawRepository` and a
`block_insecure` flag through `ResolveRequest`, lifted off
`composer.json`'s `config.audit.block-insecure`.
- Collect every advisory's `affectedVersions` constraint at resolve
time. When `block_insecure` is set and an inline package's
normalized version satisfies the constraint, drop it from the pool
before solving — root requires with no unaffected candidate then
fail with the standard "could not be resolved" error.
|
|
Composer's FilterRepository wraps a repository with three knobs:
`only` / `exclude` to drop packages by name, and `canonical: false` to
relax the repo's authoritative claim on its package names so
lower-priority repos can still answer. Mozart was ignoring all three,
so first-listed inline / composer-repo entries always shadowed later
repos and `only` / `exclude` lists were silently no-ops.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's RootPackageRepository puts a clone of the root package into
the pool as a fixed entry — its `require` / `require-dev` cleared, but
its name, version, provides, and replaces preserved. That way a
transitive `require` pointing back at the root resolves through the
pool the same way any other reference would, and legal circular
dependencies (root requires A, A requires root) work.
Mozart had no such seed: the rule generator only knew about the root
through the explicit root-require / root-provide / root-replace tables,
so a transitive consumer requiring the root by name failed with no
provider.
Plumb root_version through ResolveRequest (RawPackageData gains a
matching `Option<String>` field), build a fixed PoolPackageInput for
the root with provides/replaces lifted from request.root_provide /
root_replace, and skip the root by name when collecting the resolver's
output so it doesn't leak into the lock file. Falls back to
`1.0.0+no-version-set` (Composer's RootPackage::DEFAULT_PRETTY_VERSION)
when the root composer.json omits `version`.
Unblocks circular_dependency2, conflict_against_replaced_package_problem,
and provider_conflicts installer fixtures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
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.
|
|
- Extend self.version replacement to conflict, provide, and replace
link types (previously only require and require-dev)
- Only rewrite self.version when VCS metadata is actually removed,
matching Composer's behavior
- Read optimize-autoloader, classmap-authoritative, and apcu-autoloader
from the project's composer.json config section instead of hardcoding
false
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Extract modules from the single `mozart` crate into 5 focused library
crates to improve compilation parallelism and architectural clarity:
- mozart-constraint: version constraint parser (independent)
- mozart-core: base types, console, validation, platform utilities
- mozart-archiver: archive creation (tar, zip, bzip2)
- mozart-registry: Packagist API, cache, resolver, downloader, lockfile
- mozart-autoload: autoloader generation and PHP scanner
Refactor Console::from_cli and build_cache_config to accept primitive
args instead of &Cli to break circular dependencies. Introduce
[workspace.dependencies] for centralized version management. Remove 9
unused direct dependencies from the CLI crate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|