1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! # pubsat — SAT-based dependency resolution
//!
//! `pubsat` is a backend-agnostic, ecosystem-agnostic SAT-based
//! dependency resolver for semver-shaped constraint problems. The
//! same engine should serve a JS-style package manager, a private
//! artifact registry, a build-tool internal resolver, or any
//! other workflow with a "pick the right versions" sub-problem.
//!
//! ## Modules
//!
//! - [`version`] — node-semver-compatible range parser (caret,
//! tilde, hyphen, x-ranges, unions, dist tags) with
//! [`VersionSet`](version::VersionSet) operations.
//! - [`constraint`] — ecosystem-independent
//! [`Constraint`](constraint::Constraint) vocabulary.
//! - [`registry`] — [`PackageRegistry`](registry::PackageRegistry)
//! trait, single-flighted [`CachedRegistry`](registry::CachedRegistry)
//! wrapper, and in-process [`MockRegistry`](registry::MockRegistry).
//! - [`graph`] — [`DependencyGraph`](graph::DependencyGraph)
//! (petgraph-backed) with cycle detection.
//! - [`encoding`] —
//! [`ConstraintEncoder`](encoding::ConstraintEncoder) lowering
//! constraints to CNF.
//! - [`builder`] —
//! [`DependencyGraphBuilder`](builder::DependencyGraphBuilder)
//! that walks a registry concurrently.
//! - [`resolver`] —
//! [`DependencyResolver`](resolver::DependencyResolver) that
//! orchestrates the full pipeline with greedy "prefer newest"
//! SAT assumptions.
//! - [`sat`] — backend-agnostic SAT types and the
//! [`SatSolver`](sat::SatSolver) trait, with a
//! [`VarisatSolver`](sat::VarisatSolver) impl behind the default
//! `varisat-solver` feature.
//! - [`error`] — [`ResolutionError`](error::ResolutionError),
//! [`SatError`](error::SatError), and their `Result` aliases.
//!
//! ## Example: parse and evaluate a range
//!
//! ```
//! use pubsat::version::VersionSet;
//! use semver::Version;
//! use std::str::FromStr;
//!
//! let range: VersionSet = "^1.2.3".parse().unwrap();
//! assert!(range.satisfies(&Version::from_str("1.5.0").unwrap()));
//! assert!(range.satisfies(&Version::from_str("1.2.3").unwrap()));
//! assert!(!range.satisfies(&Version::from_str("2.0.0").unwrap()));
//! assert!(!range.satisfies(&Version::from_str("1.2.2").unwrap()));
//! ```
//!
//! ## Example: end-to-end resolution
//!
//! ```
//! # #[cfg(feature = "varisat-solver")]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! use std::sync::Arc;
//! use pubsat::builder::DependencyGraphBuilder;
//! use pubsat::registry::{MockRegistry, VersionMetadata};
//! use pubsat::resolver::DependencyResolver;
//! use pubsat::version::VersionSet;
//! use semver::Version;
//!
//! let vs = |s: &str| -> VersionSet { s.parse().unwrap() };
//!
//! let registry = Arc::new(
//! MockRegistry::new()
//! .with_versions("chalk", &["4.1.0", "5.0.0"])
//! .with_versions("ansi-styles", &["4.3.0", "6.2.1"])
//! .with_dependency("chalk", "4.1.0", "ansi-styles", vs("^4.0.0"))
//! .with_dependency("chalk", "5.0.0", "ansi-styles", vs("^6.0.0")),
//! );
//!
//! let root = VersionMetadata::new("my-app", Version::new(1, 0, 0))
//! .with_dependency("chalk", vs("^5.0.0"));
//!
//! let graph = DependencyGraphBuilder::new(registry.clone())
//! .build(root)
//! .await
//! .unwrap();
//!
//! let resolution = DependencyResolver::new(registry)
//! .resolve(graph)
//! .await
//! .unwrap();
//!
//! // resolution.packages: [ansi-styles@6.2.1, chalk@5.0.0]
//! assert_eq!(resolution.packages.len(), 2);
//! # }
//! ```
//!
//! ## Design context
//!
//! See [`docs/design/architecture.md`][arch] for the design
//! rationale (why SAT and not PubGrub, hot-path lessons, the
//! comparison with prior art).
//!
//! [arch]: https://github.com/cygnus-io/pubsat/blob/main/docs/design/architecture.md