use crates::git_checks_core::impl_prelude::*;
use binary_format;
#[derive(Builder, Debug, Default, Clone, Copy)]
#[builder(field(private))]
pub struct RejectBinaries {}
impl RejectBinaries {
pub fn builder() -> RejectBinariesBuilder {
RejectBinariesBuilder::default()
}
}
impl ContentCheck for RejectBinaries {
fn name(&self) -> &str {
"reject-binaries"
}
fn check(
&self,
ctx: &CheckGitContext,
content: &dyn Content,
) -> Result<CheckResult, Box<dyn Error>> {
let mut result = CheckResult::new();
for diff in content.diffs() {
match diff.status {
StatusChange::Added | StatusChange::Modified(_) => (),
_ => continue,
}
let binary_attr = ctx.check_attr("hooks-allow-binary", diff.name.as_path())?;
let allowed_binary_type = match binary_attr {
AttributeState::Set => continue,
AttributeState::Value(ref v) => Some(v),
_ => None,
};
let binary_type = {
let cat_file = ctx
.git()
.arg("cat-file")
.arg("blob")
.arg(diff.new_blob.as_str())
.output()
.map_err(|err| GitError::subcommand("cat-file", err))?;
let stdout = cat_file.stdout;
binary_format::detect_binary_format(stdout)
};
if let Some(binary_type) = binary_type {
let type_name = binary_type.name();
if let Some(allowed_binary_type) = allowed_binary_type {
if allowed_binary_type != type_name {
result.add_error(format!(
"{}adds the {} (not {}) binary `{}`.",
commit_prefix(content),
type_name,
allowed_binary_type,
diff.name,
));
}
} else {
result.add_error(format!(
"{}adds the {} binary `{}`.",
commit_prefix(content),
type_name,
diff.name,
));
}
}
}
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;
use RejectBinaries;
#[derive(Deserialize, Debug)]
pub struct RejectBinariesConfig {}
impl IntoCheck for RejectBinariesConfig {
type Check = RejectBinaries;
fn into_check(self) -> Self::Check {
RejectBinaries::default()
}
}
register_checks! {
RejectBinariesConfig {
"reject_binaries" => CommitCheckConfig,
"reject_binaries/topic" => TopicCheckConfig,
},
}
#[test]
fn test_reject_binaries_config_empty() {
let json = json!({});
serde_json::from_value::<RejectBinariesConfig>(json).unwrap();
}
}
#[cfg(test)]
mod tests {
use test::*;
use RejectBinaries;
const BAD_COMMIT: &str = "8326e6bcc8cd6718e367d889bcb64739982b6c66";
const BAD_COMMIT_EXE: &str = "b8c710757905c59cf880ade2af288b6891b5723c";
const FIX_COMMIT: &str = "6bb12ca6419503c82a723bc89984d0f0dda76f05";
const ATTR_COMMIT: &str = "63ff7dbf0523c6ffcb9bac64c8406f9bb121ea9f";
const ATTR_COMMIT_BAD: &str = "107c49759fe7d603d83264cd2e013054f730f534";
const FIX_ATTR_COMMIT: &str = "9c925e6b7f967dd04958588e1994429f6f8712f6";
#[test]
fn test_reject_binaries_builder_default() {
assert!(RejectBinaries::builder().build().is_ok());
}
#[test]
fn test_reject_binaries() {
let check = RejectBinaries::default();
let result = run_check("test_reject_binaries", BAD_COMMIT, check);
test_result_errors(result, &[
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the ELF binary `elf-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-cigam-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-fat-cigam-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-fat-magic-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-magic-header`.",
"commit 8326e6bcc8cd6718e367d889bcb64739982b6c66 adds the AR binary `ar-header`.",
]);
}
#[test]
fn test_reject_binaries_plus_x() {
let check = RejectBinaries::default();
let result = run_check("test_reject_binaries_plus_x", BAD_COMMIT_EXE, check);
test_result_errors(result, &[
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the ELF binary `elf-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-cigam-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-fat-cigam-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-fat-magic-header`.",
"commit e5e1e2c8db62ac8f50f249d3cf3f334ddf158936 adds the Mach-O binary `macho-magic-header`.",
"commit 261577469c6790190d866a928dc3bd8e91d238cf adds the ELF binary `elf-header`.",
"commit 261577469c6790190d866a928dc3bd8e91d238cf adds the Mach-O binary `macho-cigam-header`.",
"commit 261577469c6790190d866a928dc3bd8e91d238cf adds the Mach-O binary `macho-fat-cigam-header`.",
"commit 261577469c6790190d866a928dc3bd8e91d238cf adds the Mach-O binary `macho-fat-magic-header`.",
"commit 261577469c6790190d866a928dc3bd8e91d238cf adds the Mach-O binary `macho-magic-header`.",
"commit b8c710757905c59cf880ade2af288b6891b5723c adds the AR binary `ar-header`.",
]);
}
#[test]
fn test_reject_binaries_attr_ok() {
let check = RejectBinaries::default();
run_check_ok("test_reject_binaries_attr_ok", ATTR_COMMIT, check)
}
#[test]
fn test_reject_binaries_attr_bad() {
let check = RejectBinaries::default();
let result = run_check("test_reject_binaries_attr_bad", ATTR_COMMIT_BAD, check);
test_result_errors(result, &[
"commit 71fa463c4bedeb40807b6c73b08ce207b0fe0309 adds the ELF (not Mach-O) binary `elf-header`.",
"commit 71fa463c4bedeb40807b6c73b08ce207b0fe0309 adds the Mach-O (not ELF) binary `macho-cigam-header`.",
"commit 71fa463c4bedeb40807b6c73b08ce207b0fe0309 adds the Mach-O (not ELF) binary `macho-fat-cigam-header`.",
"commit 71fa463c4bedeb40807b6c73b08ce207b0fe0309 adds the Mach-O (not ELF) binary `macho-fat-magic-header`.",
"commit 71fa463c4bedeb40807b6c73b08ce207b0fe0309 adds the Mach-O (not ELF) binary `macho-magic-header`.",
"commit 107c49759fe7d603d83264cd2e013054f730f534 adds the AR (not ELF) binary `ar-header`.",
]);
}
#[test]
fn test_reject_binaries_topic() {
let check = RejectBinaries::default();
let result = run_topic_check("test_reject_binaries_topic", BAD_COMMIT, check);
test_result_errors(
result,
&[
"adds the AR binary `ar-header`.",
"adds the ELF binary `elf-header`.",
"adds the Mach-O binary `macho-cigam-header`.",
"adds the Mach-O binary `macho-fat-cigam-header`.",
"adds the Mach-O binary `macho-fat-magic-header`.",
"adds the Mach-O binary `macho-magic-header`.",
],
);
}
#[test]
fn test_reject_binaries_topic_attr_ok() {
let check = RejectBinaries::default();
run_topic_check_ok("test_reject_binaries_topic_attr_ok", ATTR_COMMIT, check)
}
#[test]
fn test_reject_binaries_topic_attr_bad() {
let check = RejectBinaries::default();
let result = run_topic_check(
"test_reject_binaries_topic_attr_bad",
ATTR_COMMIT_BAD,
check,
);
test_result_errors(
result,
&[
"adds the AR (not ELF) binary `ar-header`.",
"adds the ELF (not Mach-O) binary `elf-header`.",
"adds the Mach-O (not ELF) binary `macho-cigam-header`.",
"adds the Mach-O (not ELF) binary `macho-fat-cigam-header`.",
"adds the Mach-O (not ELF) binary `macho-fat-magic-header`.",
"adds the Mach-O (not ELF) binary `macho-magic-header`.",
],
);
}
#[test]
fn test_reject_binaries_topic_plus_x() {
let check = RejectBinaries::default();
let result = run_topic_check("test_reject_binaries_topic_plus_x", BAD_COMMIT_EXE, check);
test_result_errors(
result,
&[
"adds the AR binary `ar-header`.",
"adds the ELF binary `elf-header`.",
"adds the Mach-O binary `macho-cigam-header`.",
"adds the Mach-O binary `macho-fat-cigam-header`.",
"adds the Mach-O binary `macho-fat-magic-header`.",
"adds the Mach-O binary `macho-magic-header`.",
],
);
}
#[test]
fn test_reject_binaries_topic_fixed() {
let check = RejectBinaries::default();
run_topic_check_ok("test_reject_binaries_topic_fixed", FIX_COMMIT, check);
}
#[test]
fn test_reject_binaries_topic_attr_fixed() {
let check = RejectBinaries::default();
run_topic_check_ok(
"test_reject_binaries_topic_attr_fixed",
FIX_ATTR_COMMIT,
check,
);
}
}