use crates::git_checks_core::impl_prelude::*;
#[derive(Builder, Debug, Clone)]
#[builder(field(private))]
pub struct RestrictedPath {
#[builder(setter(into))]
path: String,
#[builder(default = "true")]
required: bool,
}
impl RestrictedPath {
pub fn builder() -> RestrictedPathBuilder {
RestrictedPathBuilder::default()
}
}
impl ContentCheck for RestrictedPath {
fn name(&self) -> &str {
"restricted-path"
}
fn check(
&self,
_: &CheckGitContext,
content: &dyn Content,
) -> Result<CheckResult, Box<dyn Error>> {
let mut result = CheckResult::new();
let is_restricted = content
.diffs()
.iter()
.map(|diff| diff.name.as_path())
.any(|path| path.starts_with(&self.path));
if is_restricted {
if self.required {
result.add_error(format!(
"{}the `{}` path is restricted.",
commit_prefix_str(content, "not allowed;"),
self.path,
));
} else {
result.add_warning(format!(
"{}the `{}` path is restricted.",
commit_prefix_str(content, "should be inspected;"),
self.path,
));
};
}
Ok(result)
}
}
#[cfg(feature = "config")]
pub(crate) mod config {
use crates::git_checks_config::{CommitCheckConfig, IntoCheck, TopicCheckConfig};
use crates::inventory;
#[cfg(test)]
use crates::serde_json;
#[cfg(test)]
use test;
use RestrictedPath;
#[derive(Deserialize, Debug)]
pub struct RestrictedPathConfig {
path: String,
#[serde(default)]
required: Option<bool>,
}
impl IntoCheck for RestrictedPathConfig {
type Check = RestrictedPath;
fn into_check(self) -> Self::Check {
let mut builder = RestrictedPath::builder();
builder.path(self.path);
if let Some(required) = self.required {
builder.required(required);
}
builder
.build()
.expect("configuration mismatch for `RestrictedPath`")
}
}
register_checks! {
RestrictedPathConfig {
"restricted_path" => CommitCheckConfig,
"restricted_path/topic" => TopicCheckConfig,
},
}
#[test]
fn test_restricted_path_config_empty() {
let json = json!({});
let err = serde_json::from_value::<RestrictedPathConfig>(json).unwrap_err();
test::check_missing_json_field(err, "path");
}
#[test]
fn test_restricted_path_config_minimum_fields() {
let exp_restricted_path = "path/to/restricted/content";
let json = json!({
"path": exp_restricted_path,
});
let check: RestrictedPathConfig = serde_json::from_value(json).unwrap();
assert_eq!(check.path, exp_restricted_path);
assert_eq!(check.required, None);
}
#[test]
fn test_restricted_path_config_all_fields() {
let exp_restricted_path = "path/to/restricted/content";
let json = json!({
"path": exp_restricted_path,
"required": false,
});
let check: RestrictedPathConfig = serde_json::from_value(json).unwrap();
assert_eq!(check.path, exp_restricted_path);
assert_eq!(check.required, Some(false));
}
}
#[cfg(test)]
mod tests {
use test::*;
use RestrictedPath;
const BAD_TOPIC: &str = "e845fa2521c17bdd31d5891c1c644fb17f0629db";
const FIX_TOPIC: &str = "d8a2f22943cdcca373f00892a23b85f3a6ba1196";
#[test]
fn test_restricted_path_builder_default() {
assert!(RestrictedPath::builder().build().is_err());
}
#[test]
fn test_restricted_path_builder_minimum_fields() {
assert!(RestrictedPath::builder().path("restricted").build().is_ok());
}
#[test]
fn test_restricted_path() {
let check = RestrictedPath::builder()
.path("restricted")
.build()
.unwrap();
let result = run_check("test_restricted_path", BAD_TOPIC, check);
test_result_errors(result, &[
"commit e845fa2521c17bdd31d5891c1c644fb17f0629db not allowed; the `restricted` path \
is restricted.",
]);
}
#[test]
fn test_restricted_path_topic() {
let check = RestrictedPath::builder()
.path("restricted")
.build()
.unwrap();
let result = run_topic_check("test_restricted_path_topic", BAD_TOPIC, check);
test_result_errors(result, &["the `restricted` path is restricted."]);
}
#[test]
fn test_restricted_path_warning() {
let check = RestrictedPath::builder()
.path("restricted")
.required(false)
.build()
.unwrap();
let result = run_check("test_restricted_path_warning", BAD_TOPIC, check);
test_result_warnings(
result,
&[
"commit e845fa2521c17bdd31d5891c1c644fb17f0629db should be inspected; the \
`restricted` path is restricted.",
],
);
}
#[test]
fn test_restricted_path_warning_topic() {
let check = RestrictedPath::builder()
.path("restricted")
.required(false)
.build()
.unwrap();
let result = run_topic_check("test_restricted_path_warning_topic", BAD_TOPIC, check);
test_result_warnings(result, &["the `restricted` path is restricted."]);
}
#[test]
fn test_restricted_path_topic_fixed() {
let check = RestrictedPath::builder()
.path("restricted")
.build()
.unwrap();
run_topic_check_ok("test_restricted_path_topic_fixed", FIX_TOPIC, check);
}
}