diff --git a/git-cliff-core/src/changelog.rs b/git-cliff-core/src/changelog.rs index 01ad3872af..c5dd26d055 100644 --- a/git-cliff-core/src/changelog.rs +++ b/git-cliff-core/src/changelog.rs @@ -7,6 +7,10 @@ use crate::release::{ }; use crate::template::Template; use std::io::Write; +use std::time::{ + SystemTime, + UNIX_EPOCH, +}; /// Changelog generator. #[derive(Debug)] @@ -136,6 +140,23 @@ impl<'a> Changelog<'a> { } } + /// Increments the version for the unreleased changes based on semver. + pub fn bump_version(&mut self) -> 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()?; + debug!("Bumping the version to {next_version}"); + last_release.version = Some(next_version.to_string()); + last_release.timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH)? + .as_secs() + .try_into()?; + return Ok(Some(next_version)); + } + } + Ok(None) + } + /// Generates the changelog and writes it to the given output. pub fn generate(&self, out: &mut W) -> Result<()> { debug!("Generating changelog..."); @@ -231,7 +252,7 @@ mod test { body: Some(String::from( r#"{% if version %} ## Release [{{ version }}] - {{ timestamp | date(format="%Y-%m-%d") }} - ({{ commit_id }}){% else %} + {% if commit_id %}({{ commit_id }}){% endif %}{% else %} ## Unreleased{% endif %} {% for group, commits in commits | group_by(attribute="group") %} ### {{ group }}{% for group, commits in commits | group_by(attribute="scope") %} @@ -499,13 +520,16 @@ mod test { #[test] fn changelog_generator() -> Result<()> { let (config, releases) = get_test_data(); - let changelog = Changelog::new(releases, &config)?; + let mut changelog = Changelog::new(releases, &config)?; + changelog.bump_version()?; + changelog.releases[0].timestamp = 0; let mut out = Vec::new(); changelog.generate(&mut out)?; assert_eq!( String::from( r#"# Changelog - ## Unreleased + ## Release [v1.1.0] - 1970-01-01 + ### Bug Fixes #### app diff --git a/git-cliff/src/lib.rs b/git-cliff/src/lib.rs index 4e2f2b8f2d..925e419c5f 100644 --- a/git-cliff/src/lib.rs +++ b/git-cliff/src/lib.rs @@ -65,14 +65,6 @@ fn check_new_version() { } } -/// Output of the `process_repository` call. -enum ProcessOutput<'a> { - /// List of releases. - Releases(Vec>), - /// Semantic version. - Version(String), -} - /// Processes the tags and commits for creating release entries for the /// changelog. /// @@ -82,7 +74,7 @@ fn process_repository<'a>( repository: &'static Repository, config: Config, args: &Opt, -) -> Result> { +) -> Result>> { let mut tags = repository.tags(&config.git.tag_pattern, args.topo_order)?; let skip_regex = config.git.skip_tags.as_ref(); let ignore_regex = config.git.ignore_tags.as_ref(); @@ -269,24 +261,7 @@ fn process_repository<'a>( } } - // Bump the version. - if (args.bump || args.bumped_version) && - releases[release_index].version.is_none() - { - let next_version = releases[release_index].calculate_next_version()?; - if args.bumped_version { - return Ok(ProcessOutput::Version(next_version)); - } - - debug!("Bumping the version to {next_version}"); - releases[release_index].version = Some(next_version.to_string()); - releases[release_index].timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH)? - .as_secs() - .try_into()?; - } - - Ok(ProcessOutput::Releases(releases)) + Ok(releases) } /// Runs `git-cliff`. @@ -401,34 +376,32 @@ pub fn run(mut args: Opt) -> Result<()> { // Process the repository. let repositories = args.repository.clone().unwrap_or(vec![env::current_dir()?]); let mut releases = Vec::::new(); - let mut versions = Vec::::new(); for repository in repositories { let repository = Repository::init(repository)?; - let process_output = process_repository( + releases.extend(process_repository( Box::leak(Box::new(repository)), config.clone(), &args, - )?; - - match process_output { - ProcessOutput::Releases(release) => releases.extend(release), - ProcessOutput::Version(version) => versions.push(version), - } + )?); } - // Generate output. - if !versions.is_empty() { - let buf = versions.join("\n"); - if let Some(path) = args.output { - let mut output = File::create(path)?; - output.write_all(buf.as_bytes())?; - } else { - println!("{buf}"); - }; - return Ok(()); - } + // Process commits and releases for the changelog. + let mut changelog = Changelog::new(releases, &config)?; - let changelog = Changelog::new(releases, &config)?; + // Print the result. + if args.bump || args.bumped_version { + if let Some(next_version) = changelog.bump_version()? { + if args.bumped_version { + if let Some(path) = args.output { + let mut output = File::create(path)?; + output.write_all(next_version.as_bytes())?; + } else { + println!("{next_version}"); + } + return Ok(()); + } + } + } if args.context { return if let Some(path) = args.output { let mut output = File::create(path)?;