| Age | Commit message (Collapse) | Author |
|
Composer's ArrayLoader and AliasPackage rewrite "self.version" to the
declaring package's own version when building Link objects, so a
package's replace/provide/conflict/require constraints carry a concrete
"= <version>" rather than the literal string. Mozart was passing
"self.version" through verbatim, which then failed to parse in
Pool::matches_package and caused replace_alias.test to fail to find a
provider for c/c 1.* via a/a's branch alias.
Push the substitution into make_pool_links, threading the source
package's normalized version through the call sites in resolver.rs
(packagist/inline/composer-repo) and vcs_bridge.rs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Port Composer's RuleSetGenerator::createRequireRule self-fulfilling
branch: when the root composer.json's `provide` or `replace` covers a
name it also requires (with intersecting constraints), skip emitting an
install-one-of rule for that root require. Composer relies on the root
package being a fixed entry in the pool so whatProvides() includes it;
Mozart does not yet add the root to the pool, so the same decision is
made via explicit `root_provide` / `root_replace` tables threaded
through ResolveRequest. Without this, an inline repo package whose name
matches the root's provide was being force-installed.
Fixes installer fixtures `provider_satisfies_its_own_requirement` and
`replacer_satisfies_its_own_requirement`.
|
|
Adds the missing pieces for installer fixtures that pin a dev package
via `dev-foo#hex` or rely on Composer's `default-branch: true` synthetic
`9999999-dev` alias.
Mirrors Composer at four layers:
1. `mozart_semver::parse_single` strips `dev-...#hex` / `....x-dev#hex`
suffixes from constraints (Composer's `parseConstraint` regex).
2. `PackagistVersion` carries `default_branch`. When set on a `dev-`
package with no numeric prefix, `packagist_to_pool_inputs` emits
the synthetic `9999999-dev` alias — but skips it when an explicit
`extra.branch-alias` already covers the version (matches
`ArrayLoader::getBranchAlias`).
3. `RuleSetGenerator::generate` picks up `addRulesForRootAliases`:
any pool alias whose target was added gets its own alias↔target
rules so the SAT solver pulls them in together.
4. `lockfile::generate_lock_file` extracts root `#hex` overrides from
`require`/`require-dev` and rewrites source/dist references (and
github/gitlab/bitbucket archive URLs) on the matched package, the
`setSourceDistReferences` ladder Composer runs in `PoolBuilder`.
Resolver also infers `Stability::Dev` from a `dev-foo` style
single-atom constraint when no explicit `@flag` is given, mirroring
the second loop of `RootPackageLoader::extractStabilityFlags` so the
package isn't filtered out under default `stable` minimum-stability.
Newly green: install_branch_alias_composer_repo, install_reference,
conflict_with_alias_prevents_update_if_not_required,
unbounded_conflict_matches_default_branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Plumb Composer's `extra.branch-alias` mechanism end-to-end so a dev
branch (e.g. `dev-foobar`) can be installed alongside its numeric alias
(e.g. `3.2.x-dev`) and resolve constraints written against the alias
target.
Concretely:
- `mozart-semver`: stop treating pure-numeric `-dev` as a wildcard
branch — `3.2.9999999.9999999-dev` (the form `normalizeBranch` emits)
now parses as a classical version with `is_dev_branch=false`, so
constraints like `3.2.*` match it.
- `mozart-registry/composer_repo`: load `type: composer` repositories
from `file://` URLs (legacy embedded `packages.json`).
- `mozart-registry/resolver`: emit pool entries in pairs for dev
branches with `extra.branch-alias`, link them via `is_alias_of`, and
apply `@dev`/`@beta` etc. stability suffix flags from root requires.
- `mozart-sat-resolver`: alias rules (`PackageAlias` /
`PackageInverseAlias`) so alias and target install together; alias
packages skipped from same-name conflict indexing.
- `mozart-sat-resolver/policy`: `DefaultPolicy` now honors
`prefer_stable` via Composer's stability-tier comparison.
- `mozart-registry/lockfile`: split resolved set into real packages vs.
alias entries; populate the `aliases[]` block.
- `mozart-registry/installer_executor`: new `MarkAliasInstalled`
operation; `format_full_pretty_version` mirroring
`BasePackage::getFullPrettyVersion` (appends source ref[0..7] for
dev/git packages).
- Test harness rewrites fixture-relative `file://` URLs to absolute
paths.
Newly green fixtures: `install_branch_alias_composer_repo`,
`alias_solver_problems`, `alias_solver_problems2`,
`conflict_with_all_dependencies_option_dont_recommend_to_use_it`,
`unbounded_conflict_does_not_match_default_branch_with_branch_alias`,
`unbounded_conflict_does_not_match_default_branch_with_numeric_branch`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Three coupled changes that bring `compute_operations` + the in-process
trace recorder into byte-parity with Composer's `Transaction::__toString`
output:
- `TraceRecorderExecutor`: emit "Removing X (V)" instead of "Uninstalling
X (V)" — Composer's `UninstallOperation::__toString` uses "Removing".
- `install_from_lock`: run removals before installs/updates to mirror
`Transaction::moveUninstallsToFront`. Both dry-run and real-execution
branches now emit the same prefix order.
- `topological_sort`: replace recursive DFS with the stack-based DFS that
Composer uses in `Transaction::calculateOperations`. Roots are seeded
reverse-alphabetically (matching `setResultPackageMaps`'s uasort with
`strcmp(b, a)`), and `getProvidersInResult` is mirrored by treating a
package's `provide`/`replace` keys as additional name targets when
resolving a `require` link.
To make the third change work end-to-end, `LockedPackage` gains typed
`provide` and `replace` fields (Composer's lock preserves them; Mozart
was silently dropping them). `packagist_version_to_locked_package` now
copies them through.
Unignores 13 installer fixtures (10 newly green from the fix, 3 that
were already green-but-still-flagged): conflict_downgrade_nested,
install_from_lock_removes_package, install_security_advisory_matching_dependency,
load_replaced_package_if_replacer_dropped, partial_update_keeps_older_dep_*
(×2), partial_update_security_advisory_matching_locked_dep,
provider_packages_can_be_installed_together_with_provided_if_both_installable,
remove_deletes_unused_deps, replace_priorities,
update_allow_list_require_new_replace,
update_allow_list_with_dependencies_require_new_replace,
update_requiring_decision_reverts_and_learning_positive_literals.
Installer scoreboard: 75/187 → 88/187.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Replaces the spawn-based runner in tests/installer.rs with the
in-process harness from Step E. Every fixture now goes through
mozart::commands::{install,update}::run with an empty RepositorySet
(Composer's `'packagist' => false` test config) and a
TraceRecorderExecutor (Composer's InstallationManagerMock), and the
EXPECT section is now asserted against the recorder's trace -
load-bearing for behavior parity, not just exit-code.
The original CI failure (suggest_replaced) is now legitimately tested:
the empty RepositorySet makes b/b unreachable just like Composer's
test config, the inline package repo's eager preload finds c/c which
replaces b/b, and the topological install order in compute_operations
produces the c/c -> a/a trace the fixture pins.
Strict trace assertion surfaced 60 Mozart-vs-Composer divergences that
the exit-code-only spawn runner had been silently ignoring. Each is
marked `installer_fixture\!(name, ignore)` for now; the categories
break down roughly as:
- alias handling (alias_in_lock2, install_aliased_alias, update_alias*)
- replace / provider trace shape (replace_priorities,
provider_satisfies_its_own_requirement, replacer_*)
- update direction strings (update_changes_url, update_reference,
update_dev_*)
- partial-update + lock interactions (partial_update_*)
- allow-list with replace/dependency interactions
(update_allow_list_with_dependencies_require_new*)
These each become individual follow-up Mozart bugs rather than mass
silent-pass.
Also marks prefer_lowest_branches as ignore: it's a real flake driven
by HashSet iteration order in the resolver, where two equivalent
candidates can be picked in either order. That's a separate
determinism bug worth its own fix.
The proxy-hack env-vars in mozart-test-harness::runner are removed -
no test currently spawns the binary, and the in-process harness
expresses Packagist disablement directly via RepositorySet::empty
rather than relying on TCP failure to suppress network calls.
Headline numbers: 75 passed (in-process, exit-code + EXPECT trace) +
112 ignored, vs prior 136 passed (spawn, exit-code only) + 51 ignored.
The drop in passing count reflects the stricter assertion bar, not
new regressions.
Also removes tests/installer_in_process.rs - its single proof-of-
concept fixture (suggest_replaced) is now part of the unified
installer.rs harness.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Adds TraceRecorderExecutor (Composer's InstallationManagerMock analog),
which records every install/update/uninstall as a string matching
Composer's *Operation::__toString output (after strip_tags) - the
load-bearing assertion target for in-process fixture tests.
Two changes were needed to make the recorder useful:
- InstallerExecutor::uninstall_package gains a version parameter, and
install_from_lock now looks up both the uninstall and the
Update-from-version from installed.json. Previously the Update path
passed the new version as a placeholder; the recorder needs the real
old version to emit `Upgrading pkg (old => new)`.
- compute_operations now topologically sorts the lock contents (deps
before dependents) before computing actions, mirroring Composer's
Transaction::calculateOperations. Without this, packages would
install in alphabetical order and the trace would diverge from
Composer's expectation.
Also adds crates/mozart/tests/installer_in_process.rs with the
in-process harness scaffold: parses the same .test fixtures, builds a
tempdir, calls commands::install::run / update::run with an empty
RepositorySet (no Packagist) and a TraceRecorderExecutor, then asserts
exit code + EXPECT trace. One fixture wired up: suggest_replaced - the
original CI failure that motivated this whole DI refactor. It now
passes on the in-process path because the empty RepositorySet makes
b/b unreachable just like Composer's `'packagist' => false` test
config, and the resolver finds c/c (which replaces b/b) via the inline
package repo's eager preload.
Step F will migrate every fixture currently in installer.rs to the new
harness; remaining divergences (alias handling, output ordering,
replace trace shape, etc.) will surface as individual follow-ups.
All 136 existing spawn-based fixtures + 114 mozart-registry tests +
541 mozart lib tests still green; clippy clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
ResolveRequest and LockFileGenerationRequest now take Arc<RepositorySet>
instead of a raw Cache. install_from_lock now accepts &mut dyn
InstallerExecutor instead of constructing FilesystemExecutor internally.
Both changes expose the DI injection points needed by the upcoming
in-process test harness, where Packagist must be replaced with an empty
RepositorySet (Composer's `'packagist' => false` test config) and
filesystem install execution must be replaced with a tracing recorder
(Composer's InstallationManagerMock).
The eager VCS scan and inline-package preload still happen inside
resolve(), so the RawRepository array is kept on ResolveRequest as
raw_repositories - migrating those through RepositorySet remains a
follow-up. RepositorySet gains with_packagist and empty constructors so
production callers and future tests have a uniform construction shape.
All 136 enabled installer fixtures + 114 mozart-registry tests + 541
mozart lib tests still green; clippy clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Replace direct packagist::fetch_package_versions calls in
resolver::resolve (seed + transitive loops) and lockfile::generate_lock_file
with repo_set.load_packages calls. PackagistRepository now propagates
errors instead of swallowing them, so the seed loop's strictness and the
transitive loop's local-leniency are both preserved exactly.
VCS and inline-package repositories are still preloaded directly into
the pool builder for now, with their names tracked in skip lists so we
don't double-load them through the trait. Migrating them through
RepositorySet is a follow-up - vcs_to_pool_inputs and
packagist_to_pool_inputs differ in dev-branch handling that needs to be
unified first.
All 136 enabled installer fixtures + 114 mozart-registry tests + 541
mozart lib tests remain green; clippy clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Sets up DI scaffolding for in-process installer E2E tests, mirroring how
Composer's PHPUnit suite swaps Packagist (FactoryMock) and the install
manager (InstallationManagerMock) without touching the network or filesystem.
Additions:
- Repository trait + RepositorySet (Composer's RepositoryInterface analog),
with PackagistRepository, InlinePackageRepository, VcsRepository impls.
- InstallerExecutor trait (Composer's InstallationManager analog) with
FilesystemExecutor extracted from install_from_lock.
install_from_lock now delegates per-package install/uninstall verbs to
FilesystemExecutor; console output orchestration stays in the caller so
existing --EXPECT-OUTPUT-shape assertions remain comparable. No behavior
change - all 136 enabled installer fixtures still pass.
Also tightens the installer_fixture\! ignore form to a single token
(installer_fixture\!(name, ignore)) for readability.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
The pool builder and rule-set generator only consulted an exact-match
HashSet, so `--ignore-platform-reqs` (no value) and `--ignore-platform-req=ext-foo-*`
fell through to the SAT layer and produced "no matching package found"
for transitive platform deps. Track the bool flag separately and run
each platform name through `mozart_core::matches_wildcard` against the
configured patterns.
Unblocks four installer fixtures:
install-{ignore-platform-package-requirement-wildcard,ignore-platform-package-requirements}
update-{ignore-platform-package-requirement-wildcard,ignore-platform-package-requirements}.
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>
|
|
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'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>
|
|
Replace if-let/else-return with `?`, swap `as_ref().map(|k| k.as_slice())`
for `as_deref()`, and switch test fixtures from `vec\![]` to array literals
where ownership is unneeded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer treats _readme as write-only metadata: Locker.php injects it on
write but the loader never requires it. Mozart's deserializer was strict,
so any composer.lock without _readme failed to parse — including most
fixtures under composer/tests/.../installer/*.test.
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>
|
|
files_cache was Option<&Cache> and install_from_lock always passed None,
so downloaded zip/tar archives were never cached. Make the parameter
non-optional (&Cache) and wire it through every command that downloads
dist archives (install, update, require, remove, create-project,
archive). The Cache internally respects --no-cache via its enabled flag,
so the Option wrapper was unnecessary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
The watch graph's propagateLiteral used a cloned chain for iteration
while checking the live chain for bounds. After move_watch removed a
node, the stale clone kept re-reading the same node index, causing an
infinite loop on large dependency sets (e.g. laravel/laravel).
Now re-fetch the live chain each iteration, matching Composer's
SplDoublyLinkedList semantics where remove() advances the iterator.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Remove the Option wrapper from repo_cache in ResolveRequest,
LockFileGenerationRequest, and fetch_package_versions. All commands
now initialize a Cache via build_cache_config(cli.no_cache), ensuring
Packagist metadata is cached to disk (respecting --no-cache flag).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Add #[tracing::instrument] and debug logs to all HTTP-calling
functions in mozart-registry and mozart-vcs for request-level
observability (URL, status code, cache hits, download size).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Replace manual tokio::runtime::Handle::current().block_on() calls with
native async/await throughout all VCS drivers. Introduce AnyVcsDriver
enum for static dispatch to avoid dyn trait with async methods.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Implement VCS driver/downloader infrastructure mirroring Composer's VCS
subsystem. Includes drivers for GitHub, GitLab, Bitbucket, Forgejo, Git,
Hg, and SVN with API-based metadata resolution, plus source downloaders
for Git/Hg/SVN. Integrates into mozart-registry via vcs_bridge module to
scan VCS repositories and feed discovered packages into the SAT resolver.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
passthrough
- Parse and apply --with temporary constraints to the resolver
- Support inline constraint shorthand (vendor/pkg:1.0.*)
- Reject --lock combined with specific package names
- Filter magic keywords (lock/nothing/mirrors) from package list
- Pass APCu CLI flags through to InstallConfig instead of hardcoding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Parse the `abandoned` field from Packagist search API responses and
show a "! Abandoned !" warning inline, matching Composer's behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Virtual/meta packages (e.g. "psr/http-client-implementation") don't
exist on Packagist and caused a fatal error during transitive dependency
exploration. These packages are resolved via provides/replaces from
other packages already in the pool, so 404 errors are now skipped.
Also fix PoolBuilder::next_pending() repeatedly returning the same
virtual package name by tracking explored names in a HashSet, since
virtual packages are never added to inputs and the old check
(inputs.any(name)) never matched them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Replace unreachable\!() with proper @dev suffix output. Although Dev
is normally handled by an early return, this prevents a panic if the
control flow is ever refactored.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
composer-runtime-api, composer-plugin-api, and composer are Composer
pseudo packages that don't exist on Packagist. The resolver was trying
to fetch them remotely (HTTP 404) because PackageName::is_platform()
didn't recognize them and detect_platform() didn't inject them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Add mozart-sat-resolver crate implementing a CDCL SAT-based dependency
resolver ported from Composer's DependencyResolver. This replaces the
pubgrub library to ensure identical resolution behavior with Composer.
The new crate includes: pool (package storage with integer IDs),
rule/rule_set/rule_set_generator (constraint encoding), decisions
(assignment tracking), rule_watch_graph (2-watched literal BCP),
solver (CDCL loop with conflict analysis and clause learning),
policy (version preference), problem (Composer-style error messages),
and transaction (install/update/uninstall operation computation).
The registry resolver is rewritten to use PoolBuilder → RuleSetGenerator
→ Solver pipeline instead of pubgrub's DependencyProvider trait.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
ComposerVersion used u16 segments (max 65535), causing overflow for
PHP extensions like ext-dom (version 20031129). The extension became
invisible to the resolver, failing create-project with "depends on
ext-dom" errors.
Use mozart_semver::Version (u64 segments) directly as pubgrub's
version type, eliminating the overflow and redundant conversion layer.
Also fixes Ord for patch pre-releases (patch1 > stable) and adds
Display impl required by pubgrub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Rename mozart-constraint to mozart-semver (mirrors composer/semver) and
extract mozart-class-map-generator from mozart-autoload (mirrors
composer/class-map-generator). No logic changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Composer never shows the internal __root__ identifier to users. Add
root_name field to ResolveRequest so the resolver can substitute the
real package name (e.g. "laravel/laravel") in pubgrub error reports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
PlatformConfig::new() was hardcoded to PHP 8.1 with a fixed extension
list, causing resolution failures for packages requiring newer PHP
(e.g. Laravel 12 requires >=8.2). Now calls detect_platform() to
discover the actual PHP version, extensions and capabilities.
Also adds a mutex to composer_home_dir tests to prevent env-var races.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
|
|
Add mozart_core::http::user_agent() that returns a consistent
"Mozart/<version> (<os>; <arch>)" string. Replace all scattered
user-agent definitions across mozart-registry and mozart CLI commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Port composer/metadata-minifier to Rust as an independent workspace
crate. Implements expand() and minify() for Packagist's delta-encoded
version metadata. Update mozart-registry to use the new crate for
transparent minified response handling, and add __unset sentinel
support to PackagistVersion deserialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Replace reqwest::blocking with async reqwest across the entire codebase.
All command execute functions, registry API calls (packagist, downloader,
resolver, lockfile), and the main entry point now use async/await with
the tokio runtime. The pubgrub resolver runs on spawn_blocking since its
DependencyProvider trait is synchronous, using Handle::block_on for
async I/O within that context.
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>
|