diff --git a/src/clidef.rs b/src/clidef.rs index 22cb267..5370926 100644 --- a/src/clidef.rs +++ b/src/clidef.rs @@ -54,8 +54,10 @@ pub fn cli(version: &'static str) -> Command { Arg::new("autodeps") .short('a') .long("autodeps") - .action(clap::ArgAction::SetTrue) - .help(format!("Include graph of package dependencies\n{}", "NOTE: This can increase the size, but might not always be useful".yellow())) + .default_value("none") + .value_name("mode") + .value_parser(["free", "clean", "tight", "none"]) + .help(format!("Auto-add package dependencies.\n{}", " NOTE: This can increase the size, but might not always be useful\n".yellow())) ) .arg( Arg::new("root") diff --git a/src/filters/resources.rs b/src/filters/resources.rs index 45b1e4f..723c81d 100644 --- a/src/filters/resources.rs +++ b/src/filters/resources.rs @@ -1,5 +1,5 @@ use super::{defs, intf::DataFilter}; -use crate::profile::Profile; +use crate::{procdata::Autodeps, profile::Profile}; use std::{ collections::HashSet, path::{Path, PathBuf}, @@ -7,13 +7,14 @@ use std::{ pub struct ResourcesDataFilter { data: Vec, + autodeps: Autodeps, remove_archives: bool, remove_images: bool, // not blobs (qcow2, raw etc) but images, like JPEG, PNG, XPM... } impl ResourcesDataFilter { - pub fn new(data: Vec, profile: Profile) -> Self { - let mut rdf = ResourcesDataFilter { data, remove_archives: false, remove_images: false }; + pub fn new(data: Vec, profile: Profile, autodeps: Autodeps) -> Self { + let mut rdf = ResourcesDataFilter { data, autodeps, remove_archives: false, remove_images: false }; if profile.filter_arc() { log::debug!("Removing archives"); rdf.remove_archives = true; @@ -87,9 +88,17 @@ impl ResourcesDataFilter { impl DataFilter for ResourcesDataFilter { fn filter(&self, data: &mut HashSet) { + if self.autodeps == Autodeps::Clean || self.autodeps == Autodeps::Tight { + log::info!("Automatically removing potential junk resources"); + } + let mut out: Vec = Vec::default(); for p in &self.data { - if self.filter_archives(p) || self.filter_images(p) { + if self.filter_archives(p) + || self.filter_images(p) + || ((self.autodeps == Autodeps::Clean || self.autodeps == Autodeps::Tight) + && ResourcesDataFilter::is_potential_junk(p.file_name().unwrap().to_str().unwrap())) + { continue; } out.push(p.to_owned()); diff --git a/src/main.rs b/src/main.rs index 04b2bf5..d900cdf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,7 +141,7 @@ fn main() -> Result<(), std::io::Error> { if let Err(err) = procdata::TintProcessor::new(rpth) .set_profile(get_profile(cli, ¶ms)) .set_dry_run(params.get_flag("dry-run")) - .set_autodeps(params.get_flag("autodeps")) + .set_autodeps(params.get_one::("autodeps").unwrap().to_string()) .start() { log::error!("{}", err); diff --git a/src/procdata.rs b/src/procdata.rs index cea1ecc..9b03179 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -14,18 +14,26 @@ use std::{ path::{Path, PathBuf}, }; +/// Autodependency mode +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Autodeps { + Undef, + Free, + Clean, + Tight, +} /// Main processing of profiles or other data #[derive(Clone)] pub struct TintProcessor { profile: Profile, root: PathBuf, dry_run: bool, - autodeps: bool, + autodeps: Autodeps, } impl TintProcessor { pub fn new(root: PathBuf) -> Self { - TintProcessor { profile: Profile::default(), root, dry_run: true, autodeps: false } + TintProcessor { profile: Profile::default(), root, dry_run: true, autodeps: Autodeps::Free } } /// Set configuration from a profile @@ -41,8 +49,14 @@ impl TintProcessor { } /// Set flag for automatic dependency tracing - pub fn set_autodeps(&mut self, ad: bool) -> &mut Self { - self.autodeps = ad; + pub fn set_autodeps(&mut self, ad: String) -> &mut Self { + match ad.as_str() { + "free" => self.autodeps = Autodeps::Free, + "clean" => self.autodeps = Autodeps::Clean, + "tight" => self.autodeps = Autodeps::Tight, + _ => self.autodeps = Autodeps::Undef, + } + self } @@ -160,7 +174,7 @@ impl TintProcessor { // and then let TextDataFilter removes what still should be removed. // The idea is to keep parts only relevant to the runtime. log::debug!("Filtering packages"); - let pscan = DebPackageScanner::new(false); // XXX: Maybe --autodeps=LEVEL to optionally include these too? + let pscan = DebPackageScanner::new(Autodeps::Undef); for p in self.profile.get_packages() { log::debug!("Getting content of package \"{}\"", p); paths.extend(pscan.get_package_contents(p.to_string())?); @@ -186,7 +200,8 @@ impl TintProcessor { // Remove resources log::debug!("Filtering resources"); - ResourcesDataFilter::new(paths.clone().into_iter().collect::>(), self.profile.to_owned()).filter(&mut paths); + ResourcesDataFilter::new(paths.clone().into_iter().collect::>(), self.profile.to_owned(), self.autodeps) + .filter(&mut paths); // Scan rootfs log::debug!("Scanning existing rootfs"); diff --git a/src/scanner/debpkg.rs b/src/scanner/debpkg.rs index cb0c248..0845d1a 100644 --- a/src/scanner/debpkg.rs +++ b/src/scanner/debpkg.rs @@ -1,7 +1,10 @@ -use crate::scanner::{ - general::{Scanner, ScannerCommons}, - tracedeb, - traceitf::PkgDepTrace, +use crate::{ + procdata::Autodeps, + scanner::{ + general::{Scanner, ScannerCommons}, + tracedeb, + traceitf::PkgDepTrace, + }, }; use colored::Colorize; use std::{ @@ -13,12 +16,12 @@ use std::{ /// a target belongs to. pub struct DebPackageScanner { commons: ScannerCommons, - autodeps: bool, + autodeps: Autodeps, } impl DebPackageScanner { /// Constructor - pub fn new(autodeps: bool) -> Self { + pub fn new(autodeps: Autodeps) -> Self { DebPackageScanner { commons: ScannerCommons::new(), autodeps } } @@ -106,7 +109,7 @@ impl Scanner for DebPackageScanner { } } - if self.autodeps { + if self.autodeps == Autodeps::Clean || self.autodeps == Autodeps::Free { // Trace dependencies graph for the package for p in tracedeb::DebPackageTrace::new().trace(pkgname.to_owned()) { log::info!("Keeping dependency package: {}", p.bright_yellow());