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
use std::error::Error;
use std::process;
use console::style;
use mit_commit::CommitMessage;
use crate::console::exit::Code::{InitialNotMatchedToAuthor, UnparsableAuthorFile};
use crate::lints::Problem;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(i32)]
pub enum Code {
InitialNotMatchedToAuthor = 3,
UnparsableAuthorFile,
StaleAuthor,
DuplicatedTrailers,
PivotalTrackerIdMissing,
JiraIssueKeyMissing,
GitHubIdMissing,
SubjectNotSeparateFromBody,
SubjectLongerThan72Characters,
SubjectNotCapitalized,
SubjectEndsWithPeriod,
BodyWiderThan72Characters,
NotConventionalCommit,
NotEmojiLog,
}
pub fn unparsable_author(parse_err: &dyn Error) {
super::style::problem("Unable to parse the author config", &format!("You can fix this by correcting the file so it's parsable\n\nYou can see a parsable example by running:\ngit mit-config mit example\n\nHere's the technical details, that might help you track down the source of the problem\n\n{}", parse_err));
std::process::exit(UnparsableAuthorFile as i32);
}
pub fn initial_not_matched_to_author(initials_without_authors: &[&str]) {
super::style::problem(
&format!(
"Could not find the initials {}.",
initials_without_authors.join(", ")
),
"You can fix this by checking the initials are in the configuration file.",
);
std::process::exit(InitialNotMatchedToAuthor as i32);
}
pub fn stale_author() {
crate::console::style::problem("The details of the author of this commit are stale", "Can you confirm who's currently coding?\n\nIt's nice to get and give the right credit.\n\nYou can fix this by running `git mit` then the initials of whoever is coding for example:\ngit mit bt\ngit mit bt se\n");
process::exit(Code::StaleAuthor as i32);
}
fn format_lint_problems(
original_message: &CommitMessage,
lint_problems: Vec<Problem>,
) -> Option<(String, Code)> {
let (_, message_and_code) = lint_problems.into_iter().fold(
(original_message, None),
|(commit_message, output), problem| {
(
commit_message,
match output {
Some((existing_output, _)) => Some((
{
let error = style(problem.error()).red().bold();
let tip = style(problem.tip()).italic();
format!("{}\n\n{}\n\n{}", existing_output, error, tip)
},
*(problem.code()),
)),
None => Some((
{
let error = style(problem.error()).red().bold();
let tip = style(problem.tip()).italic();
format!(
"{}\n\n---\n\n{}\n\n{}",
String::from(commit_message.clone()),
error,
tip
)
},
*(problem.code()),
)),
},
)
},
);
message_and_code
}
pub fn lint_problem(commit_message: &CommitMessage, lint_problems: Vec<Problem>, clipboard: bool) {
let output = format_lint_problems(commit_message, lint_problems);
if let Some((message, exit_code)) = output {
display_lint_err_and_exit(&message, exit_code, clipboard);
}
}
fn display_lint_err_and_exit(commit_message: &str, exit_code: Code, clipboard: bool) {
eprintln!("{}", commit_message);
if clipboard {
eprintln!(
"\n{}",
style("Your previous commit message has been copied to the clipboard")
.bold()
.blue()
);
}
std::process::exit(exit_code as i32);
}