Implement option to compress packages

This commit is contained in:
Wildan M 2026-03-09 19:39:15 +07:00
parent a0d3bccf5f
commit e38ff447b9
No known key found for this signature in database
GPG Key ID: 01AC53185C679C79
4 changed files with 54 additions and 9 deletions

View File

@ -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 {

View File

@ -16,6 +16,8 @@ pub struct CookConfigOpt {
pub logs: Option<bool>,
/// whether to ignore build errors
pub nonstop: Option<bool>,
/// whether to archive packages with compressed format
pub compressed: Option<bool>,
/// whether to print verbose logs to certain commands
/// build failure still be printed anyway
pub verbose: Option<bool>,
@ -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<CookConfigOpt> 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));
}

View File

@ -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<PathBuf>,
auto_deps: &BTreeSet<PackageName>,
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,

View File

@ -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())
}