diff --git a/src/git.rs b/src/git.rs index 01ad22f..0c0a9ae 100644 --- a/src/git.rs +++ b/src/git.rs @@ -119,9 +119,10 @@ pub fn parse_commit_message( /// does not have any rules for it. /// See: https://commitlint.js.org/#/reference-rules pub fn parse_subject(subject: &str) -> (Option, Option, Option) { - let re = - regex::Regex::new(r"^(?P\w+)(?:\((?P[^\)]+)\))?(!)?\:\s(?P.+)$") - .unwrap(); + let re = regex::Regex::new( + r"^(?P\w+)(?:\((?P[^\)]+)\))?(?:!)?\:\s?(?P.*)$", + ) + .unwrap(); if let Some(captures) = re.captures(subject) { let r#type = captures.name("type").map(|m| m.as_str().to_string()); let scope = captures.name("scope").map(|m| m.as_str().to_string()); @@ -232,7 +233,6 @@ Name: Keke"; ) ); } - #[test] fn test_parse_subject_with_emphasized_type_without_scope() { @@ -246,11 +246,39 @@ Name: Keke"; ) ); } + + #[test] + fn test_parse_subject_with_empty_description() { + let input = "feat(cli): "; + assert_eq!( + parse_subject(input), + ( + Some("feat".to_string()), + Some("cli".to_string()), + Some("".to_string()) + ) + ); + } + + #[test] + fn test_parse_subject_with_empty_scope() { + let input = "feat: add dummy commit"; + assert_eq!( + parse_subject(input), + ( + Some("feat".to_string()), + None, + Some("add dummy commit".to_string()) + ) + ); + } + #[test] fn test_parse_subject_without_message() { let input = ""; assert_eq!(parse_subject(input), (None, None, Some("".to_string()))); } + #[test] fn test_parse_subject_with_error_message() { let input = "test"; diff --git a/src/rule/description_format.rs b/src/rule/description_format.rs index 1f948a1..070d315 100644 --- a/src/rule/description_format.rs +++ b/src/rule/description_format.rs @@ -40,11 +40,21 @@ impl Rule for DescriptionFormat { } }; - if !regex.is_match(&message.description.as_ref().unwrap()) { - return Some(Violation { - level: self.level.unwrap_or(Self::LEVEL), - message: self.message(message), - }); + match &message.description { + None => { + return Some(Violation { + level: self.level.unwrap_or(Self::LEVEL), + message: "found no description".to_string(), + }); + } + Some(description) => { + if !regex.is_match(description) { + return Some(Violation { + level: self.level.unwrap_or(Self::LEVEL), + message: self.message(message), + }); + } + } } } diff --git a/src/rule/scope_format.rs b/src/rule/scope_format.rs index d446168..9889bed 100644 --- a/src/rule/scope_format.rs +++ b/src/rule/scope_format.rs @@ -40,11 +40,21 @@ impl Rule for ScopeFormat { } }; - if !regex.is_match(&message.scope.as_ref().unwrap()) { - return Some(Violation { - level: self.level.unwrap_or(Self::LEVEL), - message: self.message(message), - }); + match &message.scope { + None => { + return Some(Violation { + level: self.level.unwrap_or(Self::LEVEL), + message: "found no description".to_string(), + }); + } + Some(description) => { + if !regex.is_match(description) { + return Some(Violation { + level: self.level.unwrap_or(Self::LEVEL), + message: self.message(message), + }); + } + } } } diff --git a/src/rule/type_format.rs b/src/rule/type_format.rs index 3d1a1e4..259a3ee 100644 --- a/src/rule/type_format.rs +++ b/src/rule/type_format.rs @@ -40,11 +40,21 @@ impl Rule for TypeFormat { } }; - if !regex.is_match(&message.r#type.as_ref().unwrap()) { - return Some(Violation { - level: self.level.unwrap_or(Self::LEVEL), - message: self.message(message), - }); + match &message.r#type { + None => { + return Some(Violation { + level: self.level.unwrap_or(Self::LEVEL), + message: "found no type".to_string(), + }); + } + Some(description) => { + if !regex.is_match(description) { + return Some(Violation { + level: self.level.unwrap_or(Self::LEVEL), + message: self.message(message), + }); + } + } } }