use impl_prelude::*;
#[derive(Debug, Default, Clone, Copy)]
pub struct SubmoduleWatch {
reject_additions: bool,
reject_removals: bool,
}
impl SubmoduleWatch {
pub fn new() -> Self {
Self {
reject_additions: false,
reject_removals: false,
}
}
pub fn reject_additions(&mut self, reject: bool) -> &mut Self {
self.reject_additions = reject;
self
}
pub fn reject_removals(&mut self, reject: bool) -> &mut Self {
self.reject_removals = reject;
self
}
}
impl Check for SubmoduleWatch {
fn name(&self) -> &str {
"submodule-watch"
}
fn check(&self, ctx: &CheckGitContext, commit: &Commit) -> Result<CheckResult> {
let mut result = CheckResult::new();
for diff in &commit.diffs {
if diff.new_mode != "160000" && diff.old_mode != "160000" {
continue;
}
let mut added = false;
let mut removed = false;
match diff.status {
StatusChange::Added => added = true,
StatusChange::Deleted => removed = true,
StatusChange::Modified(_) => {
if diff.old_mode != diff.new_mode {
if diff.old_mode == "160000" {
removed = true;
} else {
added = true;
}
}
},
_ => (),
}
let is_configured = SubmoduleContext::new(ctx, diff.name.as_ref()).is_some();
if added && !is_configured {
if self.reject_additions {
result.add_error(format!("commit {} adds a submodule at `{}` which is not \
allowed.",
commit.sha1,
diff.name));
} else {
result.add_alert(format!("commit {} adds a submodule at `{}`.",
commit.sha1,
diff.name),
false);
}
result.make_temporary();
}
if removed {
if self.reject_removals {
result.add_error(format!("commit {} removes the submodule at `{}` which \
is not allowed.",
commit.sha1,
diff.name));
} else {
result.add_alert(format!("commit {} removes the submodule at `{}`.",
commit.sha1,
diff.name),
false);
}
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use checks::SubmoduleWatch;
use checks::test::*;
const ADD_SUBMODULE_TOPIC: &str = "fe90ee22ae3ce4b4dc41f8d0876e59355ff1e21c";
const REMOVE_SUBMODULE_TOPIC: &str = "336dbaa31d512033fe77eaba7f92ebfecbd17a39";
#[test]
fn test_submodule_watch_add() {
let check = SubmoduleWatch::new();
let result = run_check("test_submodule_watch_add", ADD_SUBMODULE_TOPIC, check);
assert_eq!(result.warnings().len(), 0);
assert_eq!(result.alerts().len(), 1);
assert_eq!(result.alerts()[0],
"commit fe90ee22ae3ce4b4dc41f8d0876e59355ff1e21c adds a submodule at \
`submodule`.");
assert_eq!(result.errors().len(), 0);
assert_eq!(result.temporary(), true);
assert_eq!(result.allowed(), false);
assert_eq!(result.pass(), true);
}
#[test]
fn test_submodule_watch_add_reject() {
let mut check = SubmoduleWatch::new();
check.reject_additions(true);
let result = run_check("test_submodule_watch_add_reject",
ADD_SUBMODULE_TOPIC,
check);
assert_eq!(result.warnings().len(), 0);
assert_eq!(result.alerts().len(), 0);
assert_eq!(result.errors().len(), 1);
assert_eq!(result.errors()[0],
"commit fe90ee22ae3ce4b4dc41f8d0876e59355ff1e21c adds a submodule at \
`submodule` which is not allowed.");
assert_eq!(result.temporary(), true);
assert_eq!(result.allowed(), false);
assert_eq!(result.pass(), false);
}
#[test]
fn test_submodule_watch_add_configured() {
let check = SubmoduleWatch::new();
let conf = make_check_conf(&check);
let result = test_check_submodule_configure("test_submodule_watch_add_configured",
ADD_SUBMODULE_TOPIC,
&conf,
"submodule");
test_result_ok(result);
}
#[test]
fn test_submodule_watch_add_configured_reject() {
let mut check = SubmoduleWatch::new();
check.reject_additions(true);
let conf = make_check_conf(&check);
let result = test_check_submodule_configure("test_submodule_watch_add_configured_reject",
ADD_SUBMODULE_TOPIC,
&conf,
"submodule");
test_result_ok(result);
}
#[test]
fn test_submodule_watch_remove() {
let check = SubmoduleWatch::new();
let conf = make_check_conf(&check);
let result = test_check_submodule_base("test_submodule_watch_remove",
REMOVE_SUBMODULE_TOPIC,
ADD_SUBMODULE_TOPIC,
&conf);
assert_eq!(result.warnings().len(), 0);
assert_eq!(result.alerts().len(), 1);
assert_eq!(result.alerts()[0],
"commit 336dbaa31d512033fe77eaba7f92ebfecbd17a39 removes the submodule at \
`submodule`.");
assert_eq!(result.errors().len(), 0);
assert_eq!(result.temporary(), false);
assert_eq!(result.allowed(), false);
assert_eq!(result.pass(), true);
}
#[test]
fn test_submodule_watch_remove_reject() {
let mut check = SubmoduleWatch::new();
check.reject_removals(true);
let conf = make_check_conf(&check);
let result = test_check_submodule_base("test_submodule_watch_remove_reject",
REMOVE_SUBMODULE_TOPIC,
ADD_SUBMODULE_TOPIC,
&conf);
test_result_errors(result, &[
"commit 336dbaa31d512033fe77eaba7f92ebfecbd17a39 removes the submodule at `submodule` \
which is not allowed.",
]);
}
}