From d815fb13b479332490058fff6f18a6bd42de2bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Fri, 29 Dec 2023 23:42:51 +0300 Subject: [PATCH 01/17] feat(next_version): support configuration --- crates/next_version/src/config.rs | 26 ++++++++++++++ crates/next_version/src/lib.rs | 3 +- crates/next_version/src/next_version.rs | 8 ++--- crates/next_version/src/version_increment.rs | 38 ++++++++++++++++---- 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 crates/next_version/src/config.rs diff --git a/crates/next_version/src/config.rs b/crates/next_version/src/config.rs new file mode 100644 index 0000000000..4d4fe6bc52 --- /dev/null +++ b/crates/next_version/src/config.rs @@ -0,0 +1,26 @@ +/// Configuration for version incrementation rules. +#[derive(Debug)] +pub struct NextVersionConfig { + /// Indicates whether uncontrolled minor version bumps are enabled. + /// When false, minor version increments are not performed and they + /// should be manually done to signal higher API stability to the user. + /// + /// Default value is `false`. + pub uncontrolled_minor_bump: bool, + + /// Indicates whether initial major version increments are enabled. + /// When true, allows for a major version increment from 0 to 1, + /// indicating a breaking change in the API. + /// + /// Default value is `false`. + pub initial_major_increment: bool, +} + +impl Default for NextVersionConfig { + fn default() -> Self { + NextVersionConfig { + uncontrolled_minor_bump: true, + initial_major_increment: false, + } + } +} diff --git a/crates/next_version/src/lib.rs b/crates/next_version/src/lib.rs index fccbb58d1a..43a86d1679 100644 --- a/crates/next_version/src/lib.rs +++ b/crates/next_version/src/lib.rs @@ -130,7 +130,8 @@ //! assert_eq!(version.next(commits.clone()), expected); //! ``` +mod config; mod next_version; mod version_increment; -pub use crate::{next_version::*, version_increment::*}; +pub use crate::{config::NextVersionConfig, next_version::*, version_increment::*}; diff --git a/crates/next_version/src/next_version.rs b/crates/next_version/src/next_version.rs index 8fbf8f6c1c..db2f5659f6 100644 --- a/crates/next_version/src/next_version.rs +++ b/crates/next_version/src/next_version.rs @@ -1,9 +1,9 @@ use semver::Version; -use crate::VersionIncrement; +use crate::{NextVersionConfig, VersionIncrement}; pub trait NextVersion { - fn next(&self, commits: I) -> Self + fn next(&self, commits: I, config: Option) -> Self where I: IntoIterator, I::Item: AsRef; @@ -36,12 +36,12 @@ impl NextVersion for Version { /// let version = Version::new(0, 3, 3); /// assert_eq!(version.next(commits), Version::new(0, 3, 4)); /// ``` - fn next(&self, commits: I) -> Self + fn next(&self, commits: I, config: Option) -> Self where I: IntoIterator, I::Item: AsRef, { - let increment = VersionIncrement::from_commits(self, commits); + let increment = VersionIncrement::from_commits(self, commits, config); match increment { Some(increment) => increment.bump(self), None => self.clone(), diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 4a34c3da72..afd7bb6c77 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -1,7 +1,7 @@ use conventional_commit_parser::commit::{CommitType, ConventionalCommit}; use semver::Version; -use crate::NextVersion; +use crate::{NextVersion, NextVersionConfig}; #[derive(Debug, PartialEq, Eq)] pub enum VersionIncrement { @@ -22,7 +22,11 @@ impl VersionIncrement { /// the version increment is [`VersionIncrement::Patch`]. /// - If some commits match conventional commits, then the next version is calculated by using /// [these](https://www.conventionalcommits.org/en/v1.0.0/#how-does-this-relate-to-semverare) rules. - pub fn from_commits(current_version: &Version, commits: I) -> Option + pub fn from_commits( + current_version: &Version, + commits: I, + config: Option, + ) -> Option where I: IntoIterator, I::Item: AsRef, @@ -40,7 +44,11 @@ impl VersionIncrement { .filter_map(|c| conventional_commit_parser::parse(c.as_ref()).ok()) .collect(); - Some(Self::from_conventional_commits(current_version, &commits)) + Some(Self::from_conventional_commits( + current_version, + &commits, + config, + )) } } @@ -71,7 +79,13 @@ impl VersionIncrement { } /// If no conventional commits are present, the version is incremented as a Patch - fn from_conventional_commits(current: &Version, commits: &[ConventionalCommit]) -> Self { + fn from_conventional_commits( + current: &Version, + commits: &[ConventionalCommit], + config: Option, + ) -> Self { + let config = config.unwrap_or_default(); + let is_there_a_feature = || { commits .iter() @@ -80,11 +94,21 @@ impl VersionIncrement { let is_there_a_breaking_change = || commits.iter().any(|commit| commit.is_breaking_change); - let is_major_bump = || current.major != 0 && is_there_a_breaking_change(); + let is_major_bump = || { + if config.initial_major_increment { + is_there_a_breaking_change() + } else { + current.major != 0 && is_there_a_breaking_change() + } + }; let is_minor_bump = || { - (current.major != 0 && is_there_a_feature()) - || (current.major == 0 && current.minor != 0 && is_there_a_breaking_change()) + if !config.uncontrolled_minor_bump { + (current.major != 0 && is_there_a_feature()) + || (current.major == 0 && current.minor != 0 && is_there_a_breaking_change()) + } else { + (is_there_a_feature()) || (current.minor != 0 && is_there_a_breaking_change()) + } }; if is_major_bump() { From c26f54f7c6d5e3cc4b5a0f671d300199b565a17c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Sat, 30 Dec 2023 00:08:59 +0300 Subject: [PATCH 02/17] test(next_version): update tests for configuration --- crates/next_version/src/config.rs | 2 +- crates/next_version/tests/all/normal.rs | 51 +++++++++++++++++--- crates/next_version/tests/all/pre_release.rs | 10 ++-- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/crates/next_version/src/config.rs b/crates/next_version/src/config.rs index 4d4fe6bc52..19d38a6b4d 100644 --- a/crates/next_version/src/config.rs +++ b/crates/next_version/src/config.rs @@ -19,7 +19,7 @@ pub struct NextVersionConfig { impl Default for NextVersionConfig { fn default() -> Self { NextVersionConfig { - uncontrolled_minor_bump: true, + uncontrolled_minor_bump: false, initial_major_increment: false, } } diff --git a/crates/next_version/tests/all/normal.rs b/crates/next_version/tests/all/normal.rs index 855cabd16a..94c8fb9735 100644 --- a/crates/next_version/tests/all/normal.rs +++ b/crates/next_version/tests/all/normal.rs @@ -1,37 +1,76 @@ -use next_version::NextVersion; +use next_version::{NextVersion, NextVersionConfig}; use semver::Version; #[test] fn commit_without_semver_prefix_increments_patch_version() { let commits = vec!["my change"]; let version = Version::new(1, 2, 3); - assert_eq!(version.next(commits), Version::new(1, 2, 4)); + assert_eq!(version.next(commits, None), Version::new(1, 2, 4)); } #[test] fn commit_with_fix_semver_prefix_increments_patch_version() { let commits = vec!["my change", "fix: serious bug"]; let version = Version::new(1, 2, 3); - assert_eq!(version.next(commits), Version::new(1, 2, 4)); + assert_eq!(version.next(commits, None), Version::new(1, 2, 4)); } #[test] fn commit_with_feat_semver_prefix_increments_patch_version() { let commits = vec!["feat: make coffe"]; let version = Version::new(1, 3, 3); - assert_eq!(version.next(commits), Version::new(1, 4, 0)); + assert_eq!(version.next(commits, None), Version::new(1, 4, 0)); +} + +#[test] +fn commit_with_feat_semver_prefix_increments_patch_version_when_major_is_zero() { + let commits = vec!["feat: make coffee"]; + let version = Version::new(0, 2, 3); + assert_eq!(version.next(commits, None), Version::new(0, 2, 4)); +} + +#[test] +fn commit_with_feat_semver_prefix_increments_minor_version_when_major_is_zero() { + let commits = vec!["feat: make coffee"]; + let version = Version::new(0, 2, 3); + assert_eq!( + version.next( + commits, + Some(NextVersionConfig { + uncontrolled_minor_bump: true, + initial_major_increment: false + }) + ), + Version::new(0, 3, 0) + ); } #[test] fn commit_with_breaking_change_increments_major_version() { let commits = vec!["feat!: break user"]; let version = Version::new(1, 2, 3); - assert_eq!(version.next(commits), Version::new(2, 0, 0)); + assert_eq!(version.next(commits, None), Version::new(2, 0, 0)); } #[test] fn commit_with_breaking_change_increments_minor_version_when_major_is_zero() { let commits = vec!["feat!: break user"]; let version = Version::new(0, 2, 3); - assert_eq!(version.next(commits), Version::new(0, 3, 0)); + assert_eq!(version.next(commits, None), Version::new(0, 3, 0)); +} + +#[test] +fn commit_with_breaking_change_increments_major_version_when_major_is_zero() { + let commits = vec!["feat!: break user"]; + let version = Version::new(0, 2, 3); + assert_eq!( + version.next( + commits, + Some(NextVersionConfig { + uncontrolled_minor_bump: false, + initial_major_increment: true + }) + ), + Version::new(1, 0, 0) + ); } diff --git a/crates/next_version/tests/all/pre_release.rs b/crates/next_version/tests/all/pre_release.rs index 8a77ef1fc6..66fadeda80 100644 --- a/crates/next_version/tests/all/pre_release.rs +++ b/crates/next_version/tests/all/pre_release.rs @@ -6,7 +6,7 @@ fn commit_without_semver_prefix_increments_pre_release_version() { let commits = vec!["my change"]; let version = Version::parse("1.0.0-alpha.2").unwrap(); let expected = Version::parse("1.0.0-alpha.3").unwrap(); - assert_eq!(version.next(commits), expected); + assert_eq!(version.next(commits, None), expected); } #[test] @@ -14,7 +14,7 @@ fn commit_with_breaking_change_increments_pre_release_version() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-alpha.2").unwrap(); let expected = Version::parse("1.0.0-alpha.3").unwrap(); - assert_eq!(version.next(commits), expected); + assert_eq!(version.next(commits, None), expected); } #[test] @@ -22,7 +22,7 @@ fn dot_1_is_added_to_unversioned_pre_release() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-alpha").unwrap(); let expected = Version::parse("1.0.0-alpha.1").unwrap(); - assert_eq!(version.next(commits), expected); + assert_eq!(version.next(commits, None), expected); } #[test] @@ -30,7 +30,7 @@ fn dot_1_is_added_to_last_identifier_in_pre_release() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-beta.1.2").unwrap(); let expected = Version::parse("1.0.0-beta.1.3").unwrap(); - assert_eq!(version.next(commits), expected); + assert_eq!(version.next(commits, None), expected); } #[test] @@ -38,5 +38,5 @@ fn dot_1_is_added_to_character_identifier_in_pre_release() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-beta.1.a").unwrap(); let expected = Version::parse("1.0.0-beta.1.a.1").unwrap(); - assert_eq!(version.next(commits), expected); + assert_eq!(version.next(commits, None), expected); } From d3d3fb07cec3e519999dd43428a4ffc4171e33ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Sat, 30 Dec 2023 02:03:20 +0300 Subject: [PATCH 03/17] refactor(next_version): use builder lite pattern --- crates/next_version/src/config.rs | 26 ------- crates/next_version/src/lib.rs | 4 +- crates/next_version/src/next_version.rs | 12 +-- crates/next_version/src/version_increment.rs | 14 ++-- crates/next_version/src/version_updater.rs | 77 ++++++++++++++++++++ crates/next_version/tests/all/normal.rs | 36 ++++----- crates/next_version/tests/all/pre_release.rs | 10 +-- 7 files changed, 109 insertions(+), 70 deletions(-) delete mode 100644 crates/next_version/src/config.rs create mode 100644 crates/next_version/src/version_updater.rs diff --git a/crates/next_version/src/config.rs b/crates/next_version/src/config.rs deleted file mode 100644 index 19d38a6b4d..0000000000 --- a/crates/next_version/src/config.rs +++ /dev/null @@ -1,26 +0,0 @@ -/// Configuration for version incrementation rules. -#[derive(Debug)] -pub struct NextVersionConfig { - /// Indicates whether uncontrolled minor version bumps are enabled. - /// When false, minor version increments are not performed and they - /// should be manually done to signal higher API stability to the user. - /// - /// Default value is `false`. - pub uncontrolled_minor_bump: bool, - - /// Indicates whether initial major version increments are enabled. - /// When true, allows for a major version increment from 0 to 1, - /// indicating a breaking change in the API. - /// - /// Default value is `false`. - pub initial_major_increment: bool, -} - -impl Default for NextVersionConfig { - fn default() -> Self { - NextVersionConfig { - uncontrolled_minor_bump: false, - initial_major_increment: false, - } - } -} diff --git a/crates/next_version/src/lib.rs b/crates/next_version/src/lib.rs index 43a86d1679..dd287afded 100644 --- a/crates/next_version/src/lib.rs +++ b/crates/next_version/src/lib.rs @@ -130,8 +130,8 @@ //! assert_eq!(version.next(commits.clone()), expected); //! ``` -mod config; mod next_version; mod version_increment; +mod version_updater; -pub use crate::{config::NextVersionConfig, next_version::*, version_increment::*}; +pub use crate::{next_version::*, version_increment::*, version_updater::*}; diff --git a/crates/next_version/src/next_version.rs b/crates/next_version/src/next_version.rs index db2f5659f6..af92d7186c 100644 --- a/crates/next_version/src/next_version.rs +++ b/crates/next_version/src/next_version.rs @@ -1,9 +1,9 @@ use semver::Version; -use crate::{NextVersionConfig, VersionIncrement}; +use crate::VersionUpdater; pub trait NextVersion { - fn next(&self, commits: I, config: Option) -> Self + fn next(&self, commits: I) -> Self where I: IntoIterator, I::Item: AsRef; @@ -36,16 +36,12 @@ impl NextVersion for Version { /// let version = Version::new(0, 3, 3); /// assert_eq!(version.next(commits), Version::new(0, 3, 4)); /// ``` - fn next(&self, commits: I, config: Option) -> Self + fn next(&self, commits: I) -> Self where I: IntoIterator, I::Item: AsRef, { - let increment = VersionIncrement::from_commits(self, commits, config); - match increment { - Some(increment) => increment.bump(self), - None => self.clone(), - } + VersionUpdater::default().next(self, commits) } // taken from https://github.com/killercup/cargo-edit/blob/643e9253a84db02c52a7fa94f07d786d281362ab/src/version.rs#L38 diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index afd7bb6c77..4f35d8b4b8 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -1,7 +1,7 @@ use conventional_commit_parser::commit::{CommitType, ConventionalCommit}; use semver::Version; -use crate::{NextVersion, NextVersionConfig}; +use crate::{NextVersion, VersionUpdater}; #[derive(Debug, PartialEq, Eq)] pub enum VersionIncrement { @@ -23,9 +23,9 @@ impl VersionIncrement { /// - If some commits match conventional commits, then the next version is calculated by using /// [these](https://www.conventionalcommits.org/en/v1.0.0/#how-does-this-relate-to-semverare) rules. pub fn from_commits( + updater: &VersionUpdater, current_version: &Version, commits: I, - config: Option, ) -> Option where I: IntoIterator, @@ -47,7 +47,7 @@ impl VersionIncrement { Some(Self::from_conventional_commits( current_version, &commits, - config, + updater, )) } } @@ -82,10 +82,8 @@ impl VersionIncrement { fn from_conventional_commits( current: &Version, commits: &[ConventionalCommit], - config: Option, + updater: &VersionUpdater, ) -> Self { - let config = config.unwrap_or_default(); - let is_there_a_feature = || { commits .iter() @@ -95,7 +93,7 @@ impl VersionIncrement { let is_there_a_breaking_change = || commits.iter().any(|commit| commit.is_breaking_change); let is_major_bump = || { - if config.initial_major_increment { + if updater.breaking_always_increment_major { is_there_a_breaking_change() } else { current.major != 0 && is_there_a_breaking_change() @@ -103,7 +101,7 @@ impl VersionIncrement { }; let is_minor_bump = || { - if !config.uncontrolled_minor_bump { + if !updater.features_always_increment_minor { (current.major != 0 && is_there_a_feature()) || (current.major == 0 && current.minor != 0 && is_there_a_breaking_change()) } else { diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs new file mode 100644 index 0000000000..1734b9fa20 --- /dev/null +++ b/crates/next_version/src/version_updater.rs @@ -0,0 +1,77 @@ +use semver::Version; + +use crate::VersionIncrement; + +/// Represents a version updater configuration. +/// +/// This struct allows controlling version increments based on certain settings. +/// +// # Example +/// +/// ``` +/// use next_version::VersionUpdater; +/// use semver::Version; +/// +/// let updated_version = VersionUpdater::new() +/// .with_features_always_increment_minor(false) +/// .with_breaking_always_increment_major(true) +/// .next(&Version::new(1, 2, 3), vec!["feat: commit 1", "fix: commit 2"]); +/// +/// println!("Updated version: {:?}", updated_version); +/// ``` +#[derive(Debug, Default)] +pub struct VersionUpdater { + pub(crate) features_always_increment_minor: bool, + pub(crate) breaking_always_increment_major: bool, +} + +impl VersionUpdater { + /// Constructs a new instance with default settings. + /// + /// Both minor version increments for feature changes and initial major version + /// increments for breaking changes are disabled (set to `false`). + pub fn new() -> Self { + Self { + features_always_increment_minor: false, + breaking_always_increment_major: false, + } + } + + /// Configures automatic minor version increments for feature changes. + /// + /// When `true` is passed, it enables automatic minor version increments for feature changes. + /// This means that any introduced feature will trigger a minor version update. + pub fn with_features_always_increment_minor( + mut self, + features_always_increment_minor: bool, + ) -> Self { + self.features_always_increment_minor = features_always_increment_minor; + self + } + + /// Configures initial major version increments for breaking changes. + /// + /// When `true` is passed, it enables the initial major version increment + /// for breaking changes. This implies that the transition from version 0 to 1 + /// will be triggered by a breaking change in the API. + pub fn with_breaking_always_increment_major( + mut self, + breaking_always_increment_major: bool, + ) -> Self { + self.breaking_always_increment_major = breaking_always_increment_major; + self + } + + /// Analyze commits and determine the next version. + pub fn next(self, version: &Version, commits: I) -> Version + where + I: IntoIterator, + I::Item: AsRef, + { + let increment = VersionIncrement::from_commits(&self, version, commits); + match increment { + Some(increment) => increment.bump(version), + None => version.clone(), + } + } +} diff --git a/crates/next_version/tests/all/normal.rs b/crates/next_version/tests/all/normal.rs index 94c8fb9735..92d1394dfe 100644 --- a/crates/next_version/tests/all/normal.rs +++ b/crates/next_version/tests/all/normal.rs @@ -1,32 +1,32 @@ -use next_version::{NextVersion, NextVersionConfig}; +use next_version::{NextVersion, VersionUpdater}; use semver::Version; #[test] fn commit_without_semver_prefix_increments_patch_version() { let commits = vec!["my change"]; let version = Version::new(1, 2, 3); - assert_eq!(version.next(commits, None), Version::new(1, 2, 4)); + assert_eq!(version.next(commits), Version::new(1, 2, 4)); } #[test] fn commit_with_fix_semver_prefix_increments_patch_version() { let commits = vec!["my change", "fix: serious bug"]; let version = Version::new(1, 2, 3); - assert_eq!(version.next(commits, None), Version::new(1, 2, 4)); + assert_eq!(version.next(commits), Version::new(1, 2, 4)); } #[test] fn commit_with_feat_semver_prefix_increments_patch_version() { let commits = vec!["feat: make coffe"]; let version = Version::new(1, 3, 3); - assert_eq!(version.next(commits, None), Version::new(1, 4, 0)); + assert_eq!(version.next(commits), Version::new(1, 4, 0)); } #[test] fn commit_with_feat_semver_prefix_increments_patch_version_when_major_is_zero() { let commits = vec!["feat: make coffee"]; let version = Version::new(0, 2, 3); - assert_eq!(version.next(commits, None), Version::new(0, 2, 4)); + assert_eq!(version.next(commits), Version::new(0, 2, 4)); } #[test] @@ -34,13 +34,10 @@ fn commit_with_feat_semver_prefix_increments_minor_version_when_major_is_zero() let commits = vec!["feat: make coffee"]; let version = Version::new(0, 2, 3); assert_eq!( - version.next( - commits, - Some(NextVersionConfig { - uncontrolled_minor_bump: true, - initial_major_increment: false - }) - ), + VersionUpdater::new() + .with_features_always_increment_minor(true) + .with_breaking_always_increment_major(false) + .next(&version, commits), Version::new(0, 3, 0) ); } @@ -49,14 +46,14 @@ fn commit_with_feat_semver_prefix_increments_minor_version_when_major_is_zero() fn commit_with_breaking_change_increments_major_version() { let commits = vec!["feat!: break user"]; let version = Version::new(1, 2, 3); - assert_eq!(version.next(commits, None), Version::new(2, 0, 0)); + assert_eq!(version.next(commits), Version::new(2, 0, 0)); } #[test] fn commit_with_breaking_change_increments_minor_version_when_major_is_zero() { let commits = vec!["feat!: break user"]; let version = Version::new(0, 2, 3); - assert_eq!(version.next(commits, None), Version::new(0, 3, 0)); + assert_eq!(version.next(commits), Version::new(0, 3, 0)); } #[test] @@ -64,13 +61,10 @@ fn commit_with_breaking_change_increments_major_version_when_major_is_zero() { let commits = vec!["feat!: break user"]; let version = Version::new(0, 2, 3); assert_eq!( - version.next( - commits, - Some(NextVersionConfig { - uncontrolled_minor_bump: false, - initial_major_increment: true - }) - ), + VersionUpdater::new() + .with_features_always_increment_minor(false) + .with_breaking_always_increment_major(true) + .next(&version, commits), Version::new(1, 0, 0) ); } diff --git a/crates/next_version/tests/all/pre_release.rs b/crates/next_version/tests/all/pre_release.rs index 66fadeda80..8a77ef1fc6 100644 --- a/crates/next_version/tests/all/pre_release.rs +++ b/crates/next_version/tests/all/pre_release.rs @@ -6,7 +6,7 @@ fn commit_without_semver_prefix_increments_pre_release_version() { let commits = vec!["my change"]; let version = Version::parse("1.0.0-alpha.2").unwrap(); let expected = Version::parse("1.0.0-alpha.3").unwrap(); - assert_eq!(version.next(commits, None), expected); + assert_eq!(version.next(commits), expected); } #[test] @@ -14,7 +14,7 @@ fn commit_with_breaking_change_increments_pre_release_version() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-alpha.2").unwrap(); let expected = Version::parse("1.0.0-alpha.3").unwrap(); - assert_eq!(version.next(commits, None), expected); + assert_eq!(version.next(commits), expected); } #[test] @@ -22,7 +22,7 @@ fn dot_1_is_added_to_unversioned_pre_release() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-alpha").unwrap(); let expected = Version::parse("1.0.0-alpha.1").unwrap(); - assert_eq!(version.next(commits, None), expected); + assert_eq!(version.next(commits), expected); } #[test] @@ -30,7 +30,7 @@ fn dot_1_is_added_to_last_identifier_in_pre_release() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-beta.1.2").unwrap(); let expected = Version::parse("1.0.0-beta.1.3").unwrap(); - assert_eq!(version.next(commits, None), expected); + assert_eq!(version.next(commits), expected); } #[test] @@ -38,5 +38,5 @@ fn dot_1_is_added_to_character_identifier_in_pre_release() { let commits = vec!["feat!: break user"]; let version = Version::parse("1.0.0-beta.1.a").unwrap(); let expected = Version::parse("1.0.0-beta.1.a.1").unwrap(); - assert_eq!(version.next(commits, None), expected); + assert_eq!(version.next(commits), expected); } From d53cd3c44c73246062ed20502436055fdfa865d8 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:19:50 +0100 Subject: [PATCH 04/17] flip condition --- crates/next_version/src/version_increment.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 4f35d8b4b8..13109a0f94 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -101,11 +101,11 @@ impl VersionIncrement { }; let is_minor_bump = || { - if !updater.features_always_increment_minor { + if updater.features_always_increment_minor { + is_there_a_feature() || (current.minor != 0 && is_there_a_breaking_change()) + } else { (current.major != 0 && is_there_a_feature()) || (current.major == 0 && current.minor != 0 && is_there_a_breaking_change()) - } else { - (is_there_a_feature()) || (current.minor != 0 && is_there_a_breaking_change()) } }; From e4e04cd2511ef823bd68aa31cece9967d45ef9a5 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:27:18 +0100 Subject: [PATCH 05/17] simpler boolean logic --- crates/next_version/src/version_increment.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 13109a0f94..14d26e2e5f 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -93,11 +93,8 @@ impl VersionIncrement { let is_there_a_breaking_change = || commits.iter().any(|commit| commit.is_breaking_change); let is_major_bump = || { - if updater.breaking_always_increment_major { - is_there_a_breaking_change() - } else { - current.major != 0 && is_there_a_breaking_change() - } + is_there_a_breaking_change() + && (current.major != 0 || updater.breaking_always_increment_major) }; let is_minor_bump = || { From 5b803c7439d91c82cf13cc6dc60718509cef3814 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:33:53 +0100 Subject: [PATCH 06/17] simplify logic --- crates/next_version/src/version_increment.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 14d26e2e5f..9182d79d41 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -98,12 +98,13 @@ impl VersionIncrement { }; let is_minor_bump = || { - if updater.features_always_increment_minor { - is_there_a_feature() || (current.minor != 0 && is_there_a_breaking_change()) - } else { - (current.major != 0 && is_there_a_feature()) - || (current.major == 0 && current.minor != 0 && is_there_a_breaking_change()) - } + let is_feat_bump = || { + is_there_a_feature() + && (current.major != 0 || updater.features_always_increment_minor) + }; + let is_breaking_bump = + || current.major == 0 && current.minor != 0 && is_there_a_breaking_change(); + is_feat_bump() || is_breaking_bump() }; if is_major_bump() { From 9b3cc3487e45e200c3d26daa4f17b95b5b2199aa Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:38:41 +0100 Subject: [PATCH 07/17] change closure to variable --- crates/next_version/src/version_increment.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 9182d79d41..02db165285 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -90,10 +90,10 @@ impl VersionIncrement { .any(|commit| commit.commit_type == CommitType::Feature) }; - let is_there_a_breaking_change = || commits.iter().any(|commit| commit.is_breaking_change); + let is_there_a_breaking_change = commits.iter().any(|commit| commit.is_breaking_change); let is_major_bump = || { - is_there_a_breaking_change() + is_there_a_breaking_change && (current.major != 0 || updater.breaking_always_increment_major) }; @@ -103,7 +103,7 @@ impl VersionIncrement { && (current.major != 0 || updater.features_always_increment_minor) }; let is_breaking_bump = - || current.major == 0 && current.minor != 0 && is_there_a_breaking_change(); + || current.major == 0 && current.minor != 0 && is_there_a_breaking_change; is_feat_bump() || is_breaking_bump() }; From 142aef0d2a6b95efb7eac49f28da89c985c10454 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:41:01 +0100 Subject: [PATCH 08/17] use assert in example --- crates/next_version/src/version_updater.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs index 1734b9fa20..f190f257e6 100644 --- a/crates/next_version/src/version_updater.rs +++ b/crates/next_version/src/version_updater.rs @@ -17,7 +17,7 @@ use crate::VersionIncrement; /// .with_breaking_always_increment_major(true) /// .next(&Version::new(1, 2, 3), vec!["feat: commit 1", "fix: commit 2"]); /// -/// println!("Updated version: {:?}", updated_version); +/// assert_eq!(Version::new(1, 3, 0), updated_version); /// ``` #[derive(Debug, Default)] pub struct VersionUpdater { From fb1ca178e525d4ad8bb416f4f749a261b2acc966 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:43:06 +0100 Subject: [PATCH 09/17] docs --- crates/next_version/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/next_version/src/lib.rs b/crates/next_version/src/lib.rs index dd287afded..519b0d9fc6 100644 --- a/crates/next_version/src/lib.rs +++ b/crates/next_version/src/lib.rs @@ -129,6 +129,11 @@ //! let expected = Version::parse("1.0.1+abcd").unwrap(); //! assert_eq!(version.next(commits.clone()), expected); //! ``` +//! +//! # Custom version increment +//! +//! If you don't like the default increment rules of the crate, +//! you can customize them by using the [`VersionUpdater`] struct. mod next_version; mod version_increment; From c595f9a2931859d415a40007948f735c8fbd97f1 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:01:44 +0100 Subject: [PATCH 10/17] avoid breaking change --- crates/next_version/src/next_version.rs | 2 +- crates/next_version/src/version_increment.rs | 12 ++++++++++++ crates/next_version/src/version_updater.rs | 12 +++++++++--- crates/next_version/tests/all/normal.rs | 4 ++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/crates/next_version/src/next_version.rs b/crates/next_version/src/next_version.rs index af92d7186c..4d96eeb8fb 100644 --- a/crates/next_version/src/next_version.rs +++ b/crates/next_version/src/next_version.rs @@ -41,7 +41,7 @@ impl NextVersion for Version { I: IntoIterator, I::Item: AsRef, { - VersionUpdater::default().next(self, commits) + VersionUpdater::default().increment(self, commits) } // taken from https://github.com/killercup/cargo-edit/blob/643e9253a84db02c52a7fa94f07d786d281362ab/src/version.rs#L38 diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 02db165285..73e533009a 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -23,6 +23,18 @@ impl VersionIncrement { /// - If some commits match conventional commits, then the next version is calculated by using /// [these](https://www.conventionalcommits.org/en/v1.0.0/#how-does-this-relate-to-semverare) rules. pub fn from_commits( + current_version: &Version, + commits: I, + ) -> Option + where + I: IntoIterator, + I::Item: AsRef, + { + let updater = VersionUpdater::default(); + Self::from_commits_with_updater(&updater, current_version, commits) + } + + pub(crate) fn from_commits_with_updater( updater: &VersionUpdater, current_version: &Version, commits: I, diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs index f190f257e6..677fc3ec24 100644 --- a/crates/next_version/src/version_updater.rs +++ b/crates/next_version/src/version_updater.rs @@ -19,12 +19,18 @@ use crate::VersionIncrement; /// /// assert_eq!(Version::new(1, 3, 0), updated_version); /// ``` -#[derive(Debug, Default)] +#[derive(Debug)] pub struct VersionUpdater { pub(crate) features_always_increment_minor: bool, pub(crate) breaking_always_increment_major: bool, } +impl Default for VersionUpdater { + fn default() -> Self { + Self::new() + } +} + impl VersionUpdater { /// Constructs a new instance with default settings. /// @@ -63,12 +69,12 @@ impl VersionUpdater { } /// Analyze commits and determine the next version. - pub fn next(self, version: &Version, commits: I) -> Version + pub fn increment(self, version: &Version, commits: I) -> Version where I: IntoIterator, I::Item: AsRef, { - let increment = VersionIncrement::from_commits(&self, version, commits); + let increment = VersionIncrement::from_commits_with_updater(&self, version, commits); match increment { Some(increment) => increment.bump(version), None => version.clone(), diff --git a/crates/next_version/tests/all/normal.rs b/crates/next_version/tests/all/normal.rs index 92d1394dfe..3346bcd69e 100644 --- a/crates/next_version/tests/all/normal.rs +++ b/crates/next_version/tests/all/normal.rs @@ -37,7 +37,7 @@ fn commit_with_feat_semver_prefix_increments_minor_version_when_major_is_zero() VersionUpdater::new() .with_features_always_increment_minor(true) .with_breaking_always_increment_major(false) - .next(&version, commits), + .increment(&version, commits), Version::new(0, 3, 0) ); } @@ -64,7 +64,7 @@ fn commit_with_breaking_change_increments_major_version_when_major_is_zero() { VersionUpdater::new() .with_features_always_increment_minor(false) .with_breaking_always_increment_major(true) - .next(&version, commits), + .increment(&version, commits), Version::new(1, 0, 0) ); } From 1d11e183ca74f2292d0f3e5e70116a8ef79c968f Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:02:08 +0100 Subject: [PATCH 11/17] fix docs --- crates/next_version/src/version_updater.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs index 677fc3ec24..3069d76399 100644 --- a/crates/next_version/src/version_updater.rs +++ b/crates/next_version/src/version_updater.rs @@ -15,7 +15,7 @@ use crate::VersionIncrement; /// let updated_version = VersionUpdater::new() /// .with_features_always_increment_minor(false) /// .with_breaking_always_increment_major(true) -/// .next(&Version::new(1, 2, 3), vec!["feat: commit 1", "fix: commit 2"]); +/// .increment(&Version::new(1, 2, 3), vec!["feat: commit 1", "fix: commit 2"]); /// /// assert_eq!(Version::new(1, 3, 0), updated_version); /// ``` From 2474fa31d5f40970d77373a385717ec39ef2e6fe Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:04:05 +0100 Subject: [PATCH 12/17] fmt --- crates/next_version/src/version_increment.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/next_version/src/version_increment.rs b/crates/next_version/src/version_increment.rs index 73e533009a..eab3aa3fd4 100644 --- a/crates/next_version/src/version_increment.rs +++ b/crates/next_version/src/version_increment.rs @@ -22,10 +22,7 @@ impl VersionIncrement { /// the version increment is [`VersionIncrement::Patch`]. /// - If some commits match conventional commits, then the next version is calculated by using /// [these](https://www.conventionalcommits.org/en/v1.0.0/#how-does-this-relate-to-semverare) rules. - pub fn from_commits( - current_version: &Version, - commits: I, - ) -> Option + pub fn from_commits(current_version: &Version, commits: I) -> Option where I: IntoIterator, I::Item: AsRef, From cc6eb3ede752d142abd48ce4a5d7fa54301496ea Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:05:16 +0100 Subject: [PATCH 13/17] docs --- crates/next_version/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/next_version/src/lib.rs b/crates/next_version/src/lib.rs index 519b0d9fc6..915dfb6036 100644 --- a/crates/next_version/src/lib.rs +++ b/crates/next_version/src/lib.rs @@ -133,7 +133,7 @@ //! # Custom version increment //! //! If you don't like the default increment rules of the crate, -//! you can customize them by using the [`VersionUpdater`] struct. +//! you can customize them by using [`VersionUpdater`]. mod next_version; mod version_increment; From 066e9e9db7f149c0b8d187179ee01c9978cacd76 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:23:29 +0100 Subject: [PATCH 14/17] remove vecs --- crates/next_version/src/lib.rs | 16 ++++++++-------- crates/next_version/src/next_version.rs | 2 +- crates/next_version/tests/all/normal.rs | 16 ++++++++-------- crates/next_version/tests/all/pre_release.rs | 10 +++++----- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/crates/next_version/src/lib.rs b/crates/next_version/src/lib.rs index 915dfb6036..542bdc2e4a 100644 --- a/crates/next_version/src/lib.rs +++ b/crates/next_version/src/lib.rs @@ -13,7 +13,7 @@ //! use semver::Version; //! use next_version::NextVersion; //! -//! let commits = vec!["my change"]; +//! let commits = ["my change"]; //! assert_eq!(Version::new(1, 2, 3).next(commits), Version::new(1, 2, 4)); //! ``` //! @@ -25,10 +25,10 @@ //! use semver::Version; //! use next_version::NextVersion; //! -//! let commits = vec!["my change"]; +//! let commits = ["my change"]; //! assert_eq!(Version::new(0, 0, 4).next(&commits), Version::new(0, 0, 5)); //! -//! let commits = vec!["feat!: break user"]; +//! let commits = ["feat!: break user"]; //! assert_eq!(Version::new(0, 0, 1).next(&commits), Version::new(0, 0, 2)); //! ``` //! @@ -47,7 +47,7 @@ //! use semver::Version; //! use next_version::NextVersion; //! -//! let commits = vec!["my change", "feat: make coffe"]; +//! let commits = ["my change", "feat: make coffe"]; //! assert_eq!(Version::new(1, 2, 4).next(&commits), Version::new(1, 3, 0)); //! //! assert_eq!(Version::new(0, 2, 4).next(&commits), Version::new(0, 2, 5)); @@ -67,7 +67,7 @@ //! use semver::Version; //! use next_version::NextVersion; //! -//! let commits = vec!["feat!: break user"]; +//! let commits = ["feat!: break user"]; //! assert_eq!(Version::new(1, 2, 4).next(&commits), Version::new(2, 0, 0)); //! //! assert_eq!(Version::new(0, 4, 4).next(&commits), Version::new(0, 5, 0)); @@ -87,7 +87,7 @@ //! BREAKING CHANGE: user will be broken //! "#; //! -//! let commits = vec![breaking_commit]; +//! let commits = [breaking_commit]; //! assert_eq!(Version::new(1, 2, 4).next(&commits), Version::new(2, 0, 0)); //! ``` //! @@ -100,7 +100,7 @@ //! use semver::Version; //! use next_version::NextVersion; //! -//! let commits = vec!["feat!: break user"]; +//! let commits = ["feat!: break user"]; //! let version = Version::parse("1.0.0-alpha.1.2").unwrap(); //! let expected = Version::parse("1.0.0-alpha.1.3").unwrap(); //! assert_eq!(version.next(commits.clone()), expected); @@ -120,7 +120,7 @@ //! use semver::Version; //! use next_version::NextVersion; //! -//! let commits = vec!["my change"]; +//! let commits = ["my change"]; //! let version = Version::parse("1.0.0-beta.1+1.1.0").unwrap(); //! let expected = Version::parse("1.0.0-beta.2+1.1.0").unwrap(); //! assert_eq!(version.next(commits.clone()), expected); diff --git a/crates/next_version/src/next_version.rs b/crates/next_version/src/next_version.rs index 4d96eeb8fb..8ab0db9784 100644 --- a/crates/next_version/src/next_version.rs +++ b/crates/next_version/src/next_version.rs @@ -32,7 +32,7 @@ impl NextVersion for Version { /// use next_version::NextVersion; /// use semver::Version; /// - /// let commits = vec!["feat: make coffe"]; + /// let commits = ["feat: make coffe"]; /// let version = Version::new(0, 3, 3); /// assert_eq!(version.next(commits), Version::new(0, 3, 4)); /// ``` diff --git a/crates/next_version/tests/all/normal.rs b/crates/next_version/tests/all/normal.rs index 3346bcd69e..de79d07b5e 100644 --- a/crates/next_version/tests/all/normal.rs +++ b/crates/next_version/tests/all/normal.rs @@ -3,35 +3,35 @@ use semver::Version; #[test] fn commit_without_semver_prefix_increments_patch_version() { - let commits = vec!["my change"]; + let commits = ["my change"]; let version = Version::new(1, 2, 3); assert_eq!(version.next(commits), Version::new(1, 2, 4)); } #[test] fn commit_with_fix_semver_prefix_increments_patch_version() { - let commits = vec!["my change", "fix: serious bug"]; + let commits = ["my change", "fix: serious bug"]; let version = Version::new(1, 2, 3); assert_eq!(version.next(commits), Version::new(1, 2, 4)); } #[test] fn commit_with_feat_semver_prefix_increments_patch_version() { - let commits = vec!["feat: make coffe"]; + let commits = ["feat: make coffe"]; let version = Version::new(1, 3, 3); assert_eq!(version.next(commits), Version::new(1, 4, 0)); } #[test] fn commit_with_feat_semver_prefix_increments_patch_version_when_major_is_zero() { - let commits = vec!["feat: make coffee"]; + let commits = ["feat: make coffee"]; let version = Version::new(0, 2, 3); assert_eq!(version.next(commits), Version::new(0, 2, 4)); } #[test] fn commit_with_feat_semver_prefix_increments_minor_version_when_major_is_zero() { - let commits = vec!["feat: make coffee"]; + let commits = ["feat: make coffee"]; let version = Version::new(0, 2, 3); assert_eq!( VersionUpdater::new() @@ -44,21 +44,21 @@ fn commit_with_feat_semver_prefix_increments_minor_version_when_major_is_zero() #[test] fn commit_with_breaking_change_increments_major_version() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::new(1, 2, 3); assert_eq!(version.next(commits), Version::new(2, 0, 0)); } #[test] fn commit_with_breaking_change_increments_minor_version_when_major_is_zero() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::new(0, 2, 3); assert_eq!(version.next(commits), Version::new(0, 3, 0)); } #[test] fn commit_with_breaking_change_increments_major_version_when_major_is_zero() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::new(0, 2, 3); assert_eq!( VersionUpdater::new() diff --git a/crates/next_version/tests/all/pre_release.rs b/crates/next_version/tests/all/pre_release.rs index 8a77ef1fc6..0f2fb62216 100644 --- a/crates/next_version/tests/all/pre_release.rs +++ b/crates/next_version/tests/all/pre_release.rs @@ -3,7 +3,7 @@ use semver::Version; #[test] fn commit_without_semver_prefix_increments_pre_release_version() { - let commits = vec!["my change"]; + let commits = ["my change"]; let version = Version::parse("1.0.0-alpha.2").unwrap(); let expected = Version::parse("1.0.0-alpha.3").unwrap(); assert_eq!(version.next(commits), expected); @@ -11,7 +11,7 @@ fn commit_without_semver_prefix_increments_pre_release_version() { #[test] fn commit_with_breaking_change_increments_pre_release_version() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::parse("1.0.0-alpha.2").unwrap(); let expected = Version::parse("1.0.0-alpha.3").unwrap(); assert_eq!(version.next(commits), expected); @@ -19,7 +19,7 @@ fn commit_with_breaking_change_increments_pre_release_version() { #[test] fn dot_1_is_added_to_unversioned_pre_release() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::parse("1.0.0-alpha").unwrap(); let expected = Version::parse("1.0.0-alpha.1").unwrap(); assert_eq!(version.next(commits), expected); @@ -27,7 +27,7 @@ fn dot_1_is_added_to_unversioned_pre_release() { #[test] fn dot_1_is_added_to_last_identifier_in_pre_release() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::parse("1.0.0-beta.1.2").unwrap(); let expected = Version::parse("1.0.0-beta.1.3").unwrap(); assert_eq!(version.next(commits), expected); @@ -35,7 +35,7 @@ fn dot_1_is_added_to_last_identifier_in_pre_release() { #[test] fn dot_1_is_added_to_character_identifier_in_pre_release() { - let commits = vec!["feat!: break user"]; + let commits = ["feat!: break user"]; let version = Version::parse("1.0.0-beta.1.a").unwrap(); let expected = Version::parse("1.0.0-beta.1.a.1").unwrap(); assert_eq!(version.next(commits), expected); From 69aa18ddf5b0ee4426208286a9a86b7fdf3efe85 Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:24:30 +0100 Subject: [PATCH 15/17] docs --- crates/next_version/src/version_updater.rs | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs index 3069d76399..32423ed4e8 100644 --- a/crates/next_version/src/version_updater.rs +++ b/crates/next_version/src/version_updater.rs @@ -2,9 +2,10 @@ use semver::Version; use crate::VersionIncrement; -/// Represents a version updater configuration. +/// This struct allows to increment a version by +/// specifying a configuration. /// -/// This struct allows controlling version increments based on certain settings. +/// Useful if you don't like the default increment rules of the crate. /// // # Example /// @@ -15,7 +16,7 @@ use crate::VersionIncrement; /// let updated_version = VersionUpdater::new() /// .with_features_always_increment_minor(false) /// .with_breaking_always_increment_major(true) -/// .increment(&Version::new(1, 2, 3), vec!["feat: commit 1", "fix: commit 2"]); +/// .increment(&Version::new(1, 2, 3), ["feat: commit 1", "fix: commit 2"]); /// /// assert_eq!(Version::new(1, 3, 0), updated_version); /// ``` @@ -32,10 +33,23 @@ impl Default for VersionUpdater { } impl VersionUpdater { - /// Constructs a new instance with default settings. + /// Constructs a new instance with default rules of the crate. /// - /// Both minor version increments for feature changes and initial major version - /// increments for breaking changes are disabled (set to `false`). + /// If you don't customize the struct further, it is equivalent to + /// calling [`crate::NextVersion::next`]. + /// + /// ``` + /// use next_version::{NextVersion, VersionUpdater}; + /// use semver::Version; + /// + /// let version = Version::new(1, 2, 3); + /// let commits = ["feat: commit 1", "fix: commit 2"]; + /// let updated_version1 = VersionUpdater::new() + /// .increment(&version, &commits); + /// let updated_version2 = version.next(&commits); + /// + /// assert_eq!(updated_version1, updated_version2); + /// ``` pub fn new() -> Self { Self { features_always_increment_minor: false, @@ -47,6 +61,8 @@ impl VersionUpdater { /// /// When `true` is passed, it enables automatic minor version increments for feature changes. /// This means that any introduced feature will trigger a minor version update. + /// + /// Default: `false` pub fn with_features_always_increment_minor( mut self, features_always_increment_minor: bool, @@ -60,6 +76,8 @@ impl VersionUpdater { /// When `true` is passed, it enables the initial major version increment /// for breaking changes. This implies that the transition from version 0 to 1 /// will be triggered by a breaking change in the API. + /// + /// Default: `false` pub fn with_breaking_always_increment_major( mut self, breaking_always_increment_major: bool, From 00fc07e2beb8a9ceb6e345d34a609b5fd23c637a Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:43:53 +0100 Subject: [PATCH 16/17] docs --- crates/next_version/src/version_updater.rs | 40 +++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs index 32423ed4e8..1c5a35b48c 100644 --- a/crates/next_version/src/version_updater.rs +++ b/crates/next_version/src/version_updater.rs @@ -33,7 +33,7 @@ impl Default for VersionUpdater { } impl VersionUpdater { - /// Constructs a new instance with default rules of the crate. + /// Constructs a new instance with the default rules of the crate. /// /// If you don't customize the struct further, it is equivalent to /// calling [`crate::NextVersion::next`]. @@ -63,6 +63,25 @@ impl VersionUpdater { /// This means that any introduced feature will trigger a minor version update. /// /// Default: `false` + /// + /// ```rust + /// use semver::Version; + /// use next_version::VersionUpdater; + /// + /// let commits = ["feat: make coffee"]; + /// let version = Version::new(0, 2, 3); + /// assert_eq!( + /// VersionUpdater::new() + /// .with_features_always_increment_minor(true) + /// .increment(&version, &commits), + /// Version::new(0, 3, 0) + /// ); + /// assert_eq!( + /// VersionUpdater::new() + /// .increment(&version, &commits), + /// Version::new(0, 2, 4) + /// ); + /// ``` pub fn with_features_always_increment_minor( mut self, features_always_increment_minor: bool, @@ -78,6 +97,25 @@ impl VersionUpdater { /// will be triggered by a breaking change in the API. /// /// Default: `false` + /// + /// ```rust + /// use semver::Version; + /// use next_version::VersionUpdater; + /// + /// let commits = ["feat!: incompatible change"]; + /// let version = Version::new(0, 2, 3); + /// assert_eq!( + /// VersionUpdater::new() + /// .with_breaking_always_increment_major(true) + /// .increment(&version, &commits), + /// Version::new(1, 0, 0) + /// ); + /// assert_eq!( + /// VersionUpdater::new() + /// .increment(&version, &commits), + /// Version::new(0, 3, 0) + /// ); + /// ``` pub fn with_breaking_always_increment_major( mut self, breaking_always_increment_major: bool, From 5fbf198cd70891fc0423846625b735af8b54a9cf Mon Sep 17 00:00:00 2001 From: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:49:59 +0100 Subject: [PATCH 17/17] docs --- crates/next_version/src/version_updater.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/next_version/src/version_updater.rs b/crates/next_version/src/version_updater.rs index 1c5a35b48c..e44bbfcb14 100644 --- a/crates/next_version/src/version_updater.rs +++ b/crates/next_version/src/version_updater.rs @@ -59,10 +59,12 @@ impl VersionUpdater { /// Configures automatic minor version increments for feature changes. /// - /// When `true` is passed, it enables automatic minor version increments for feature changes. - /// This means that any introduced feature will trigger a minor version update. + /// - When `true` is passed, a feature will always trigger a minor version update. + /// - When `false` is passed, a feature will trigger: + /// - a patch version update if the major version is 0. + /// - a minor version update otherwise. /// - /// Default: `false` + /// Default: `false`. /// /// ```rust /// use semver::Version; @@ -90,13 +92,15 @@ impl VersionUpdater { self } - /// Configures initial major version increments for breaking changes. + /// Configures `0 -> 1` major version increments for breaking changes. /// - /// When `true` is passed, it enables the initial major version increment - /// for breaking changes. This implies that the transition from version 0 to 1 - /// will be triggered by a breaking change in the API. + /// - When `true` is passed, a breaking change commit will always trigger a major version update + /// (including the transition from version 0 to 1) + /// - When `false` is passed, a breaking change commit will trigger: + /// - a minor version update if the major version is 0. + /// - a major version update otherwise. /// - /// Default: `false` + /// Default: `false`. /// /// ```rust /// use semver::Version;