use super::super::*;
use std::ascii::AsciiExt;
#[derive(Debug, Default)]
pub struct InvalidPaths {
invalid_characters: String,
}
impl InvalidPaths {
pub fn new<S: ToString>(chars: S) -> Self {
InvalidPaths {
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 Check for InvalidPaths {
fn name(&self) -> &str {
"invalid-paths"
}
fn check(&self, _: &CheckGitContext, commit: &Commit) -> Result<CheckResult> {
let mut result = CheckResult::new();
for diff in &commit.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!("commit {} adds the `{}` path which contains at \
least one forbidden character: \
`<non-ASCII><whitespace><control>{}`.",
commit.sha1_short,
diff.name,
self.invalid_characters));
}
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::InvalidPaths;
use super::super::test::*;
static BAD_TOPIC: &'static str = "f536f44cf96b82e479d4973d5ea1cf78058bd1fb";
#[test]
fn test_invalid_paths() {
let check = InvalidPaths::new("$");
let mut conf = GitCheckConfiguration::new();
conf.add_check(&check);
let result = test_check("test_invalid_paths", BAD_TOPIC, &conf);
assert_eq!(result.warnings().len(), 0);
assert_eq!(result.alerts().len(), 0);
assert_eq!(result.errors().len(), 5);
assert_eq!(result.errors()[0],
"commit f536f44 adds the `\"control-character-\\003\"` path which contains \
at least one forbidden character: `<non-ASCII><whitespace><control>$`.");
assert_eq!(result.errors()[1],
"commit f536f44 adds the `\"invalid-utf8-\\200\"` path which contains at \
least one forbidden character: `<non-ASCII><whitespace><control>$`.");
assert_eq!(result.errors()[2],
"commit f536f44 adds the `\"non-ascii-\\303\\251\"` path which contains at \
least one forbidden character: `<non-ASCII><whitespace><control>$`.");
assert_eq!(result.errors()[3],
"commit f536f44 adds the `with whitespace` path which contains at least one \
forbidden character: `<non-ASCII><whitespace><control>$`.");
assert_eq!(result.errors()[4],
"commit f536f44 adds the `with-dollar-$` path which contains at least one \
forbidden character: `<non-ASCII><whitespace><control>$`.");
assert_eq!(result.allowed(), false);
assert_eq!(result.pass(), false);
}
#[test]
fn test_invalid_paths_default() {
let check = InvalidPaths::default();
let mut conf = GitCheckConfiguration::new();
conf.add_check(&check);
let result = test_check("test_invalid_paths_default", BAD_TOPIC, &conf);
assert_eq!(result.warnings().len(), 0);
assert_eq!(result.alerts().len(), 0);
assert_eq!(result.errors().len(), 4);
assert_eq!(result.errors()[0],
"commit f536f44 adds the `\"control-character-\\003\"` path which contains \
at least one forbidden character: `<non-ASCII><whitespace><control>`.");
assert_eq!(result.errors()[1],
"commit f536f44 adds the `\"invalid-utf8-\\200\"` path which contains at \
least one forbidden character: `<non-ASCII><whitespace><control>`.");
assert_eq!(result.errors()[2],
"commit f536f44 adds the `\"non-ascii-\\303\\251\"` path which contains at \
least one forbidden character: `<non-ASCII><whitespace><control>`.");
assert_eq!(result.errors()[3],
"commit f536f44 adds the `with whitespace` path which contains at least one \
forbidden character: `<non-ASCII><whitespace><control>`.");
assert_eq!(result.allowed(), false);
assert_eq!(result.pass(), false);
}
}