use impl_prelude::*;
use std::ascii::AsciiExt;
#[derive(Debug, Default)]
pub struct InvalidPaths {
invalid_characters: String,
}
impl InvalidPaths {
pub fn new<S: ToString>(chars: S) -> Self {
Self {
invalid_characters: chars.to_string(),
}
}
fn has_invalid_chars(&self, chars: &str) -> bool {
chars.chars()
.any(|ref c| {
!c.is_ascii() || c.is_whitespace() || c.is_control() ||
self.invalid_characters.chars().any(|ref ic| ic == c)
})
}
fn has_invalid_bytes(&self, bytes: &[u8]) -> bool {
bytes.iter()
.any(|&c| !c.is_ascii() || c < 32)
}
}
impl ContentCheck for InvalidPaths {
fn name(&self) -> &str {
"invalid-paths"
}
fn check(&self, _: &CheckGitContext, content: &Content) -> Result<CheckResult> {
let mut result = CheckResult::new();
for diff in content.diffs() {
if let StatusChange::Added = diff.status {
let have_bad_char = self.has_invalid_chars(diff.name.as_str());
let have_bad_bytes = self.has_invalid_bytes(diff.name.as_bytes());
if have_bad_char || have_bad_bytes {
result.add_error(format!("{}adds the `{}` path which contains at \
least one forbidden character: \
`<non-ASCII><whitespace><control>{}`.",
commit_prefix(content),
diff.name,
self.invalid_characters));
}
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use checks::InvalidPaths;
use checks::test::*;
const BAD_TOPIC: &str = "f536f44cf96b82e479d4973d5ea1cf78058bd1fb";
const FIX_TOPIC: &str = "8ff69e1834ef2e82c0ed5cfb4ba56f1e4de85d03";
#[test]
fn test_invalid_paths() {
let check = InvalidPaths::new("$");
let result = run_check("test_invalid_paths", BAD_TOPIC, check);
test_result_errors(result, &[
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the \
`\"control-character-\\003\"` path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>$`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the \
`\"invalid-utf8-\\200\"` path which contains at least one forbidden \
character: `<non-ASCII><whitespace><control>$`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the \
`\"non-ascii-\\303\\251\"` path which contains at least one forbidden \
character: `<non-ASCII><whitespace><control>$`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the `with whitespace` \
path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>$`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the `with-dollar-$` path \
which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>$`.",
]);
}
#[test]
fn test_invalid_paths_topic() {
let check = InvalidPaths::new("$");
let result = run_topic_check("test_invalid_paths_topic", BAD_TOPIC, check);
test_result_errors(result, &[
"adds the `\"control-character-\\003\"` path which contains at least one forbidden \
character: `<non-ASCII><whitespace><control>$`.",
"adds the `\"invalid-utf8-\\200\"` path which contains at least one forbidden \
character: `<non-ASCII><whitespace><control>$`.",
"adds the `\"non-ascii-\\303\\251\"` path which contains at least one forbidden \
character: `<non-ASCII><whitespace><control>$`.",
"adds the `with whitespace` path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>$`.",
"adds the `with-dollar-$` path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>$`.",
]);
}
#[test]
fn test_invalid_paths_default() {
let check = InvalidPaths::default();
let result = run_check("test_invalid_paths_default", BAD_TOPIC, check);
test_result_errors(result, &[
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the \
`\"control-character-\\003\"` path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the `\"invalid-utf8-\\200\"` \
path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the `\"non-ascii-\\303\\251\"` \
path which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>`.",
"commit f536f44cf96b82e479d4973d5ea1cf78058bd1fb adds the `with whitespace` path \
which contains at least one forbidden character: \
`<non-ASCII><whitespace><control>`.",
]);
}
#[test]
fn test_invalid_paths_topic_fixed() {
let check = InvalidPaths::default();
run_topic_check_ok("test_invalid_paths_topic_fixed", FIX_TOPIC, check);
}
}