From bf9d866930b459a4c07bc71a6f110d3f5b605112 Mon Sep 17 00:00:00 2001 From: Jaroslaw Surkont Date: Mon, 4 Mar 2024 14:55:45 +0100 Subject: [PATCH] feat(release)!: allow preserving zero-based versions closes #447 --- git-cliff-core/src/changelog.rs | 7 +-- git-cliff-core/src/release.rs | 85 +++++++++++++++++++++++---------- git-cliff/src/args.rs | 3 ++ git-cliff/src/lib.rs | 2 +- website/docs/usage/args.md | 1 + 5 files changed, 68 insertions(+), 30 deletions(-) diff --git a/git-cliff-core/src/changelog.rs b/git-cliff-core/src/changelog.rs index 2322d1a7bf..1c22333d8f 100644 --- a/git-cliff-core/src/changelog.rs +++ b/git-cliff-core/src/changelog.rs @@ -196,10 +196,11 @@ impl<'a> Changelog<'a> { } /// Increments the version for the unreleased changes based on semver. - pub fn bump_version(&mut self) -> Result> { + pub fn bump_version(&mut self, keep_zerover: bool) -> Result> { if let Some(ref mut last_release) = self.releases.iter_mut().next() { if last_release.version.is_none() { - let next_version = last_release.calculate_next_version()?; + let next_version = + last_release.calculate_next_version(keep_zerover)?; debug!("Bumping the version to {next_version}"); last_release.version = Some(next_version.to_string()); last_release.timestamp = SystemTime::now() @@ -608,7 +609,7 @@ mod test { fn changelog_generator() -> Result<()> { let (config, releases) = get_test_data(); let mut changelog = Changelog::new(releases, &config)?; - changelog.bump_version()?; + changelog.bump_version(false)?; changelog.releases[0].timestamp = 0; let mut out = Vec::new(); changelog.generate(&mut out)?; diff --git a/git-cliff-core/src/release.rs b/git-cliff-core/src/release.rs index b1930daf3b..072bb897c1 100644 --- a/git-cliff-core/src/release.rs +++ b/git-cliff-core/src/release.rs @@ -98,7 +98,7 @@ impl<'a> Release<'a> { } /// Calculates the next version based on the commits. - pub fn calculate_next_version(&self) -> Result { + pub fn calculate_next_version(&self, keep_zerover: bool) -> Result { match self .previous .as_ref() @@ -126,8 +126,8 @@ impl<'a> Release<'a> { } } let next_version = VersionUpdater::new() - .with_features_always_increment_minor(true) - .with_breaking_always_increment_major(true) + .with_features_always_increment_minor(!keep_zerover) + .with_breaking_always_increment_major(!keep_zerover) .increment( &semver?, self.commits @@ -169,7 +169,27 @@ mod test { use super::*; #[test] fn bump_version() -> Result<()> { - for (version, expected_version, commits) in [ + fn build_release<'a>(version: &str, commits: &'a [&str]) -> Release<'a> { + Release { + version: None, + commits: commits + .iter() + .map(|v| Commit::from(v.to_string())) + .collect(), + commit_id: None, + timestamp: 0, + previous: Some(Box::new(Release { + version: Some(String::from(version)), + ..Default::default() + })), + #[cfg(feature = "github")] + github: crate::github::GitHubReleaseMetadata { + contributors: vec![], + }, + } + } + + let test_shared = [ ("1.0.0", "1.1.0", vec!["feat: add xyz", "fix: fix xyz"]), ("1.0.0", "1.0.1", vec!["fix: add xyz", "fix: aaaaaa"]), ("1.0.0", "2.0.0", vec!["feat!: add xyz", "feat: zzz"]), @@ -202,27 +222,40 @@ mod test { "aaa#/@#$@9384!#%^#@#@!#!239432413-idk-9999.2200.5932-alpha.420", vec!["feat: damn this is working"], ), - ] { - let release = Release { - version: None, - commits: commits - .into_iter() - .map(|v| Commit::from(v.to_string())) - .collect(), - commit_id: None, - timestamp: 0, - previous: Some(Box::new(Release { - version: Some(String::from(version)), - ..Default::default() - })), - #[cfg(feature = "github")] - github: crate::github::GitHubReleaseMetadata { - contributors: vec![], - }, - }; - let next_version = release.calculate_next_version()?; - assert_eq!(expected_version, next_version); + ]; + + for (version, expected_version, commits) in test_shared.iter().chain( + [ + ("0.0.1", "0.0.2", vec!["fix: fix xyz"]), + ("0.0.1", "0.1.0", vec!["feat: add xyz", "fix: fix xyz"]), + ("0.0.1", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]), + ("0.1.0", "0.1.1", vec!["fix: fix xyz"]), + ("0.1.0", "0.2.0", vec!["feat: add xyz", "fix: fix xyz"]), + ("0.1.0", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]), + ] + .iter(), + ) { + let release = build_release(version, commits); + let next_version = release.calculate_next_version(false)?; + assert_eq!(expected_version, &next_version); + } + + for (version, expected_version, commits) in test_shared.iter().chain( + [ + ("0.0.1", "0.0.2", vec!["fix: fix xyz"]), + ("0.0.1", "0.0.2", vec!["feat: add xyz", "fix: fix xyz"]), + ("0.0.1", "0.0.2", vec!["feat!: add xyz", "feat: zzz"]), + ("0.1.0", "0.1.1", vec!["fix: fix xyz"]), + ("0.1.0", "0.1.1", vec!["feat: add xyz", "fix: fix xyz"]), + ("0.1.0", "0.2.0", vec!["feat!: add xyz", "feat: zzz"]), + ] + .iter(), + ) { + let release = build_release(version, commits); + let next_version = release.calculate_next_version(true)?; + assert_eq!(expected_version, &next_version); } + let empty_release = Release { previous: Some(Box::new(Release { version: None, @@ -230,8 +263,8 @@ mod test { })), ..Default::default() }; - let next_version = empty_release.calculate_next_version()?; - assert_eq!("0.1.0", next_version); + assert_eq!("0.1.0", empty_release.calculate_next_version(false)?); + assert_eq!("0.1.0", empty_release.calculate_next_version(true)?); Ok(()) } diff --git a/git-cliff/src/args.rs b/git-cliff/src/args.rs index 3f8d6766a2..d1ff504048 100644 --- a/git-cliff/src/args.rs +++ b/git-cliff/src/args.rs @@ -182,6 +182,9 @@ pub struct Opt { /// Bumps the version for unreleased changes. #[arg(long, help_heading = Some("FLAGS"))] pub bump: bool, + /// Keeps leading zeros (0.0.x, 0.x.y) when bumping the version. + #[arg(long, help_heading = Some("FLAGS"))] + pub keep_zerover: bool, /// Prints bumped version for unreleased changes. #[arg(long, help_heading = Some("FLAGS"))] pub bumped_version: bool, diff --git a/git-cliff/src/lib.rs b/git-cliff/src/lib.rs index 0cf683d4f4..cbbd4c5fe4 100644 --- a/git-cliff/src/lib.rs +++ b/git-cliff/src/lib.rs @@ -464,7 +464,7 @@ pub fn run(mut args: Opt) -> Result<()> { // Print the result. if args.bump || args.bumped_version { - if let Some(next_version) = changelog.bump_version()? { + if let Some(next_version) = changelog.bump_version(args.keep_zerover)? { if args.bumped_version { if let Some(path) = args.output { let mut output = File::create(path)?; diff --git a/website/docs/usage/args.md b/website/docs/usage/args.md index 3a79ff630c..a583f73fa8 100644 --- a/website/docs/usage/args.md +++ b/website/docs/usage/args.md @@ -15,6 +15,7 @@ git-cliff [FLAGS] [OPTIONS] [--] [RANGE] -V, --version Prints version information -v, --verbose... Increases the logging verbosity --bump Bumps the version for unreleased changes + --keep-zerover Keeps leading zeros (0.0.x, 0.x.y) when bumping the version. --bumped-version Prints bumped version for unreleased changes -l, --latest Processes the commits starting from the latest tag --current Processes the commits that belong to the current tag