Skip to content

Commit

Permalink
feat(config): add field and value matchers to the commit parser (#312)
Browse files Browse the repository at this point in the history
* feat(config): add field and value matchers to commit parser (#194)

* docs(config): matchers docs updated with new type of parser based on field and pattern

* test(config): tests covering new parsers

* chore(docs): fix typos in website/docs/configuration.md

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>

* chore(docs): fix more typos website/docs/configuration.md

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>

* chore(docs): update docs for git-cliff-core/src/config.rs

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>

* chore(config): code matching field name refactored

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>

---------

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
  • Loading branch information
dpecos and orhun committed Oct 15, 2023
1 parent 32cbea8 commit 04fbcb8
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 1 deletion.
14 changes: 14 additions & 0 deletions git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ mod test {
default_scope: None,
scope: None,
skip: Some(true),
field: None,
pattern: None,
},
CommitParser {
message: Regex::new("feat*").ok(),
Expand All @@ -246,6 +248,8 @@ mod test {
default_scope: Some(String::from("other")),
scope: None,
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new("^fix*").ok(),
Expand All @@ -254,6 +258,8 @@ mod test {
default_scope: None,
scope: None,
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new("doc:").ok(),
Expand All @@ -262,6 +268,8 @@ mod test {
default_scope: None,
scope: Some(String::from("documentation")),
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new("docs:").ok(),
Expand All @@ -270,6 +278,8 @@ mod test {
default_scope: None,
scope: Some(String::from("documentation")),
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new(r"match\((.*)\):.*").ok(),
Expand All @@ -278,6 +288,8 @@ mod test {
default_scope: None,
scope: None,
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new(".*").ok(),
Expand All @@ -286,6 +298,8 @@ mod test {
default_scope: Some(String::from("other")),
scope: None,
skip: None,
field: None,
pattern: None,
},
]),
protect_breaking_commits: None,
Expand Down
61 changes: 61 additions & 0 deletions git-cliff-core/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,33 @@ impl Commit<'_> {
) {
regex_checks.push((body_regex, body.to_string()))
}
if let (Some(field_name), Some(pattern_regex)) =
(parser.field.as_ref(), parser.pattern.as_ref())
{
regex_checks.push((
pattern_regex,
match field_name.as_str() {
"id" => Some(self.id.clone()),
"message" => Some(self.message.clone()),
"body" => self
.conv
.as_ref()
.and_then(|v| v.body())
.map(|v| v.to_string()),
"author.name" => self.author.name.clone(),
"author.email" => self.author.email.clone(),
"committer.name" => self.committer.name.clone(),
"committer.email" => self.committer.email.clone(),
_ => None,
}
.ok_or_else(|| {
AppError::FieldError(format!(
"field {} does not have a value",
field_name
))
})?,
));
}
for (regex, text) in regex_checks {
if regex.is_match(&text) {
if self.skip_commit(parser, protect_breaking) {
Expand Down Expand Up @@ -420,6 +447,8 @@ mod test {
default_scope: Some(String::from("test_scope")),
scope: None,
skip: None,
field: None,
pattern: None,
}],
false,
false,
Expand Down Expand Up @@ -568,4 +597,36 @@ mod test {
Commit::from(String::from("thisisinvalidsha1 style: add formatting"))
);
}

#[test]
fn parse_commit_field() -> Result<()> {
let mut commit = Commit::new(
String::from("8f55e69eba6e6ce811ace32bd84cc82215673cb6"),
String::from("feat: do something"),
);

commit.author = Signature {
name: Some("John Doe".to_string()),
email: None,
timestamp: 0x0,
};

let parsed_commit = commit.parse(
&[CommitParser {
message: None,
body: None,
group: Some(String::from("Test group")),
default_scope: None,
scope: None,
skip: None,
field: Some(String::from("author.name")),
pattern: Regex::new("John Doe").ok(),
}],
false,
false,
)?;

assert_eq!(Some(String::from("Test group")), parsed_commit.group);
Ok(())
}
}
5 changes: 5 additions & 0 deletions git-cliff-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ pub struct CommitParser {
pub scope: Option<String>,
/// Whether to skip this commit group.
pub skip: Option<bool>,
/// Field name of the commit to match the regex against.
pub field: Option<String>,
/// Regex for matching the field value.
#[serde(with = "serde_regex", default)]
pub pattern: Option<Regex>,
}

/// TextProcessor, e.g. for modifying commit messages.
Expand Down
4 changes: 4 additions & 0 deletions git-cliff-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ pub enum Error {
/// Error that may occur while parsing integers.
#[error("Failed to parse integer: `{0}`")]
IntParseError(#[from] std::num::TryFromIntError),
/// Error that may occur while processing parsers that define field and
/// value matchers
#[error("Field error: `{0}`")]
FieldError(String),
/// Error that may occur while parsing a SemVer version or version
/// requirement.
#[error("Semver error: `{0}`")]
Expand Down
36 changes: 35 additions & 1 deletion git-cliff-core/tests/integration_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use git_cliff_core::commit::Commit;
use git_cliff_core::commit::{
Commit,
Signature,
};
use git_cliff_core::config::{
ChangelogConfig,
CommitParser,
Expand Down Expand Up @@ -55,6 +58,8 @@ fn generate_changelog() -> Result<()> {
default_scope: None,
scope: None,
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new("^fix").ok(),
Expand All @@ -63,6 +68,8 @@ fn generate_changelog() -> Result<()> {
default_scope: None,
scope: None,
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: Regex::new("^test").ok(),
Expand All @@ -71,6 +78,18 @@ fn generate_changelog() -> Result<()> {
default_scope: None,
scope: Some(String::from("tests")),
skip: None,
field: None,
pattern: None,
},
CommitParser {
message: None,
body: None,
group: Some(String::from("docs")),
default_scope: None,
scope: None,
skip: None,
field: Some(String::from("author.name")),
pattern: Regex::new("John Doe").ok(),
},
]),
protect_breaking_commits: None,
Expand All @@ -95,6 +114,17 @@ fn generate_changelog() -> Result<()> {
limit_commits: None,
};

let mut commit_with_author = Commit::new(
String::from("hjdfas32"),
String::from("docs(cool): testing author filtering"),
);

commit_with_author.author = Signature {
name: Some("John Doe".to_string()),
email: None,
timestamp: 0x0,
};

let releases = vec![
Release {
version: Some(String::from("v2.0.0")),
Expand Down Expand Up @@ -133,6 +163,7 @@ fn generate_changelog() -> Result<()> {
String::from("1234"),
String::from("fix: support preprocessing (fixes #99)"),
),
commit_with_author
]
.iter()
.filter_map(|c| c.process(&git_config).ok())
Expand Down Expand Up @@ -181,6 +212,9 @@ fn generate_changelog() -> Result<()> {
## Release v2.0.0
### docs
- *(cool)* testing author filtering
### fix bugs
- fix abc
- support preprocessing [closes Issue#99]
Expand Down
9 changes: 9 additions & 0 deletions website/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,15 @@ Examples:
- If the commit starts with "doc", group the commit as "Documentation" and set the default scope to "other". (e.g. `docs: xyz` will be processed as `docs(other): xyz`)
- `{ message = "(www)", scope = "Application"}`
- If the commit contains "(www)", override the scope with "Application". Scoping order is: scope specification, conventional commit's scope and default scope.
- `{ field = "author.name", pattern = "John Doe", group = "John's stuff"}`
- If the author's name attribute of the commit matches the pattern "John Doe" (as a regex), override the scope with "John' stuff". Supported commit attributes are:
- `id`
- `message`
- `body`
- `author.name`
- `author.email`
- `committer.email`
- `committer.name`

### protect_breaking_commits

Expand Down

0 comments on commit 04fbcb8

Please sign in to comment.