aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart-registry/src/installer_executor
AgeCommit message (Collapse)Author
2026-05-02feat(resolver): add branch-alias support across the resolution pipelinensfisis
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>
2026-05-02fix(installer): match Composer's transaction order and uninstall labelnsfisis
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>
2026-05-02test(installer): switch fixtures to in-process harnessnsfisis
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>
2026-05-02feat(installer): add trace recorder and topo install ordernsfisis
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>
2026-05-02refactor(registry): introduce Repository and InstallerExecutor traitsnsfisis
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>