diff --git a/crates/mono-project/src/project/version/ext.rs b/crates/mono-project/src/project/version/ext.rs index 8199112..5be124b 100644 --- a/crates/mono-project/src/project/version/ext.rs +++ b/crates/mono-project/src/project/version/ext.rs @@ -38,7 +38,10 @@ pub trait VersionExt { /// Returns the next version after applying the given increment. fn bump(&self, increment: Increment) -> Version; - /// Returns the highest possible increment for the version. + /// Returns the minimum increment for the version. + fn min_bump(&self) -> Option; + + /// Returns the maximum increment for the version. fn max_bump(&self) -> Increment; /// Parses a version from a string, allowing for an optional `v` prefix. @@ -113,15 +116,21 @@ impl VersionExt for Version { version } - /// Returns the highest possible increment for the version. - /// - /// This method returns the highest possible increment for this version, - /// taking into account special handling for `0.0.z` and `0.y.z` ranges. + /// Returns the minimum increment for the version. + fn min_bump(&self) -> Option { + if let (0, 0) = (self.major, self.minor) { + Some(Increment::Patch) + } else { + None + } + } + + /// Returns the maximum increment for the version. fn max_bump(&self) -> Increment { match (self.major, self.minor) { (0, 0) => Increment::Patch, (0, _) => Increment::Minor, - _ => Increment::Major, + (_, _) => Increment::Major, } } } diff --git a/crates/mono-project/src/project/workspace/dependents/suggestion.rs b/crates/mono-project/src/project/workspace/dependents/suggestion.rs index 149638a..7f3d2d8 100644 --- a/crates/mono-project/src/project/workspace/dependents/suggestion.rs +++ b/crates/mono-project/src/project/workspace/dependents/suggestion.rs @@ -25,10 +25,11 @@ //! Version increment suggestion. +use std::cmp; use std::collections::BTreeSet; use crate::project::manifest::Manifest; -use crate::project::version::Increment; +use crate::project::version::{Increment, VersionExt}; use crate::project::{Project, Result}; use super::Dependents; @@ -66,6 +67,7 @@ where /// # Errors /// /// This method passes through errors returned by the given function. + #[allow(clippy::missing_panics_doc)] pub fn bump(&self, increments: &mut [Option], f: F) -> Result where F: Fn(Suggestion<'_, T>) -> Result>, @@ -82,6 +84,17 @@ where // chosen by the caller are correctly propagated to dependents let incoming = self.graph.topology().incoming(); for node in self.graph.traverse(sources) { + let project = self.graph[node]; + + // Obtain the current package version, and clamp the increment to + // the minimum and maximum viable increments for the given version. + // This ensures that we never suggest an increment lower or higher + // than what the version requires or allows. + let version = project.manifest.version().expect("invariant"); + increments[node] = increments[node] + .map(|increment| cmp::min(increment, version.max_bump())) + .or(version.min_bump()); + // Obtain the unique version increments of all dependencies, and // collect them into a set for selection through the caller let mut options = BTreeSet::from_iter([increments[node]]); @@ -94,7 +107,7 @@ where // Collect the suggested version increments, and invoke the given // function, remembering the returned version increment increments[node] = f(Suggestion { - project: self.graph[node], + project, increments: &options.into_iter().collect::>(), })?; }