use indoc::indoc;
use mit_commit::CommitMessage;
use regex::Regex;
use crate::console::exit::Code;
use crate::lints::lib::Problem;
pub(crate) const CONFIG: &str = "github-id-missing";
const HELP_MESSAGE: &str = indoc!(
"
It's important to add the issue ID because it allows us to link code back to the motivations for doing it, and because we can help people exploring the repository link their issues to specific bits of code.
You can fix this by adding a ID like the following examples:
#642
GH-642
AnUser/git-mit#642
AnOrganisation/git-mit#642
fixes #642
Be careful just putting '#642' on a line by itself, as '#' is the default comment character"
);
const ERROR: &str = "Your commit message is missing a GitHub ID";
lazy_static! {
static ref RE: Regex =
Regex::new(r"(?m)(^| )([a-zA-Z0-9_-]{3,39}/[a-zA-Z0-9-]+#|GH-|#)[0-9]+( |$)").unwrap();
}
pub(crate) fn lint(mit_commit: &CommitMessage) -> Option<Problem> {
if mit_commit.matches_pattern(&*RE) {
None
} else {
Some(Problem::new(
ERROR.into(),
HELP_MESSAGE.into(),
Code::GitHubIdMissing,
))
}
}
#[cfg(test)]
mod tests_has_missing_github_id {
#![allow(clippy::wildcard_imports)]
use indoc::indoc;
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn id_and_close() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
close #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
closes: #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
Closed GH-642
"
),
&None,
);
}
#[test]
fn id_and_fix() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
fix #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
This fixes #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
fixed #642
"
),
&None,
);
}
#[test]
fn id_and_resolve() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
resolve #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
resolves #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
resolved #642
"
),
&None,
);
}
#[test]
fn issue() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
Issue #642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
Issue #642
"
),
&None,
);
}
#[test]
fn gh_id_variant() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
GH-642
"
),
&None,
);
}
#[test]
fn hash_alone_variant() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
#642
; Comment character is set to something else like ';'
"
),
&None,
);
}
#[test]
fn long_variant() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
AnUser/git-mit#642
"
),
&None,
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
AnOrganisation/git-mit#642
"
),
&None,
);
}
#[test]
fn id_missing() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
"
),
&Some(Problem::new(
ERROR.into(),
HELP_MESSAGE.into(),
Code::GitHubIdMissing,
)),
);
}
#[test]
fn id_malformed() {
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
H-123
"
),
&Some(Problem::new(
ERROR.into(),
HELP_MESSAGE.into(),
Code::GitHubIdMissing,
)),
);
test_has_missing_github_id(
indoc!(
"
An example commit
This is an example commit
git-mit#123
"
),
&Some(Problem::new(
ERROR.into(),
HELP_MESSAGE.into(),
Code::GitHubIdMissing,
)),
);
}
fn test_has_missing_github_id(message: &str, expected: &Option<Problem>) {
let actual = &lint(&CommitMessage::from(message));
assert_eq!(
actual, expected,
"Message {:?} should have returned {:?}, found {:?}",
message, expected, actual
);
}
}