diff --git a/src/bin/repo.rs b/src/bin/repo.rs index 82328676..ef8e50e7 100644 --- a/src/bin/repo.rs +++ b/src/bin/repo.rs @@ -69,6 +69,7 @@ const REPO_HELP_STR: &str = r#" COOKBOOK_OFFLINE=false prevent internet access if possible ignored when command "fetch" is used COOKBOOK_NONSTOP=false keep running even a recipe build failed + COOKBOOK_COMPRESSED=false build packages in compressed format COOKBOOK_VERBOSE=true print success/error on each recipe COOKBOOK_CLEAN_BUILD=false remove build directory before building COOKBOOK_CLEAN_TARGET=false remove target directory after building @@ -704,7 +705,7 @@ fn handle_cook( ) .map_err(|err| anyhow!("failed to build: {:?}", err))?; - package(&recipe, &stage_dirs, &auto_deps, logger) + package(&recipe, &stage_dirs, &auto_deps, &config.cook, logger) .map_err(|err| anyhow!("failed to package: {:?}", err))?; if config.cook.clean_target || config.cook.write_filetree { diff --git a/src/config.rs b/src/config.rs index 61e402e8..02347df0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,6 +16,8 @@ pub struct CookConfigOpt { pub logs: Option, /// whether to ignore build errors pub nonstop: Option, + /// whether to archive packages with compressed format + pub compressed: Option, /// whether to print verbose logs to certain commands /// build failure still be printed anyway pub verbose: Option, @@ -35,6 +37,7 @@ pub struct CookConfig { pub tui: bool, pub logs: bool, pub nonstop: bool, + pub compressed: bool, pub verbose: bool, pub clean_build: bool, pub clean_target: bool, @@ -49,6 +52,7 @@ impl From for CookConfig { tui: value.tui.unwrap(), logs: value.logs.unwrap(), nonstop: value.nonstop.unwrap(), + compressed: value.compressed.unwrap(), verbose: value.verbose.unwrap(), clean_build: value.clean_build.unwrap(), clean_target: value.clean_target.unwrap(), @@ -98,6 +102,9 @@ pub fn init_config() { if config.cook_opt.offline.is_none() { config.cook_opt.offline = Some(extract_env("COOKBOOK_OFFLINE", false)); } + if config.cook_opt.compressed.is_none() { + config.cook_opt.compressed = Some(extract_env("COOKBOOK_COMPRESSED", false)); + } if config.cook_opt.verbose.is_none() { config.cook_opt.verbose = Some(extract_env("COOKBOOK_VERBOSE", true)); } diff --git a/src/cook/package.rs b/src/cook/package.rs index 23b92972..1d76ec64 100644 --- a/src/cook/package.rs +++ b/src/cook/package.rs @@ -4,9 +4,12 @@ use std::{ }; use pkg::{Package, PackageName, PackagePrefix}; +use pkgar::ext::PackageSrcExt; +use pkgar_core::HeaderFlags; use crate::{ blake3::hash_to_hex, + config::CookConfig, cook::{fetch, fs::*, pty::PtyOut}, log_to_pty, recipe::{BuildKind, CookRecipe, OptionalPackageRecipe, Recipe}, @@ -16,6 +19,7 @@ pub fn package( recipe: &CookRecipe, stage_dirs: &Vec, auto_deps: &BTreeSet, + cook_config: &CookConfig, logger: &PtyOut, ) -> Result<(), String> { let name = &recipe.name; @@ -70,10 +74,17 @@ pub fn package( } if !package_file.is_file() { - pkgar::create( + pkgar::create_with_flags( secret_path, package_file.to_str().unwrap(), stage_dir.to_str().unwrap(), + HeaderFlags::latest( + pkgar_core::Architecture::Independent, + match cook_config.compressed { + true => pkgar_core::Packaging::LZMA2, + false => pkgar_core::Packaging::Uncompressed, + }, + ), ) .map_err(|err| format!("failed to create pkgar archive: {:?}", err))?; } @@ -130,12 +141,12 @@ pub fn package_toml( } } - let (hash, size) = if let Some((pkey_path, archive_path)) = package_file { + let (hash, network_size, storage_size) = if let Some((pkey_path, archive_path)) = package_file { use pkgar_core::PackageSrc; let pkey = pkgar_keys::PublicKeyFile::open(pkey_path) .map_err(|e| format!("Unable to read public key: {e:?}"))? .pkey; - let package = pkgar::PackageFile::new(archive_path, &pkey).map_err(|e| { + let mut package = pkgar::PackageFile::new(archive_path, &pkey).map_err(|e| { format!( "Unable to read packaged pkgar file {}: {e:?}", archive_path.display(), @@ -147,9 +158,34 @@ pub fn package_toml( archive_path.display(), ) })?; - (hash_to_hex(package.header().blake3), mt.len()) + let package_size = mt.len(); + let storage_size = match package.header().flags.packaging() { + pkgar_core::Packaging::LZMA2 => { + let mut size = 0; + let entries = package + .read_entries() + .map_err(|e| format!("Unable to get lzma entry: {e}"))?; + for entry in entries { + let data_reader = package + .data_reader(entry) + .map_err(|e| format!("Unable to read lzma entry: {e}"))?; + size += data_reader.unpacked_size; + package + .restore_reader(data_reader.into_inner()) + .map_err(|e| format!("Unable to put lzma entry: {e}"))?; + } + size + } + _ => package_size, + }; + + ( + hash_to_hex(package.header().blake3), + package_size, + storage_size, + ) } else { - ("".into(), 0) + ("".into(), 0, 0) }; let ident_source = fetch::fetch_get_source_info(recipe)?; @@ -159,9 +195,8 @@ pub fn package_toml( version: package_version(&recipe.recipe), target: recipe.target.to_string(), blake3: hash, - // this size will be different once pkgar supports compression - network_size: size, - storage_size: size, + network_size, + storage_size, depends: package_deps, commit_identifier: ident_source.commit_identifier, source_identifier: ident_source.source_identifier, diff --git a/src/recipe.rs b/src/recipe.rs index 003febe1..979ba9d6 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -241,6 +241,8 @@ impl CookRecipe { let fn_map = |p: PackageName| { if p.is_host() { if p.name() == thisname { None } else { Some(p) } + } else if p.is_target() { + None } else { Some(p.with_host()) }