aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart-sat-resolver/src/pool_builder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mozart-sat-resolver/src/pool_builder.rs')
-rw-r--r--crates/mozart-sat-resolver/src/pool_builder.rs222
1 files changed, 0 insertions, 222 deletions
diff --git a/crates/mozart-sat-resolver/src/pool_builder.rs b/crates/mozart-sat-resolver/src/pool_builder.rs
deleted file mode 100644
index 6088e7d..0000000
--- a/crates/mozart-sat-resolver/src/pool_builder.rs
+++ /dev/null
@@ -1,222 +0,0 @@
-use crate::pool::{Pool, PoolLink, PoolPackageInput};
-use indexmap::IndexSet;
-use std::collections::VecDeque;
-
-/// Builder for constructing a Pool from package metadata.
-///
-/// The builder accepts package inputs and recursively discovers
-/// transitive dependencies. This is done by the registry layer
-/// before solving.
-pub struct PoolBuilder {
- /// Packages to add to the pool.
- inputs: Vec<PoolPackageInput>,
- /// Names already added (to avoid duplicates).
- added: IndexSet<String>,
- /// Queue of package names that need to be explored.
- pending_names: VecDeque<String>,
- /// Package names that have already been explored (returned by next_pending).
- explored_names: IndexSet<String>,
- /// Specific platform packages to ignore (from `--ignore-platform-req=name`).
- ignore_platform_reqs: IndexSet<String>,
- /// When true, ignore every platform package (php, ext-*, lib-*, composer-*).
- /// Mirrors `--ignore-platform-reqs` (no value).
- ignore_all_platform_reqs: bool,
-}
-
-impl PoolBuilder {
- pub fn new() -> Self {
- PoolBuilder {
- inputs: Vec::new(),
- added: IndexSet::new(),
- pending_names: VecDeque::new(),
- explored_names: IndexSet::new(),
- ignore_platform_reqs: IndexSet::new(),
- ignore_all_platform_reqs: false,
- }
- }
-
- /// Set platform requirements to ignore during exploration.
- pub fn set_ignore_platform_reqs(&mut self, names: IndexSet<String>) {
- 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);
- if self.added.contains(&key) {
- return false;
- }
- self.added.insert(key);
-
- // Queue dependency names for exploration
- for link in &input.requires {
- if !self.is_ignored_platform_dep(&link.target) {
- self.pending_names.push_back(link.target.clone());
- }
- }
-
- self.inputs.push(input);
- true
- }
-
- /// Get the next package name that needs to be explored.
- /// The caller should fetch available versions for this package
- /// and add them via `add_package`.
- pub fn next_pending(&mut self) -> Option<String> {
- while let Some(name) = self.pending_names.pop_front() {
- // Skip if already explored or already has versions in inputs
- if self.explored_names.contains(&name) {
- continue;
- }
- if self.inputs.iter().any(|p| p.name == name) {
- continue;
- }
- self.explored_names.insert(name.clone());
- return Some(name);
- }
- None
- }
-
- /// Check if there are more names to explore.
- pub fn has_pending(&self) -> bool {
- !self.pending_names.is_empty()
- }
-
- /// Build the final Pool.
- pub fn build(self) -> Pool {
- Pool::new(self.inputs, vec![])
- }
-
- /// Get the number of packages added so far.
- pub fn len(&self) -> usize {
- self.inputs.len()
- }
-
- /// Read-only access to package inputs collected so far. Used by the
- /// registry layer to materialize root aliases (`require: "X as Y"`) once
- /// every base + branch-alias entry is in place: a second pass scans for
- /// matching `(name, version)` and pushes the alias entry on top.
- pub fn inputs(&self) -> &[PoolPackageInput] {
- &self.inputs
- }
-
- /// Whether the builder has no packages.
- pub fn is_empty(&self) -> bool {
- self.inputs.is_empty()
- }
-}
-
-impl Default for PoolBuilder {
- fn default() -> Self {
- Self::new()
- }
-}
-
-/// Helper to convert (name, constraint) pairs from Packagist into PoolLinks.
-///
-/// `source_version` is the normalized version of the package declaring these
-/// links; it replaces any `"self.version"` constraint, mirroring Composer's
-/// `ArrayLoader::createLink` (and `AliasPackage::replaceSelfVersionDependencies`,
-/// which feeds the alias's own version in for the same purpose).
-pub fn make_pool_links(
- source: &str,
- source_version: &str,
- deps: &[(String, String)],
-) -> Vec<PoolLink> {
- deps.iter()
- .map(|(target, constraint)| PoolLink {
- target: target.clone(),
- constraint: if constraint.trim() == "self.version" {
- source_version.to_string()
- } else {
- constraint.clone()
- },
- source: source.to_string(),
- })
- .collect()
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_pool_builder_basic() {
- let mut builder = PoolBuilder::new();
-
- builder.add_package(PoolPackageInput {
- name: "a/a".to_string(),
- version: "1.0.0.0".to_string(),
- pretty_version: "1.0.0".to_string(),
- requires: vec![PoolLink {
- target: "b/b".to_string(),
- constraint: "^1.0".to_string(),
- source: "a/a".to_string(),
- }],
- replaces: vec![],
- provides: vec![],
- conflicts: vec![],
- is_fixed: false,
- is_alias_of: None,
- });
-
- // Should have b/b pending
- let pending = builder.next_pending();
- assert_eq!(pending, Some("b/b".to_string()));
-
- builder.add_package(PoolPackageInput {
- name: "b/b".to_string(),
- version: "1.0.0.0".to_string(),
- pretty_version: "1.0.0".to_string(),
- requires: vec![],
- replaces: vec![],
- provides: vec![],
- conflicts: vec![],
- is_fixed: false,
- is_alias_of: None,
- });
-
- // No more pending
- assert!(builder.next_pending().is_none());
-
- let pool = builder.build();
- assert_eq!(pool.len(), 2);
- }
-
- #[test]
- fn test_deduplication() {
- let mut builder = PoolBuilder::new();
-
- let input = PoolPackageInput {
- name: "a/a".to_string(),
- version: "1.0.0.0".to_string(),
- pretty_version: "1.0.0".to_string(),
- requires: vec![],
- replaces: vec![],
- provides: vec![],
- conflicts: vec![],
- is_fixed: false,
- is_alias_of: None,
- };
-
- assert!(builder.add_package(input.clone()));
- assert!(!builder.add_package(input));
- assert_eq!(builder.len(), 1);
- }
-}