Skip to content

Commit

Permalink
move solver mod comment to resolver (#319)
Browse files Browse the repository at this point in the history
* move solver mod comment to resolver

* Some nits

* fix todos. removing the Version trait
  • Loading branch information
Eh2406 authored Feb 6, 2025
1 parent 2335796 commit 00c688c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 77 deletions.
35 changes: 18 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,6 @@
//! we should try to provide a very human-readable and clear
//! explanation as to why that failed.
//!
//! # Package and Version traits
//!
//! All the code in this crate is manipulating packages and versions, and for this to work
//! we defined a [Package] trait
//! that is used as bounds on most of the exposed types and functions.
//!
//! Package identifiers needs to implement our [Package] trait,
//! which is automatic if the type already implements
//! [Clone] + [Eq] + [Hash] + [Debug] + [Display](std::fmt::Display).
//! So things like [String] will work out of the box.
//!
//! TODO! This is all wrong. Need to talk about VS, not Version.
//! Our Version trait requires
//! [Clone] + [Ord] + [Debug] + [Display](std::fmt::Display).
//! For convenience, this library provides [SemanticVersion]
//! that implements semantic versioning rules.
//!
//! # Basic example
//!
//! Let's imagine that we are building a user interface
Expand Down Expand Up @@ -59,6 +42,24 @@
//! let solution = resolve(&dependency_provider, "root", 1u32).unwrap();
//! ```
//!
//! # Package and Version flexibility
//!
//! The [OfflineDependencyProvider] used in that example is generic over the way package names,
//! version requirements, and version numbers are represented.
//!
//! The first bound is the type of package names. It can be anything that implements our [Package] trait.
//! The [Package] trait is automatic if the type already implements
//! [Clone] + [Eq] + [Hash] + [Debug] + [Display](std::fmt::Display).
//! So things like [String] will work out of the box.
//!
//! The second bound is the type of package requirements. It can be anything that implements our [VersionSet] trait.
//! This trait is used to figure out how version requirements are combined.
//! If the normal [Ord]/[PartialEq] operations are all that is needed for requirements, our [Ranges] type will work.
//!
//! The chosen `VersionSet` in turn specifies what can be used for version numbers.
//! This type needs to at least implement [Clone] + [Ord] + [Debug] + [Display](std::fmt::Display).
//! For convenience, this library provides [SemanticVersion] that implements the basics of semantic versioning rules.
//!
//! # DependencyProvider trait
//!
//! In our previous example we used the
Expand Down
115 changes: 55 additions & 60 deletions src/solver.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,5 @@
// SPDX-License-Identifier: MPL-2.0

//! PubGrub version solving algorithm.
//!
//! It consists in efficiently finding a set of packages and versions
//! that satisfy all the constraints of a given project dependencies.
//! In addition, when that is not possible,
//! PubGrub tries to provide a very human-readable and clear
//! explanation as to why that failed.
//! Below is an example of explanation present in
//! the introductory blog post about PubGrub
//!
//! ```txt
//! Because dropdown >=2.0.0 depends on icons >=2.0.0 and
//! root depends on icons <2.0.0, dropdown >=2.0.0 is forbidden.
//!
//! And because menu >=1.1.0 depends on dropdown >=2.0.0,
//! menu >=1.1.0 is forbidden.
//!
//! And because menu <1.1.0 depends on dropdown >=1.0.0 <2.0.0
//! which depends on intl <4.0.0, every version of menu
//! requires intl <4.0.0.
//!
//! So, because root depends on both menu >=1.0.0 and intl >=5.0.0,
//! version solving failed.
//! ```
//!
//! The algorithm is generic and works for any type of dependency system
//! as long as packages (P) and versions (V) implement
//! the [Package] and Version traits.
//! [Package] is strictly equivalent and automatically generated
//! for any type that implement [Clone] + [Eq] + [Hash] + [Debug] + [Display].
//!
//! ## API
//!
//! ```
//! # use std::convert::Infallible;
//! # use pubgrub::{resolve, OfflineDependencyProvider, PubGrubError, Ranges};
//! #
//! # type NumVS = Ranges<u32>;
//! #
//! # fn try_main() -> Result<(), PubGrubError<OfflineDependencyProvider<&'static str, NumVS>>> {
//! # let dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
//! # let package = "root";
//! # let version = 1u32;
//! let solution = resolve(&dependency_provider, package, version)?;
//! # Ok(())
//! # }
//! # fn main() {
//! # assert!(matches!(try_main(), Err(PubGrubError::NoSolution(_))));
//! # }
//! ```
//!
//! Where `dependency_provider` supplies the list of available packages and versions,
//! as well as the dependencies of every available package
//! by implementing the [DependencyProvider] trait.
//! The call to [resolve] for a given package at a given version
//! will compute the set of packages and versions needed
//! to satisfy the dependencies of that package and version pair.
//! If there is no solution, the reason will be provided as clear as possible.
use std::collections::BTreeSet as Set;
use std::error::Error;
use std::fmt::{Debug, Display};
Expand Down Expand Up @@ -107,8 +48,62 @@ impl PackageResolutionStatistics {
}
}

/// Main function of the library.
/// Finds a set of packages satisfying dependency bounds for a given package + version pair.
///
/// It consists in efficiently finding a set of packages and versions
/// that satisfy all the constraints of a given project dependencies.
/// In addition, when that is not possible,
/// PubGrub tries to provide a very human-readable and clear
/// explanation as to why that failed.
/// Below is an example of explanation present in
/// the introductory blog post about PubGrub
/// (Although this crate is not yet capable of building formatting quite this nice.)
///
/// ```txt
/// Because dropdown >=2.0.0 depends on icons >=2.0.0 and
/// root depends on icons <2.0.0, dropdown >=2.0.0 is forbidden.
///
/// And because menu >=1.1.0 depends on dropdown >=2.0.0,
/// menu >=1.1.0 is forbidden.
///
/// And because menu <1.1.0 depends on dropdown >=1.0.0 <2.0.0
/// which depends on intl <4.0.0, every version of menu
/// requires intl <4.0.0.
///
/// So, because root depends on both menu >=1.0.0 and intl >=5.0.0,
/// version solving failed.
/// ```
///
/// Is generic over an implementation of [DependencyProvider] which represents where the dependency constraints come from.
/// The associated types on the DependencyProvider allow flexibility for the representation of
/// package names, version requirements, version numbers, and other things.
/// See its documentation for more details.
/// For simple cases [OfflineDependencyProvider](crate::OfflineDependencyProvider) may be sufficient.
///
/// ## API
///
/// ```
/// # use std::convert::Infallible;
/// # use pubgrub::{resolve, OfflineDependencyProvider, PubGrubError, Ranges};
/// #
/// # type NumVS = Ranges<u32>;
/// #
/// # fn try_main() -> Result<(), PubGrubError<OfflineDependencyProvider<&'static str, NumVS>>> {
/// # let dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
/// # let package = "root";
/// # let version = 1u32;
/// let solution = resolve(&dependency_provider, package, version)?;
/// # Ok(())
/// # }
/// # fn main() {
/// # assert!(matches!(try_main(), Err(PubGrubError::NoSolution(_))));
/// # }
/// ```
///
/// The call to [resolve] for a given package at a given version
/// will compute the set of packages and versions needed
/// to satisfy the dependencies of that package and version pair.
/// If there is no solution, the reason will be provided as clear as possible.
#[cold]
pub fn resolve<DP: DependencyProvider>(
dependency_provider: &DP,
Expand Down

0 comments on commit 00c688c

Please sign in to comment.