Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor Version.bump() to accept bumping major/minor/patch/last #452

Merged
merged 19 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/rattler_conda_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ pub use repo_data::{
pub use repo_data_record::RepoDataRecord;
pub use run_export::RunExportKind;
pub use version::{
Component, ParseVersionError, ParseVersionErrorKind, StrictVersion, Version, VersionWithSource,
Component, ParseVersionError, ParseVersionErrorKind, StrictVersion, Version, VersionBumpType,
VersionWithSource,
};
pub use version_spec::VersionSpec;

Expand Down
11 changes: 11 additions & 0 deletions crates/rattler_conda_types/src/version/bump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// VersionBumpType is used to specify the type of bump to perform on a version.
pub enum VersionBumpType {
/// Bump the major version number.
Major,
/// Bump the minor version number.
Minor,
/// Bump the patch version number.
Patch,
/// Bump the last version number.
Last,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a Segment(uint) type? So that we can explicitly select the segment to bump?

We might also consider that bumping non-existent segments should be possible. Usually, all non-existent segments are implicit .0, so bumping the patch of a 1.0 could also result in 1.0.1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a Segment(uint) type? So that we can explicitly select the segment to bump?

Good idea. Will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might also consider that bumping non-existent segments should be possible. Usually, all non-existent segments are implicit .0, so bumping the patch of a 1.0 could also result in 1.0.1.

Don't you prefer to instead fail, so it also builds incentive for the user to explicitly use x.x.x instead of x or x.x?

Unless you feel strongly here, I would prefer to let it for another PR (I can open a ticket if you want).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added support for VersionBumpType::Segment(i32) in 9283770 (rust side only).

}
154 changes: 144 additions & 10 deletions crates/rattler_conda_types/src/version/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub(crate) mod parse;
mod segment;
mod with_source;

pub(crate) mod bump;
pub use bump::VersionBumpType;

use flags::Flags;
use segment::Segment;

Expand Down Expand Up @@ -227,8 +230,8 @@ impl Version {
})
}

/// Returns a new version where the last numerical segment of this version has been bumped.
pub fn bump(&self) -> Self {
/// Returns a new version after bumping it according to the specified bump type.
pub fn bump(&self, bump_type: VersionBumpType) -> Self {
let mut components = ComponentVec::new();
let mut segments = SegmentVec::new();
let mut flags = Flags::default();
Expand All @@ -239,6 +242,31 @@ impl Version {
flags = flags.with_has_epoch(true);
}

// Sanity check whether the version has enough segments for this bump type.
let segment_count = self.segment_count();
match bump_type {
hadim marked this conversation as resolved.
Show resolved Hide resolved
VersionBumpType::Major => {
if segment_count < 1 {
panic!("cannot bump the major segment of a version with less than 1 segment");
}
}
VersionBumpType::Minor => {
if segment_count < 2 {
panic!("cannot bump the minor segment of a version with less than 2 segments");
}
}
VersionBumpType::Patch => {
if segment_count < 3 {
panic!("cannot bump the last segment of a version with less than 3 segment");
}
}
VersionBumpType::Last => {
if segment_count == 0 {
panic!("cannot bump the last segment of a version with no segments");
}
}
}

// Copy over all the segments and bump the last segment.
let segment_count = self.segment_count();
for (idx, segment_iter) in self.segments().enumerate() {
Expand All @@ -247,9 +275,16 @@ impl Version {
let mut segment_components =
segment_iter.components().cloned().collect::<ComponentVec>();

// If this is the last segment of the version bump the last number. Each segment must at
// least start with a number so this should always work.
if idx == (segment_count - 1) {
// Determine whether this is the segment that needs to be bumped.
let is_segment_to_bump = match bump_type {
VersionBumpType::Major => idx == 0,
VersionBumpType::Minor => idx == 1,
VersionBumpType::Patch => idx == 2,
VersionBumpType::Last => idx == (segment_count - 1),
};

// Bump the segment if we need to. Each segment must at least start with a number so this should always work.
if is_segment_to_bump {
let last_numeral_component = segment_components
.iter_mut()
.filter_map(Component::as_number_mut)
Expand Down Expand Up @@ -998,7 +1033,7 @@ mod test {

use rand::seq::SliceRandom;

use crate::version::StrictVersion;
use crate::version::{StrictVersion, VersionBumpType};

use super::Version;

Expand Down Expand Up @@ -1202,17 +1237,23 @@ mod test {
}

#[test]
fn bump() {
fn bump_last() {
assert_eq!(
Version::from_str("1.1").unwrap().bump(),
Version::from_str("1.1")
.unwrap()
.bump(VersionBumpType::Last),
Version::from_str("1.2").unwrap()
);
assert_eq!(
Version::from_str("1.1l").unwrap().bump(),
Version::from_str("1.1l")
.unwrap()
.bump(VersionBumpType::Last),
Version::from_str("1.2l").unwrap()
);
assert_eq!(
Version::from_str("5!1.alpha+3.4").unwrap().bump(),
Version::from_str("5!1.alpha+3.4")
.unwrap()
.bump(VersionBumpType::Last),
Version::from_str("5!1.1alpha+3.4").unwrap()
);
}
Expand Down Expand Up @@ -1347,4 +1388,97 @@ mod test {
Version::from_str("3!4.5a.6b").unwrap()
);
}

#[test]
fn bump_dev() {
let version = Version::from_str("5!1.alpha+3.4").unwrap();
hadim marked this conversation as resolved.
Show resolved Hide resolved

println!("****************");
println!("components: {:?}", version.components);
println!("flags: {:?}", version.flags);
println!("segments: {:#?}", version.segments);
println!("****************");
}

#[test]
fn bump_major() {
assert_eq!(
Version::from_str("1.1")
.unwrap()
.bump(VersionBumpType::Major),
Version::from_str("2.1").unwrap()
);
assert_eq!(
Version::from_str("2.1l")
.unwrap()
.bump(VersionBumpType::Major),
Version::from_str("3.1l").unwrap()
);
assert_eq!(
Version::from_str("5!1.alpha+3.4")
.unwrap()
.bump(VersionBumpType::Major),
Version::from_str("5!2.alpha+3.4").unwrap()
);
}

#[test]
fn bump_minor() {
assert_eq!(
Version::from_str("1.1")
.unwrap()
.bump(VersionBumpType::Minor),
Version::from_str("1.2").unwrap()
);
assert_eq!(
Version::from_str("2.1l")
.unwrap()
.bump(VersionBumpType::Minor),
Version::from_str("2.2l").unwrap()
);
assert_eq!(
Version::from_str("5!1.alpha+3.4")
.unwrap()
.bump(VersionBumpType::Minor),
Version::from_str("5!1.1alpha+3.4").unwrap()
);
}

#[test]
#[should_panic(
expected = "cannot bump the minor segment of a version with less than 2 segments"
)]
fn bump_minor_fail() {
Version::from_str("1").unwrap().bump(VersionBumpType::Minor);
}

#[test]
fn bump_patch() {
assert_eq!(
Version::from_str("1.1.9")
.unwrap()
.bump(VersionBumpType::Patch),
Version::from_str("1.1.10").unwrap()
);
assert_eq!(
Version::from_str("2.1l.5alpha")
.unwrap()
.bump(VersionBumpType::Patch),
Version::from_str("2.1l.6alpha").unwrap()
);
assert_eq!(
Version::from_str("5!1.8.alpha+3.4")
.unwrap()
.bump(VersionBumpType::Patch),
Version::from_str("5!1.8.1alpha+3.4").unwrap()
);
}

#[test]
#[should_panic(expected = "cannot bump the last segment of a version with less than 3 segment")]
fn bump_patch_fail() {
Version::from_str("1.3")
.unwrap()
.bump(VersionBumpType::Patch);
}
}
Loading