use impl_prelude::*;
#[derive(Debug, Default, Clone, Copy)]
pub struct RejectBinaries;
impl RejectBinaries {
pub fn new() -> Self {
RejectBinaries
}
}
const ELF_MAGIC: &[u8] = &[0x7f, 0x45, 0x4c, 0x46]; const MACHO_MAGIC: &[u8] = &[0xcf, 0xfa, 0xed, 0xfe];
const MACHO_CIGAM: &[u8] = &[0xfe, 0xed, 0xfa, 0xcf];
const MACHO_FAT_MAGIC: &[u8] = &[0xca, 0xfe, 0xba, 0xbe];
const MACHO_FAT_CIGAM: &[u8] = &[0xbe, 0xba, 0xfe, 0xca];
impl ContentCheck for RejectBinaries {
fn name(&self) -> &str {
"reject-binaries"
}
fn check(&self, ctx: &CheckGitContext, content: &Content) -> Result<CheckResult> {
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()
.chain_err(|| "failed to contruct cat-file command")?;
let stdout = cat_file.stdout;
if stdout.starts_with(ELF_MAGIC) {
Some("ELF")
} else if stdout.starts_with(MACHO_MAGIC)
|| stdout.starts_with(MACHO_CIGAM)
|| stdout.starts_with(MACHO_FAT_MAGIC)
|| stdout.starts_with(MACHO_FAT_CIGAM) {
Some("Mach-O")
} else {
None
}
};
if let Some(binary_type) = binary_type {
if let Some(allowed_binary_type) = allowed_binary_type {
if allowed_binary_type != binary_type {
result.add_error(format!("{}adds the {} (not {}) binary `{}`.",
commit_prefix(content),
binary_type,
allowed_binary_type,
diff.name));
}
} else {
result.add_error(format!("{}adds the {} binary `{}`.",
commit_prefix(content),
binary_type,
diff.name));
}
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use checks::RejectBinaries;
use checks::test::*;
const BAD_COMMIT: &str = "e5e1e2c8db62ac8f50f249d3cf3f334ddf158936";
const BAD_COMMIT_EXE: &str = "261577469c6790190d866a928dc3bd8e91d238cf";
const FIX_COMMIT: &str = "b9d46ccc02c1d484e8b619e210226597591fbd35";
const ATTR_COMMIT: &str = "f5fd493ca51556d6cd0c42dfc8003925d77441f3";
const ATTR_COMMIT_BAD: &str = "71fa463c4bedeb40807b6c73b08ce207b0fe0309";
const FIX_ATTR_COMMIT: &str = "f534f59e97607581eb35eb10b65499ec3f44800b";
#[test]
fn test_reject_binaries() {
let check = RejectBinaries::new();
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`.",
]);
}
#[test]
fn test_reject_binaries_plus_x() {
let check = RejectBinaries::new();
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`.",
]);
}
#[test]
fn test_reject_binaries_attr_ok() {
let check = RejectBinaries::new();
run_check_ok("test_reject_binaries_attr_ok", ATTR_COMMIT, check)
}
#[test]
fn test_reject_binaries_attr_bad() {
let check = RejectBinaries::new();
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`.",
]);
}
#[test]
fn test_reject_binaries_topic() {
let check = RejectBinaries::new();
let result = run_topic_check("test_reject_binaries_topic", BAD_COMMIT, check);
test_result_errors(result, &[
"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::new();
run_topic_check_ok("test_reject_binaries_topic_attr_ok", ATTR_COMMIT, check)
}
#[test]
fn test_reject_binaries_topic_attr_bad() {
let check = RejectBinaries::new();
let result = run_topic_check("test_reject_binaries_topic_attr_bad", ATTR_COMMIT_BAD, check);
test_result_errors(result, &[
"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::new();
let result = run_topic_check("test_reject_binaries_topic_plus_x", BAD_COMMIT_EXE, check);
test_result_errors(result, &[
"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::new();
run_topic_check_ok("test_reject_binaries_topic_fixed", FIX_COMMIT, check);
}
#[test]
fn test_reject_binaries_topic_attr_fixed() {
let check = RejectBinaries::new();
run_topic_check_ok("test_reject_binaries_topic_attr_fixed", FIX_ATTR_COMMIT, check);
}
}