use super::super::*;
#[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 {
CommitSubject {
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_short));
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_short,
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_short,
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_short));
}
if lines.len() == 2 {
result.add_error(format!("commit {} has an invalid commit subject; it cannot be \
exactly two lines.",
commit.sha1_short));
} 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_short));
}
}
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_short));
}
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_short));
} 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_short));
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::CommitSubject;
use super::super::test::*;
static BAD_TOPIC: &'static str = "5f7284fe1599265c90550b681a4bf0763bc1de21";
#[test]
fn test_check_subject() {
let check = CommitSubject::new();
let mut conf = GitCheckConfiguration::new();
conf.add_check(&check);
let result = test_check("test_check_subject", BAD_TOPIC, &conf);
assert_eq!(result.warnings().len(), 0);
assert_eq!(result.alerts().len(), 0);
assert_eq!(result.errors().len(), 11);
assert_eq!(result.errors()[0],
"commit 5f7284f cannot be merged; it is marked as a commit to be squashed.");
assert_eq!(result.errors()[1],
"commit 54d673f cannot be merged; it is marked as a fixup commit.");
assert_eq!(result.errors()[2],
"commit 11dbbbf cannot be merged; it is marked as a work-in-progress (WIP).");
assert_eq!(result.errors()[3],
"commit 9039b9a cannot be merged; it is marked as a work-in-progress (WIP).");
assert_eq!(result.errors()[4],
"commit e478f63 cannot be merged; it is marked as a work-in-progress (WIP).");
assert_eq!(result.errors()[5],
"commit 3a6fe6d has an invalid commit subject; the second line must be \
empty.");
assert_eq!(result.errors()[6],
"commit 3a6fe6d has an invalid commit subject; the third line must not be \
empty.");
assert_eq!(result.errors()[7],
"commit b1ca628 has an invalid commit subject; the second line must be \
empty.");
assert_eq!(result.errors()[8],
"commit b1ca628 has an invalid commit subject; it cannot be exactly two \
lines.");
assert_eq!(result.errors()[9],
"commit 1afc6b3 has an invalid commit subject; the first line must be no \
longer than 78 characters.");
assert_eq!(result.errors()[10],
"commit 234de3c has an invalid commit subject; the first line must be at \
least 8 characters.");
assert_eq!(result.allowed(), false);
assert_eq!(result.pass(), false);
}
}