use impl_prelude::*;
#[derive(Debug, Clone, Copy)]
pub struct CheckSize {
max_size: usize,
}
impl CheckSize {
pub fn new(max_size: usize) -> Self {
Self {
max_size: max_size,
}
}
}
impl ContentCheck for CheckSize {
fn name(&self) -> &str {
"check-size"
}
fn check(&self, ctx: &CheckGitContext, content: &Content) -> Result<CheckResult> {
let mut result = CheckResult::new();
for diff in content.diffs() {
if let StatusChange::Deleted = diff.status {
continue;
}
if diff.new_mode == "160000" {
continue;
}
let size_attr = ctx.check_attr("hooks-max-size", diff.name.as_path())?;
let prefix = commit_prefix(content);
let max_size = match size_attr {
AttributeState::Unset => continue,
AttributeState::Value(ref v) => {
v.parse().unwrap_or_else(|_| {
result.add_error(format!("{}has an invalid value hooks-max-size={} for \
`{}`. The value must be an unsigned integer.",
prefix,
v,
diff.name));
self.max_size
})
},
_ => self.max_size,
};
let cat_file = ctx.git()
.arg("cat-file")
.arg("-s")
.arg(diff.new_blob.as_str())
.output()
.chain_err(|| "failed to construct cat-file command")?;
if !cat_file.status.success() {
bail!(ErrorKind::Git(format!("failed to get the size of the {} blob: {}",
diff.new_blob,
String::from_utf8_lossy(&cat_file.stderr))));
}
let new_size: usize = String::from_utf8_lossy(&cat_file.stdout)
.trim()
.parse()
.unwrap_or_else(|msg| {
result.add_error(format!("{}has the file `{}` which has a size which did not \
parse: {}",
prefix,
diff.name,
msg));
0
});
if new_size > max_size {
result.add_error(format!("{}creates blob {} at `{}` with size {} bytes ({:.2} \
KiB) which is greater than the maximum size {} bytes \
({:.2} KiB). If the file is intended to be committed, \
set the `hooks-max-size` attribute on its path.",
prefix,
diff.new_blob,
diff.name,
new_size,
new_size as f64 / 1024.,
max_size,
max_size as f64 / 1024.));
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use checks::CheckSize;
use checks::test::*;
const CHECK_SIZE_COMMIT: &str = "1464c62cc09b01a8e86a8512dd400b705c760c42";
const ADD_SUBMODULE_TOPIC: &str = "fe90ee22ae3ce4b4dc41f8d0876e59355ff1e21c";
const FIX_TOPIC: &str = "cb03f0d95897e93dcb089790f9cafd1ee7987922";
#[test]
fn test_check_size() {
let check = CheckSize::new(46);
let result = run_check("test_check_size", CHECK_SIZE_COMMIT, check);
test_result_errors(result, &[
"commit 1464c62cc09b01a8e86a8512dd400b705c760c42 creates blob \
921aae7a6949c74bc4bd53b4122fcd7ee3c819c6 at `no-value` with size 50 bytes (0.05 KiB) \
which is greater than the maximum size 46 bytes (0.04 KiB). If the file is intended \
to be committed, set the `hooks-max-size` attribute on its path.",
"commit 112e9b34401724bff57f68cf47c5065d4342b263 has an invalid value \
hooks-max-size=not-a-number for `bad-attr-value`. The value must be an unsigned \
integer.",
"commit a61fd3759b61a4a1f740f3fe656bc42151cefbdd creates blob \
293071f2f4dd15bb57904e08bf6529e748e4075a at `increased-limit` with size 273 bytes \
(0.27 KiB) which is greater than the maximum size 200 bytes (0.20 KiB). If the file \
is intended to be committed, set the `hooks-max-size` attribute on its path.",
"commit a61fd3759b61a4a1f740f3fe656bc42151cefbdd creates blob \
4fa03f0211ccd20b0285314d9469ccbee1edd81c at `large-file` with size 48 bytes (0.05 \
KiB) which is greater than the maximum size 46 bytes (0.04 KiB). If the file is \
intended to be committed, set the `hooks-max-size` attribute on its path.",
]);
}
#[test]
fn test_check_size_topic() {
let check = CheckSize::new(46);
let result = run_topic_check("test_check_size_topic", CHECK_SIZE_COMMIT, check);
test_result_errors(result, &[
"has an invalid value hooks-max-size=not-a-number for `bad-attr-value`. The value \
must be an unsigned integer.",
"creates blob 293071f2f4dd15bb57904e08bf6529e748e4075a at `increased-limit` with size \
273 bytes (0.27 KiB) which is greater than the maximum size 200 bytes (0.20 KiB). If \
the file is intended to be committed, set the `hooks-max-size` attribute on its \
path.",
"creates blob 4fa03f0211ccd20b0285314d9469ccbee1edd81c at `large-file` with size 48 \
bytes (0.05 KiB) which is greater than the maximum size 46 bytes (0.04 KiB). If the \
file is intended to be committed, set the `hooks-max-size` attribute on its path.",
"creates blob 921aae7a6949c74bc4bd53b4122fcd7ee3c819c6 at `no-value` with size \
50 bytes (0.05 KiB) which is greater than the maximum size 46 bytes (0.04 KiB). If \
the file is intended to be committed, set the `hooks-max-size` attribute on its \
path.",
]);
}
#[test]
fn test_check_size_submodule() {
let check = CheckSize::new(1024);
run_check_ok("test_check_size_submodule", ADD_SUBMODULE_TOPIC, check);
}
#[test]
fn test_check_size_topic_fixed() {
let check = CheckSize::new(46);
run_topic_check_ok("test_check_size_topic_fixed", FIX_TOPIC, check);
}
}