1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use thiserror::Error as ThisError;

/// Library related errors that we are exposing to the rest of the workspaces.
#[derive(Debug, ThisError)]
pub enum Error {
	/// Error that may occur while I/O operations.
	#[error("IO error: `{0}`")]
	IoError(#[from] std::io::Error),
	/// Error that may occur when attempting to interpret a sequence of u8 as a
	/// string.
	#[error("UTF-8 error: `{0}`")]
	Utf8Error(#[from] std::str::Utf8Error),
	/// Error variant that represents errors coming out of libgit2.
	#[cfg(feature = "repo")]
	#[error("Git error: `{0}`")]
	GitError(#[from] git2::Error),
	/// Error variant that represents other repository related errors.
	#[cfg(feature = "repo")]
	#[error("Git repository error: `{0}`")]
	RepoError(String),
	/// Error that may occur while parsing the config file.
	#[error("Cannot parse config: `{0}`")]
	ConfigError(#[from] config::ConfigError),
	/// A possible error while initializing the logger.
	#[error("Logger error: `{0}`")]
	LoggerError(String),
	/// When commit's not follow the conventional commit structure we throw this
	/// error.
	#[error("Cannot parse the commit: `{0}`")]
	ParseError(#[from] git_conventional::Error),
	/// Error that may occur while grouping commits.
	#[error("Grouping error: `{0}`")]
	GroupError(String),
	/// Error that may occur while generating changelog.
	#[error("Changelog error: `{0}`")]
	ChangelogError(String),
	/// Error that may occur while parsing the template.
	#[error("Template parse error:\n{0}")]
	TemplateParseError(String),
	/// Error that may occur while rendering the template.
	#[error("Template render error:\n{0}")]
	TemplateRenderError(String),
	/// Error that may occur while rendering the template.
	#[error("Template render error:\n{0}\n{1}")]
	TemplateRenderDetailedError(String, String),
	/// Error that may occur during more general template operations.
	#[error("Template error: `{0}`")]
	TemplateError(#[from] tera::Error),
	/// Error that may occur while parsing the command line arguments.
	#[error("Argument error: `{0}`")]
	ArgumentError(String),
	/// Error that may occur while extracting the embedded content.
	#[error("Embedded error: `{0}`")]
	EmbeddedError(String),
	/// Errors that may occur when deserializing types from TOML format.
	#[error("Cannot parse TOML: `{0}`")]
	DeserializeError(#[from] toml::de::Error),
	/// Errors that may occur while de/serializing JSON format.
	#[error("Cannot de/serialize JSON: `{0}`")]
	JsonError(#[from] serde_json::Error),
	/// Errors that may occur during parsing or compiling a regular expression.
	#[error("Cannot parse/compile regex: `{0}`")]
	RegexError(#[from] regex::Error),
	/// Error that may occur due to system time related anomalies.
	#[error("System time error: `{0}`")]
	SystemTimeError(#[from] std::time::SystemTimeError),
	/// 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}`")]
	SemverError(#[from] semver::Error),
	/// The errors that may occur when processing a HTTP request.
	#[error("HTTP client error: `{0}`")]
	#[cfg(feature = "github")]
	HttpClientError(#[from] reqwest::Error),
	/// The errors that may occur while constructing the HTTP client with
	/// middleware.
	#[error("HTTP client with middleware error: `{0}`")]
	#[cfg(feature = "github")]
	HttpClientMiddlewareError(#[from] reqwest_middleware::Error),
	/// A possible error when converting a HeaderValue from a string or byte
	/// slice.
	#[error("HTTP header error: `{0}`")]
	#[cfg(feature = "github")]
	HttpHeaderError(#[from] reqwest::header::InvalidHeaderValue),
	/// Error that may occur during handling pages.
	#[error("Pagination error: `{0}`")]
	PaginationError(String),
	/// The errors that may occur while parsing URLs.
	#[error("URL parse error: `{0}`")]
	UrlParseError(#[from] url::ParseError),
	/// Error that may occur when a remote is not set.
	#[error("Repository remote is not set.")]
	RemoteNotSetError,
	/// Error that may occur while handling location of directories.
	#[error("Directory error: `{0}`")]
	DirsError(String),
}

/// Result type of the core library.
pub type Result<T> = core::result::Result<T, Error>;

#[cfg(test)]
mod test {
	use super::*;
	use git_conventional::{
		Commit,
		ErrorKind,
	};
	fn mock_function() -> super::Result<Commit<'static>> {
		Ok(Commit::parse("test")?)
	}

	#[test]
	fn throw_parse_error() {
		let actual_error = mock_function().expect_err("expected error");
		let expected_error_kind = ErrorKind::MissingType;
		match actual_error {
			Error::ParseError(e) => {
				assert_eq!(expected_error_kind, e.kind());
			}
			_ => {
				unreachable!()
			}
		}
	}
}