blob: fea87b101e98bf8ac78c8813094792a4e24cf2cc [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::operations::size_check::PackageSizeInfo;
use crate::util::read_config;
use anyhow::{format_err, Result};
use assembly_images_manifest::{BlobfsContents, Image, ImagesManifest};
use ffx_assembly_args::ProductSizeCheckArgs;
/// Verifies that the product budget is not exceeded.
pub fn verify_product_budgets(args: ProductSizeCheckArgs) -> Result<()> {
let images_manifest: ImagesManifest = read_config(&args.assembly_manifest)?;
let blobfs_contents = match extract_blobfs_contents(&images_manifest) {
Some(contents) => contents,
None => {
log::info!("No blobfs image was found in {}", args.assembly_manifest.to_string_lossy());
return Ok(());
}
};
let max_contents_size = blobfs_contents
.maximum_contents_size
.ok_or(format_err!("BlobFS max_contents_size is not specified in images manifest"))?;
let package_sizes = calculate_package_sizes(&blobfs_contents)?;
let total_blobfs_size = calculate_total_blobfs_size(&blobfs_contents)?;
let contents_fit = total_blobfs_size <= max_contents_size;
if let Some(base_assembly_manifest) = args.base_assembly_manifest {
let other_images_manifest = read_config(&base_assembly_manifest)?;
let other_blobfs_contents =
extract_blobfs_contents(&other_images_manifest).ok_or(format_err!(
"Attempted to diff with {} which does not contain a blobfs image",
base_assembly_manifest.to_string_lossy()
))?;
let other_package_sizes = calculate_package_sizes(&other_blobfs_contents)?;
print_size_diff(&package_sizes, &other_package_sizes);
} else if args.verbose || !contents_fit {
print_verbose_output(&package_sizes);
}
if contents_fit {
Ok(())
} else {
Err(format_err!(
"BlobFS contents size ({}) exceeds max_contents_size ({})",
total_blobfs_size,
max_contents_size
))
}
}
/// Extracts the blobfs contents from the images manifest.
fn extract_blobfs_contents(images_manifest: &ImagesManifest) -> Option<&BlobfsContents> {
for image in &images_manifest.images {
if let Image::BlobFS { contents, .. } = image {
return Some(contents);
}
}
None
}
/// Calculates the size of each package in the blobfs image.
fn calculate_package_sizes(_blobfs_contents: &BlobfsContents) -> Result<Vec<PackageSizeInfo>> {
unimplemented!()
}
/// Calculates the total size of all the blobs in the blobfs image.
fn calculate_total_blobfs_size(_blobfs_contents: &BlobfsContents) -> Result<u64> {
unimplemented!()
}
/// Prints the size of the contents of the blobfs image broken down by package and blob
/// sorted by package sizes.
fn print_verbose_output(_package_sizes: &Vec<PackageSizeInfo>) {
unimplemented!()
}
/// Prints the difference between the contents of two blobfs images broken down by package
/// and blob sorted by the amount of change in size.
fn print_size_diff(
_package_sizes: &Vec<PackageSizeInfo>,
_other_package_sizes: &Vec<PackageSizeInfo>,
) {
unimplemented!()
}
#[cfg(test)]
mod tests {
use crate::operations::size_check_product::extract_blobfs_contents;
use anyhow::Result;
use assembly_images_manifest::{
BlobfsContents, Image, ImagesManifest, PackageMetadata, PackageSetMetadata,
PackagesMetadata,
};
#[test]
fn extract_blobfs_contents_test() -> Result<()> {
let blobfs_contents = BlobfsContents {
packages: PackagesMetadata {
base: PackageSetMetadata(vec![PackageMetadata {
name: "hello".to_string(),
manifest: "path".into(),
blobs: Default::default(),
}]),
cache: PackageSetMetadata(vec![]),
},
maximum_contents_size: Some(1234),
blobs: Default::default(),
};
let mut images_manifest = ImagesManifest {
images: vec![Image::VBMeta("a/b/c".into()), Image::FVM("x/y/z".into())],
};
assert_eq!(extract_blobfs_contents(&images_manifest), None);
images_manifest
.images
.push(Image::BlobFS { path: "path/to/blob.blk".into(), contents: blobfs_contents });
let blobfs_contents =
extract_blobfs_contents(&images_manifest).expect("blobfs contents is found");
assert_eq!(blobfs_contents.maximum_contents_size, Some(1234));
Ok(())
}
}