git_conventional/
error.rs1use std::fmt;
4
5pub struct Error {
7 kind: ErrorKind,
8
9 context: Option<Box<dyn fmt::Display + Send + Sync>>,
10 commit: Option<String>,
11}
12
13impl Error {
14 pub(crate) fn new(kind: ErrorKind) -> Self {
16 Self {
17 kind,
18 context: None,
19 commit: None,
20 }
21 }
22
23 pub(crate) fn with_nom(
24 commit: &str,
25 err: winnow::error::ParseError<&str, winnow::error::ContextError>,
26 ) -> Self {
27 use winnow::error::StrContext;
28 use ErrorKind::{
29 InvalidBody, InvalidFormat, InvalidScope, MissingDescription, MissingType,
30 };
31
32 let mut kind = InvalidFormat;
33 for context in err.inner().context() {
34 kind = match context {
35 StrContext::Label(string) => match *string {
36 crate::parser::SUMMARY => MissingType,
37 crate::parser::TYPE => MissingType,
38 crate::parser::SCOPE => InvalidScope,
39 crate::parser::DESCRIPTION => MissingDescription,
40 crate::parser::BODY => InvalidBody,
41 _ => kind,
42 },
43 _ => kind,
44 };
45 }
46
47 Self {
48 kind,
49 context: None,
50 commit: Some(commit.to_owned()),
51 }
52 }
53
54 pub(crate) fn set_context(mut self, context: Box<dyn fmt::Display + Send + Sync>) -> Self {
55 self.context = Some(context);
56 self
57 }
58
59 pub fn kind(&self) -> ErrorKind {
61 self.kind
62 }
63}
64
65impl fmt::Debug for Error {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.debug_struct("Error")
68 .field("kind", &self.kind)
69 .field("context", &self.context.as_ref().map(|s| s.to_string()))
70 .field("commit", &self.commit)
71 .finish()
72 }
73}
74
75impl fmt::Display for Error {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 if let Some(context) = self.context.as_ref() {
78 write!(f, "{}: {}", self.kind, context)
79 } else {
80 write!(f, "{}", self.kind)
81 }
82 }
83}
84
85impl std::error::Error for Error {
86 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
87 None
88 }
89}
90
91#[derive(Copy, Clone, Debug, PartialEq, Eq)]
93#[non_exhaustive]
94pub enum ErrorKind {
95 MissingType,
97
98 InvalidScope,
100
101 MissingDescription,
103
104 InvalidBody,
106
107 InvalidFooter,
109
110 InvalidFormat,
113}
114
115impl fmt::Display for ErrorKind {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 let s = match self {
118 ErrorKind::MissingType => {
119 "Missing type in the commit summary, expected `type: description`"
120 }
121 ErrorKind::InvalidScope => {
122 "Incorrect scope syntax in commit summary, expected `type(scope): description`"
123 }
124 ErrorKind::MissingDescription => {
125 "Missing description in commit summary, expected `type: description`"
126 }
127 ErrorKind::InvalidBody => "Incorrect body syntax",
128 ErrorKind::InvalidFooter => "Incorrect footer syntax",
129 ErrorKind::InvalidFormat => "Incorrect conventional commit format",
130 };
131 f.write_str(s)
132 }
133}