aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-02 11:19:09 +0900
committernsfisis <nsfisis@gmail.com>2026-05-02 11:19:09 +0900
commitb216124157b69edc7330291214a6043c555f0ade (patch)
tree13794ed3f158af0b01fc438548723e533eda4300
parent2ff728fe6796506be0e6b640ccb85ed3e1ce2b56 (diff)
downloadphp-mozart-b216124157b69edc7330291214a6043c555f0ade.tar.gz
php-mozart-b216124157b69edc7330291214a6043c555f0ade.tar.zst
php-mozart-b216124157b69edc7330291214a6043c555f0ade.zip
feat(resolver): honor --ignore-platform-reqs and wildcard patterns
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>
-rw-r--r--crates/mozart-registry/src/resolver.rs9
-rw-r--r--crates/mozart-sat-resolver/src/pool_builder.rs24
-rw-r--r--crates/mozart-sat-resolver/src/rule_set_generator.rs28
-rw-r--r--crates/mozart/tests/installer.rs20
4 files changed, 55 insertions, 26 deletions
diff --git a/crates/mozart-registry/src/resolver.rs b/crates/mozart-registry/src/resolver.rs
index 7aab6b2..710a9c4 100644
--- a/crates/mozart-registry/src/resolver.rs
+++ b/crates/mozart-registry/src/resolver.rs
@@ -231,7 +231,9 @@ fn should_skip_platform_dep(
if ignore_platform_reqs {
return true;
}
- ignore_platform_req_list.iter().any(|p| p == dep_name)
+ ignore_platform_req_list
+ .iter()
+ .any(|p| mozart_core::matches_wildcard(dep_name, p))
}
// ─────────────────────────────────────────────────────────────────────────────
@@ -412,13 +414,11 @@ pub async fn resolve(request: &ResolveRequest) -> Result<Vec<ResolvedPackage>, R
// Set up ignore list for platform requirements
let mut ignore_set: HashSet<String> = HashSet::new();
- if request.ignore_platform_reqs {
- // We'll skip platform deps in the loop below
- }
for name in &request.ignore_platform_req_list {
ignore_set.insert(name.clone());
}
builder.set_ignore_platform_reqs(ignore_set.clone());
+ builder.set_ignore_all_platform_reqs(request.ignore_platform_reqs);
// Add platform packages as fixed entries
let platform_config = request.platform.to_versions();
@@ -560,6 +560,7 @@ pub async fn resolve(request: &ResolveRequest) -> Result<Vec<ResolvedPackage>, R
// Generate rules
let mut generator = RuleSetGenerator::new(&mut pool);
generator.set_ignore_platform_reqs(ignore_set);
+ generator.set_ignore_all_platform_reqs(request.ignore_platform_reqs);
let rules = generator.generate(&root_requires, &fixed_ids);
// Create policy and solve
diff --git a/crates/mozart-sat-resolver/src/pool_builder.rs b/crates/mozart-sat-resolver/src/pool_builder.rs
index a642fc3..544cac3 100644
--- a/crates/mozart-sat-resolver/src/pool_builder.rs
+++ b/crates/mozart-sat-resolver/src/pool_builder.rs
@@ -15,8 +15,11 @@ pub struct PoolBuilder {
pending_names: VecDeque<String>,
/// Package names that have already been explored (returned by next_pending).
explored_names: HashSet<String>,
- /// Platform packages to ignore.
+ /// Specific platform packages to ignore (from `--ignore-platform-req=name`).
ignore_platform_reqs: HashSet<String>,
+ /// When true, ignore every platform package (php, ext-*, lib-*, composer-*).
+ /// Mirrors `--ignore-platform-reqs` (no value).
+ ignore_all_platform_reqs: bool,
}
impl PoolBuilder {
@@ -27,6 +30,7 @@ impl PoolBuilder {
pending_names: VecDeque::new(),
explored_names: HashSet::new(),
ignore_platform_reqs: HashSet::new(),
+ ignore_all_platform_reqs: false,
}
}
@@ -35,6 +39,22 @@ impl PoolBuilder {
self.ignore_platform_reqs = names;
}
+ /// When set, every platform package is skipped during exploration.
+ pub fn set_ignore_all_platform_reqs(&mut self, ignore_all: bool) {
+ self.ignore_all_platform_reqs = ignore_all;
+ }
+
+ fn is_ignored_platform_dep(&self, name: &str) -> bool {
+ if self
+ .ignore_platform_reqs
+ .iter()
+ .any(|p| mozart_core::matches_wildcard(name, p))
+ {
+ return true;
+ }
+ self.ignore_all_platform_reqs && mozart_core::platform::is_platform_package(name)
+ }
+
/// Add a package version to the builder. Returns true if it's new.
pub fn add_package(&mut self, input: PoolPackageInput) -> bool {
let key = format!("{}@{}", input.name, input.version);
@@ -45,7 +65,7 @@ impl PoolBuilder {
// Queue dependency names for exploration
for link in &input.requires {
- if !self.ignore_platform_reqs.contains(&link.target) {
+ if !self.is_ignored_platform_dep(&link.target) {
self.pending_names.push_back(link.target.clone());
}
}
diff --git a/crates/mozart-sat-resolver/src/rule_set_generator.rs b/crates/mozart-sat-resolver/src/rule_set_generator.rs
index 39d28fd..bc56dff 100644
--- a/crates/mozart-sat-resolver/src/rule_set_generator.rs
+++ b/crates/mozart-sat-resolver/src/rule_set_generator.rs
@@ -13,8 +13,11 @@ pub struct RuleSetGenerator<'a> {
added_map: HashSet<PackageId>,
/// Package names → list of package IDs with that name (non-alias).
added_packages_by_name: HashMap<String, Vec<PackageId>>,
- /// Platform packages to ignore.
+ /// Specific platform packages to ignore (from `--ignore-platform-req=name`).
ignore_platform_reqs: HashSet<String>,
+ /// When true, every platform package is treated as ignored.
+ /// Mirrors `--ignore-platform-reqs` (no value).
+ ignore_all_platform_reqs: bool,
}
impl<'a> RuleSetGenerator<'a> {
@@ -25,6 +28,7 @@ impl<'a> RuleSetGenerator<'a> {
added_map: HashSet::new(),
added_packages_by_name: HashMap::new(),
ignore_platform_reqs: HashSet::new(),
+ ignore_all_platform_reqs: false,
}
}
@@ -33,6 +37,22 @@ impl<'a> RuleSetGenerator<'a> {
self.ignore_platform_reqs = names;
}
+ /// When set, every platform package is treated as ignored.
+ pub fn set_ignore_all_platform_reqs(&mut self, ignore_all: bool) {
+ self.ignore_all_platform_reqs = ignore_all;
+ }
+
+ fn is_ignored_platform_dep(&self, name: &str) -> bool {
+ if self
+ .ignore_platform_reqs
+ .iter()
+ .any(|p| mozart_core::matches_wildcard(name, p))
+ {
+ return true;
+ }
+ self.ignore_all_platform_reqs && mozart_core::platform::is_platform_package(name)
+ }
+
/// Generate rules for a set of requirements and fixed packages.
///
/// Port of Composer's RuleSetGenerator::getRulesFor.
@@ -60,7 +80,7 @@ impl<'a> RuleSetGenerator<'a> {
// Process root requirements
for (name, constraint) in requires {
- if self.ignore_platform_reqs.contains(name.as_str()) {
+ if self.is_ignored_platform_dep(name.as_str()) {
continue;
}
@@ -116,7 +136,7 @@ impl<'a> RuleSetGenerator<'a> {
// Process each requirement
for link in requires {
- if self.ignore_platform_reqs.contains(&link.target) {
+ if self.is_ignored_platform_dep(&link.target) {
continue;
}
@@ -168,7 +188,7 @@ impl<'a> RuleSetGenerator<'a> {
let conflicts = pkg.conflicts.clone();
for link in conflicts {
- if self.ignore_platform_reqs.contains(&link.target) {
+ if self.is_ignored_platform_dep(&link.target) {
continue;
}
diff --git a/crates/mozart/tests/installer.rs b/crates/mozart/tests/installer.rs
index fc13392..3c47750 100644
--- a/crates/mozart/tests/installer.rs
+++ b/crates/mozart/tests/installer.rs
@@ -190,14 +190,8 @@ installer_fixture!(install_funding_notice);
installer_fixture!(install_funding_notice_env);
installer_fixture!(install_funding_notice_not_displayed_env);
installer_fixture!(install_ignore_platform_package_requirement_list);
-installer_fixture!(
- install_ignore_platform_package_requirement_wildcard,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- install_ignore_platform_package_requirements,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(install_ignore_platform_package_requirement_wildcard);
+installer_fixture!(install_ignore_platform_package_requirements);
installer_fixture!(
install_missing_alias_from_lock,
ignore = "mozart binary cannot yet run this fixture"
@@ -461,14 +455,8 @@ installer_fixture!(
);
installer_fixture!(update_ignore_platform_package_requirement_list);
installer_fixture!(update_ignore_platform_package_requirement_list_upper_bounds);
-installer_fixture!(
- update_ignore_platform_package_requirement_wildcard,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- update_ignore_platform_package_requirements,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(update_ignore_platform_package_requirement_wildcard);
+installer_fixture!(update_ignore_platform_package_requirements);
installer_fixture!(update_installed_alias);
installer_fixture!(update_installed_alias_dry_run);
installer_fixture!(update_installed_reference);