From 3c0527aa63574f17c9f372b6187d5690e0cbaff0 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 3 May 2026 13:14:00 +0900 Subject: fix(resolver): apply root "X as Y" aliases via pool second pass Mirrors Composer's `RootPackageLoader::extractAliases` + `PoolBuilder::loadPackage` flow: strip the `as` clause from each root require so the SAT side sees only the LEFT-hand constraint, and after every package is loaded run a second pass that materializes an alias entry for any input matching `(name, version_normalized)`. Locked-only packages in a partial update are excluded via a new `ResolveRequest::locked_package_names` so they don't pick up the alias (`propagateUpdate=false` in Composer). Two adjacent fixes uncovered while making `install_aliased_alias` green: - `Version::cmp` treated unnamed wildcard branches (`1.0.x-dev`, `is_dev_branch=true && name=None`) as below every numeric version. They are semantically the same as the four-segment `*-dev` form Composer's `normalizeBranch` emits, so let only *named* branches take the shortcut. - `Constraint::Exact` / `NotEqual` used the derived `==`, which compared `is_dev_branch` field-by-field and missed the wildcard/numeric equivalence. Switch to `cmp` so both forms count as equal. - `Pool::matches_package` now falls back to parsing `pretty_version` when the `version` parse doesn't match the constraint, so a `dev-master` query lines up with a pool entry stored as the internal `9999999.x.x.x-dev` expansion. Net effect on installer fixtures: `install_aliased_alias` newly green, plus `aliased_priority`, `aliased_priority_conflicting`, and `install_dev_using_dist` come along for the ride. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/mozart/src/commands/remove.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'crates/mozart/src/commands/remove.rs') diff --git a/crates/mozart/src/commands/remove.rs b/crates/mozart/src/commands/remove.rs index 08f7cc6..15b3586 100644 --- a/crates/mozart/src/commands/remove.rs +++ b/crates/mozart/src/commands/remove.rs @@ -274,6 +274,7 @@ pub async fn execute( .iter() .map(|(k, v)| (k.clone(), v.clone())) .collect(), + locked_package_names: indexmap::IndexSet::new(), }; // Print header messages @@ -550,6 +551,7 @@ async fn remove_unused( .iter() .map(|(k, v)| (k.clone(), v.clone())) .collect(), + locked_package_names: indexmap::IndexSet::new(), }; console.info("Resolving dependencies to detect unused packages..."); @@ -859,7 +861,7 @@ mod tests { #[tokio::test] #[ignore] async fn test_remove_full_e2e() { - use indexmap::IndexMap; + use indexmap::{IndexMap, IndexSet}; use mozart_registry::lockfile::{LockFileGenerationRequest, generate_lock_file}; use mozart_registry::resolver::{ResolveRequest, resolve}; use tempfile::tempdir; @@ -902,6 +904,7 @@ mod tests { root_provide: IndexMap::new(), root_replace: IndexMap::new(), root_conflict: IndexMap::new(), + locked_package_names: IndexSet::new(), }; let resolved = resolve(&request) .await @@ -957,6 +960,7 @@ mod tests { root_provide: IndexMap::new(), root_replace: IndexMap::new(), root_conflict: IndexMap::new(), + locked_package_names: IndexSet::new(), }; let resolved2 = resolve(&request2) .await -- cgit v1.3.1