From ebcb9ef2e8c137c5ed6811046a01d87b9d6d351e Mon Sep 17 00:00:00 2001 From: Joey Riches Date: Wed, 17 Jul 2024 23:02:57 +0100 Subject: [PATCH] boulder/analysis: Add compress man handler compresses man/info pages --- Cargo.lock | 1 + boulder/Cargo.toml | 1 + boulder/src/package/analysis.rs | 1 + boulder/src/package/analysis/handler.rs | 78 ++++++++++++++++++++++++- crates/stone_recipe/src/lib.rs | 2 + 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0140223a8..3bd4b6186 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -249,6 +249,7 @@ dependencies = [ "tui", "url", "yaml", + "zstd", ] [[package]] diff --git a/boulder/Cargo.toml b/boulder/Cargo.toml index 3ae914e52..730b47460 100644 --- a/boulder/Cargo.toml +++ b/boulder/Cargo.toml @@ -43,3 +43,4 @@ strum.workspace = true thiserror.workspace = true tokio.workspace = true url.workspace = true +zstd.workspace = true diff --git a/boulder/src/package/analysis.rs b/boulder/src/package/analysis.rs index 19b89cb4c..7426eed75 100644 --- a/boulder/src/package/analysis.rs +++ b/boulder/src/package/analysis.rs @@ -38,6 +38,7 @@ impl<'a> Chain<'a> { Box::new(handler::elf), Box::new(handler::pkg_config), Box::new(handler::cmake), + Box::new(handler::compressman), // Catch-all if not excluded Box::new(handler::include_any), ], diff --git a/boulder/src/package/analysis/handler.rs b/boulder/src/package/analysis/handler.rs index b6d11c098..6a505c0c2 100644 --- a/boulder/src/package/analysis/handler.rs +++ b/boulder/src/package/analysis/handler.rs @@ -1,5 +1,13 @@ -use std::{path::PathBuf, process::Command}; - +use std::fs::File; +use std::io::{BufReader, BufWriter, Write}; +use std::{ + fs, + os::unix::fs::symlink, + path::{Component, PathBuf}, + process::Command, +}; + +use itertools::Itertools; use moss::{dependency, Dependency, Provider}; use crate::package::collect::PathInfo; @@ -134,3 +142,69 @@ pub fn cmake(bucket: &mut BucketMut, info: &mut PathInfo) -> Result Result { + if !bucket.recipe.parsed.options.compressman { + return Ok(Decision::NextHandler.into()); + } + + let is_man_file = info.path.components().contains(&Component::Normal("man".as_ref())) + && info.file_name().ends_with(|c| ('1'..'9').contains(&c)); + let is_info_file = + info.path.components().contains(&Component::Normal("info".as_ref())) && info.file_name().ends_with(".info"); + + if !(is_man_file || is_info_file) { + return Ok(Decision::NextHandler.into()); + } + + let mut generated_path = PathBuf::new(); + + /* If we have a man/info symlink update the link to the compressed file */ + if info.path.is_symlink() { + let new_original = format!("{}.zst", fs::canonicalize(&info.path)?.display()); + let new_link = format!("{}.zst", &info.path.display()); + + /* + * Depending on the order the files get analysed the new compressed file may not yet exist, + * compress it _now_ so the correct metadata src info is returned to the binary writer. + */ + if !std::path::Path::new(&new_original).exists() { + let compressed_file = compress_file_zstd(fs::canonicalize(&info.path)?)?; + let _ = bucket.paths.install().guest.join(compressed_file); + } + + symlink(format!("{}.zst", fs::read_link(&info.path)?.display()), &new_link)?; + generated_path.push(bucket.paths.install().guest.join(new_link)); + return Ok(Decision::ReplaceFile { + newpath: generated_path, + } + .into()); + } + + let mut compressed_file = PathBuf::from(format!("{}.zst", info.path.display())); + + /* We may have already compressed the file if we encountered a symlink to this file first */ + if !&compressed_file.exists() { + compressed_file = compress_file_zstd(info.path.clone())?; + } + + generated_path.push(bucket.paths.install().guest.join(compressed_file)); + + pub fn compress_file_zstd(path: PathBuf) -> Result { + let output_path = PathBuf::from(format!("{}.zst", path.display())); + let input = File::create(&output_path)?; + let mut reader = BufReader::new(File::open(&path)?); + let mut writer = BufWriter::new(input); + + zstd::stream::copy_encode(&mut reader, &mut writer, 16)?; + + writer.flush()?; + + Ok(output_path) + } + + Ok(Decision::ReplaceFile { + newpath: generated_path, + } + .into()) +} diff --git a/crates/stone_recipe/src/lib.rs b/crates/stone_recipe/src/lib.rs index b0565b609..d1d3cd07f 100644 --- a/crates/stone_recipe/src/lib.rs +++ b/crates/stone_recipe/src/lib.rs @@ -93,6 +93,8 @@ pub struct Options { pub strip: bool, #[serde(default, deserialize_with = "stringy_bool")] pub networking: bool, + #[serde(default, deserialize_with = "stringy_bool")] + pub compressman: bool, } #[derive(Debug, Clone, Deserialize)]