use impl_prelude::*;
#[derive(Debug, Default, Clone, Copy)]
pub struct CommitSubject {
min_summary: usize,
max_summary: usize,
check_wip: bool,
check_rebase_commands: bool,
}
impl CommitSubject {
pub fn new() -> Self {
Self {
min_summary: 8,
max_summary: 78,
check_wip: true,
check_rebase_commands: true,
}
}
pub fn with_summary_limits(&mut self, min: usize, max: usize) -> &mut Self {
self.min_summary = min;
self.max_summary = max;
self
}
pub fn check_work_in_progress(&mut self, wip: bool) -> &mut Self {
self.check_wip = wip;
self
}
pub fn check_rebase_commands(&mut self, rebase: bool) -> &mut Self {
self.check_rebase_commands = rebase;
self
}
fn is_generated_subject(summary: &str) -> bool {
false ||
summary.starts_with("Merge ") ||
summary.starts_with("Revert ")
}
}
impl Check for CommitSubject {
fn name(&self) -> &str {
"commit-subject"
}
fn check(&self, _: &CheckGitContext, commit: &Commit) -> Result<CheckResult> {
let mut result = CheckResult::new();
let lines = commit.message.trim().lines().collect::<Vec<_>>();
if lines.is_empty() {
result.add_error(format!("commit {} has an invalid commit subject; it is empty.",
commit.sha1));
return Ok(result);
}
let summary = &lines[0];
let summary_len = summary.len();
if summary_len < self.min_summary {
result.add_error(format!("commit {} has an invalid commit subject; the first line \
must be at least {} characters.",
commit.sha1,
self.min_summary));
}
if !Self::is_generated_subject(summary) && self.max_summary < summary_len {
result.add_error(format!("commit {} has an invalid commit subject; the first line \
must be no longer than {} characters.",
commit.sha1,
self.max_summary));
}
if lines.len() >= 2 {
if lines.len() >= 2 && !lines[1].is_empty() {
result.add_error(format!("commit {} has an invalid commit subject; the second \
line must be empty.",
commit.sha1));
}
if lines.len() == 2 {
result.add_error(format!("commit {} has an invalid commit subject; it cannot be \
exactly two lines.",
commit.sha1));
} else if lines[2].is_empty() {
result.add_error(format!("commit {} has an invalid commit subject; the third \
line must not be empty.",
commit.sha1));
}
}
if self.check_wip && (summary.starts_with("WIP") || summary.starts_with("wip")) {
result.add_error(format!("commit {} cannot be merged; it is marked as a \
work-in-progress (WIP).",
commit.sha1));
}
if self.check_rebase_commands {
if summary.starts_with("fixup! ") {
result.add_error(format!("commit {} cannot be merged; it is marked as a fixup \
commit.",
commit.sha1));
} else if summary.starts_with("squash! ") {
result.add_error(format!("commit {} cannot be merged; it is marked as a commit \
to be squashed.",
commit.sha1));
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use checks::CommitSubject;
use checks::test::*;
const BAD_TOPIC: &str = "5f7284fe1599265c90550b681a4bf0763bc1de21";
#[test]
fn test_check_subject() {
let check = CommitSubject::new();
let result = run_check("test_check_subject", BAD_TOPIC, check);
test_result_errors(result, &[
"commit 5f7284fe1599265c90550b681a4bf0763bc1de21 cannot be merged; it is marked as a \
commit to be squashed.",
"commit 54d673ff559a72ce6343bd9526a950d79034b24e cannot be merged; it is marked as a \
fixup commit.",
"commit 11dbbbff3f32445d74d1a8d96df0a49381c81ba0 cannot be merged; it is marked as a \
work-in-progress (WIP).",
"commit 9039b9a4813fa019229e960033fe1ae8514a0c8e cannot be merged; it is marked as a \
work-in-progress (WIP).",
"commit e478f630b586e331753477eba88059d644927be8 cannot be merged; it is marked as a \
work-in-progress (WIP).",
"commit 3a6fe6d56fbf11c667b6c88bdd7d851a8dcac0b1 has an invalid commit subject; the \
second line must be empty.",
"commit 3a6fe6d56fbf11c667b6c88bdd7d851a8dcac0b1 has an invalid commit subject; the \
third line must not be empty.",
"commit b1ca628043ed78625551420e2dbbd8cf74fde2c4 has an invalid commit subject; the \
second line must be empty.",
"commit b1ca628043ed78625551420e2dbbd8cf74fde2c4 has an invalid commit subject; it \
cannot be exactly two lines.",
"commit 1afc6b3584580488917fc61aa5e5298e98583805 has an invalid commit subject; the \
first line must be no longer than 78 characters.",
"commit 234de3c3f17ab29f0b7644ae96242e31a3dd634c has an invalid commit subject; the \
first line must be at least 8 characters.",
]);
}
}