diff --git a/cliff.toml b/cliff.toml index 6a37033ed8..2a5ffa3b35 100644 --- a/cliff.toml +++ b/cliff.toml @@ -91,7 +91,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "beta|alpha" # regex for ignoring tags diff --git a/config/cliff.toml b/config/cliff.toml index f402fbd753..7ab4b57677 100644 --- a/config/cliff.toml +++ b/config/cliff.toml @@ -69,7 +69,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/examples/cocogitto.toml b/examples/cocogitto.toml index 1a970122a3..99ca51c36f 100644 --- a/examples/cocogitto.toml +++ b/examples/cocogitto.toml @@ -79,7 +79,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/examples/detailed.toml b/examples/detailed.toml index 054c2b95cb..965edbf894 100644 --- a/examples/detailed.toml +++ b/examples/detailed.toml @@ -66,7 +66,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/examples/keepachangelog.toml b/examples/keepachangelog.toml index 9f64a4c3ec..2408f9bfbb 100644 --- a/examples/keepachangelog.toml +++ b/examples/keepachangelog.toml @@ -55,7 +55,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = true # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/examples/scoped.toml b/examples/scoped.toml index af6440bf71..da9b6d2b1d 100644 --- a/examples/scoped.toml +++ b/examples/scoped.toml @@ -57,7 +57,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/examples/scopesorted.toml b/examples/scopesorted.toml index 1d5222bf2e..07195587d9 100644 --- a/examples/scopesorted.toml +++ b/examples/scopesorted.toml @@ -70,7 +70,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/examples/unconventional.toml b/examples/unconventional.toml index ac41fc71d8..8a90a101b1 100644 --- a/examples/unconventional.toml +++ b/examples/unconventional.toml @@ -55,7 +55,7 @@ protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags diff --git a/git-cliff-core/src/config.rs b/git-cliff-core/src/config.rs index 63f97192b2..cfbd926535 100644 --- a/git-cliff-core/src/config.rs +++ b/git-cliff-core/src/config.rs @@ -68,7 +68,8 @@ pub struct GitConfig { /// Whether to filter out commits. pub filter_commits: Option, /// Blob pattern for git tags. - pub tag_pattern: Option, + #[serde(with = "serde_regex", default)] + pub tag_pattern: Option, /// Regex to skip matched tags. #[serde(with = "serde_regex", default)] pub skip_tags: Option, @@ -199,7 +200,7 @@ mod test { .join(crate::DEFAULT_CONFIG); const FOOTER_VALUE: &str = "test"; - const TAG_PATTERN_VALUE: &str = "*[0-9]*"; + const TAG_PATTERN_VALUE: &str = ".*[0-9].*"; const IGNORE_TAGS_VALUE: &str = "v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+"; env::set_var("GIT_CLIFF__CHANGELOG__FOOTER", FOOTER_VALUE); @@ -211,7 +212,10 @@ mod test { assert_eq!(Some(String::from(FOOTER_VALUE)), config.changelog.footer); assert_eq!( Some(String::from(TAG_PATTERN_VALUE)), - config.git.tag_pattern + config + .git + .tag_pattern + .map(|tag_pattern| tag_pattern.to_string()) ); assert_eq!( Some(String::from(IGNORE_TAGS_VALUE)), diff --git a/git-cliff-core/src/repo.rs b/git-cliff-core/src/repo.rs index 0207174fdb..0bde26b230 100644 --- a/git-cliff-core/src/repo.rs +++ b/git-cliff-core/src/repo.rs @@ -10,6 +10,7 @@ use git2::{ }; use glob::Pattern; use indexmap::IndexMap; +use regex::Regex; use std::io; use std::path::PathBuf; @@ -102,12 +103,19 @@ impl Repository { /// It collects lightweight and annotated tags. pub fn tags( &self, - pattern: &Option, + pattern: &Option, topo_order: bool, ) -> Result> { let mut tags: Vec<(Commit, String)> = Vec::new(); - let tag_names = self.inner.tag_names(pattern.as_deref())?; - for name in tag_names.iter().flatten().map(String::from) { + let tag_names = self.inner.tag_names(None)?; + for name in tag_names + .iter() + .flatten() + .filter(|tag_name| { + pattern.as_ref().map_or(true, |pat| pat.is_match(tag_name)) + }) + .map(String::from) + { let obj = self.inner.revparse_single(&name)?; if let Ok(commit) = obj.clone().into_commit() { tags.push((commit, name)); @@ -191,4 +199,43 @@ mod test { assert_eq!(&get_last_tag()?, tags.last().expect("no tags found").1); Ok(()) } + + #[test] + fn git_tags() -> Result<()> { + let repository = Repository::init( + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("parent directory not found") + .to_path_buf(), + )?; + let tags = repository.tags(&None, true)?; + assert_eq!( + tags.get("2b8b4d3535f29231e05c3572e919634b9af907b6").expect( + "the commit hash does not exist in the repository (tag v0.1.0)" + ), + "v0.1.0" + ); + assert_eq!( + tags.get("4ddef08debfff48117586296e49d5caa0800d1b5").expect( + "the commit hash does not exist in the repository (tag \ + v0.1.0-beta.4)" + ), + "v0.1.0-beta.4" + ); + let tags = repository.tags( + &Some( + Regex::new("^v[0-9]+\\.[0-9]+\\.[0-9]$") + .expect("the regex is not valid"), + ), + true, + )?; + assert_eq!( + tags.get("2b8b4d3535f29231e05c3572e919634b9af907b6").expect( + "the commit hash does not exist in the repository (tag v0.1.0)" + ), + "v0.1.0" + ); + assert!(!tags.contains_key("4ddef08debfff48117586296e49d5caa0800d1b5")); + Ok(()) + } } diff --git a/website/docs/configuration.md b/website/docs/configuration.md index 540e674153..a4ad48a129 100644 --- a/website/docs/configuration.md +++ b/website/docs/configuration.md @@ -83,7 +83,7 @@ commit_parsers = [ ] protect_breaking_commits = false filter_commits = false -tag_pattern = "v[0-9]*" +tag_pattern = "^v[0-9].*" skip_tags = "v0.1.0-beta.1" ignore_tags = "" topo_order = false @@ -241,13 +241,7 @@ If set to `true`, commits that are not matched by [`commit_parsers`](#commit_par ### tag_pattern -A glob pattern for matching the git tags. - -e.g. It processes the same tags as the output of the following git command: - -```bash -git tag --list 'v[0-9]*' -``` +A regular expression for matching the git tags. ### skip_tags