From 02a6187a58583f27e4604d7ea518b52b4bc7a833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Thu, 2 Dec 2021 10:01:10 +0300 Subject: [PATCH] feat(args): add `--current` flag for processing the current tag (#37) --- README.md | 6 ++++++ git-cliff-core/src/repo.rs | 11 +++++++++++ git-cliff/src/args.rs | 3 +++ git-cliff/src/lib.rs | 27 ++++++++++++++++++++++----- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 596ed882b5..d6ea432b67 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ git-cliff [FLAGS] [OPTIONS] [RANGE] -v, --verbose Increases the logging verbosity -i, --init Writes the default configuration file to cliff.toml -l, --latest Processes the commits starting from the latest tag + --current Processes the commits that belong to the current tag -u, --unreleased Processes the commits that do not belong to a tag --topo-order Sorts the tags topologically -h, --help Prints help information @@ -195,6 +196,11 @@ Generate a changelog for a certain part of git history: # (requires at least 2 tags) git cliff --latest +# only takes the current tag into account +# useful if you checkout a specific tag (e.g. `git checkout v0.0.1`) +# (requires a tag to be present for the current commit (i.e. HEAD)) +git cliff --current + # generate changelog for unreleased commits git cliff --unreleased git cliff --unreleased --tag 1.0.0 diff --git a/git-cliff-core/src/repo.rs b/git-cliff-core/src/repo.rs index 92812effdd..3e68d06ebc 100644 --- a/git-cliff-core/src/repo.rs +++ b/git-cliff-core/src/repo.rs @@ -4,6 +4,7 @@ use crate::error::{ }; use git2::{ Commit, + DescribeOptions, Repository as GitRepository, Sort, }; @@ -90,6 +91,16 @@ impl Repository { Ok(commits) } + /// Returns the current tag. + /// + /// It is the same as running `git describe --tags` + pub fn current_tag(&self) -> Option { + self.inner + .describe(DescribeOptions::new().describe_tags()) + .ok() + .and_then(|describe| describe.format(None).ok()) + } + /// Parses and returns a commit-tag map. /// /// It collects lightweight and annotated tags. diff --git a/git-cliff/src/args.rs b/git-cliff/src/args.rs index 2119e0c84e..3972e7c4f2 100644 --- a/git-cliff/src/args.rs +++ b/git-cliff/src/args.rs @@ -67,6 +67,9 @@ pub struct Opt { /// Processes the commits starting from the latest tag. #[structopt(short, long)] pub latest: bool, + /// Processes the commits that belong to the current tag. + #[structopt(long)] + pub current: bool, /// Processes the commits that do not belong to a tag. #[structopt(short, long)] pub unreleased: bool, diff --git a/git-cliff/src/lib.rs b/git-cliff/src/lib.rs index f101b3f115..3226e0afc7 100644 --- a/git-cliff/src/lib.rs +++ b/git-cliff/src/lib.rs @@ -116,14 +116,31 @@ pub fn run(mut args: Opt) -> Result<()> { if let Some(last_tag) = tags.last().map(|(k, _)| k) { commit_range = Some(format!("{}..HEAD", last_tag)); } - } else if args.latest { + } else if args.latest || args.current { if tags.len() < 2 { return Err(Error::ChangelogError(String::from( - "Latest tag cannot be processed", + "Not enough tags exist for processing the latest/current tag", ))); - } else if let (Some(tag1), Some(tag2)) = ( - tags.get_index(tags.len() - 2).map(|(k, _)| k), - tags.get_index(tags.len() - 1).map(|(k, _)| k), + } + let mut tag_index = tags.len() - 2; + if args.current { + if let Some(current_tag_index) = + repository.current_tag().as_ref().and_then(|tag| { + tags.iter() + .enumerate() + .find(|(_, (_, v))| v == &tag) + .map(|(i, _)| i) + }) { + tag_index = current_tag_index - 1; + } else { + return Err(Error::ChangelogError(String::from( + "No tag exists for the current commit", + ))); + } + } + if let (Some(tag1), Some(tag2)) = ( + tags.get_index(tag_index).map(|(k, _)| k), + tags.get_index(tag_index + 1).map(|(k, _)| k), ) { commit_range = Some(format!("{}..{}", tag1, tag2)); }