From a06953b3e3d2091aa09cc100c8d43725f34b9a77 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 31 Oct 2023 20:54:02 +0100 Subject: [PATCH 01/20] Enable additional two filters from the CLI --- src/clidef.rs | 6 ++++++ src/main.rs | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/clidef.rs b/src/clidef.rs index 512268e..5474598 100644 --- a/src/clidef.rs +++ b/src/clidef.rs @@ -78,6 +78,12 @@ pub fn cli(version: &'static str) -> Command { .arg( Arg::new("f_log").long("logs").action(clap::ArgAction::SetTrue).help("Leave any kind of logs") ) + .arg( + Arg::new("f_img").long("pic").action(clap::ArgAction::SetTrue).help("Leave any graphics (pictures)") + ) + .arg( + Arg::new("f_arc").long("arc").action(clap::ArgAction::SetTrue).help("Leave any kind of archives/tarballs") + ) // Other .next_help_heading("Other") diff --git a/src/main.rs b/src/main.rs index 1e79f5e..79bdfe8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,7 +54,9 @@ fn get_profile(mut cli: Command, params: &ArgMatches) -> Profile { .set_doc(f(params, "f_doc")) .set_i18n(f(params, "f_i18n")) .set_l10n(f(params, "f_l10n")) - .set_log(f(params, "f_log")); + .set_log(f(params, "f_log")) + .set_arch(f(params, "f_arc")) + .set_img(f(params, "f_pic")); } else if let Some(profile_path) = profile_path { log::info!("Getting profile at {profile_path}"); match Profile::new(Path::new(profile_path)) { @@ -80,6 +82,12 @@ fn get_profile(mut cli: Command, params: &ArgMatches) -> Profile { if is_f(params, "f_log") { profile.set_manpages(f(params, "f_log")); } + if is_f(params, "f_pic") { + profile.set_img(f(params, "f_pic")); + } + if is_f(params, "f_arc") { + profile.set_arch(f(params, "f_arc")); + } } Err(err) => { log::error!("{}", err); From 345e788e560a75cbdccc347319d8a2c5291c6954 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 31 Oct 2023 20:54:16 +0100 Subject: [PATCH 02/20] Add more logging --- src/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main.rs b/src/main.rs index 79bdfe8..5c9237d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -137,6 +137,9 @@ fn main() -> Result<(), std::io::Error> { log::error!("Mountpoint \"{}\" does not exist or is not accessible", rpth.to_str().unwrap().bright_yellow()); process::exit(exitcode::IOERR); } + + log::info!("Launching scanner and data processor"); + if let Err(err) = procdata::TintProcessor::new(rpth).set_profile(get_profile(cli, ¶ms)).set_dry_run(params.get_flag("dry-run")).start() { @@ -144,5 +147,11 @@ fn main() -> Result<(), std::io::Error> { process::exit(exitcode::IOERR); } + if params.get_flag("dry-run") { + log::warn!("This was a dry-run. Changes were not applied."); + } else { + log::info!("Finished. Hopefully it even works :-)"); + } + Ok(()) } From d7856712843f99caa3c25329e9c249ef0a8c56dd Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 31 Oct 2023 20:55:35 +0100 Subject: [PATCH 03/20] Add an experimental attempt to autogenerate profile suggestions --- src/clidef.rs | 8 ++++++ src/scanner/mod.rs | 2 ++ src/scanner/tracedeb.rs | 61 +++++++++++++++++++++++++++++++++++++++++ src/scanner/traceitf.rs | 4 +++ 4 files changed, 75 insertions(+) create mode 100644 src/scanner/tracedeb.rs create mode 100644 src/scanner/traceitf.rs diff --git a/src/clidef.rs b/src/clidef.rs index 5474598..64c5797 100644 --- a/src/clidef.rs +++ b/src/clidef.rs @@ -50,6 +50,14 @@ pub fn cli(version: &'static str) -> Command { .action(clap::ArgAction::SetTrue) .help("Do not remove anything, only display what will be removed") ) + .arg( + Arg::new("inspect") + .short('s') + .long("inspect") + .action(clap::ArgAction::SetTrue) + .help("Inspect a container to generate a possible profile") + .conflicts_with_all(["dry-run", "profile"]) + ) .arg( Arg::new("root") .short('r') diff --git a/src/scanner/mod.rs b/src/scanner/mod.rs index 1f257d5..61b128e 100644 --- a/src/scanner/mod.rs +++ b/src/scanner/mod.rs @@ -1,3 +1,5 @@ pub mod binlib; pub mod debpkg; pub mod general; +pub mod tracedeb; +pub mod traceitf; diff --git a/src/scanner/tracedeb.rs b/src/scanner/tracedeb.rs new file mode 100644 index 0000000..c95ee0f --- /dev/null +++ b/src/scanner/tracedeb.rs @@ -0,0 +1,61 @@ +use std::{collections::HashSet, process::Command}; + +use super::traceitf::PkgDepTrace; + +pub struct DebPackageTrace { + data: HashSet, +} + +impl DebPackageTrace { + pub fn new() -> Self { + DebPackageTrace { data: HashSet::default() } + } + + /// Get list of package dependencies for the first nearby level + /// + /// NOTE: currently it is quite bad way by hammering with apt, + /// but it works and is okey-ish for the time being. + /// This needs to be rewritten by slurping the entire /var/lib/dpkg/status + /// and the processing it at once. + fn get_dependencies(&mut self, pkg: String, start: bool) -> Vec { + if start { + self.data.clear(); + } + + let mut c = Command::new("apt"); + c.args(["depends", pkg.as_str()]); + + match c.output() { + Ok(out) => { + if let Ok(out) = String::from_utf8(out.stdout) { + for l in out.lines().map(|s| s.trim().to_string()).collect::>() { + if l.to_lowercase().starts_with("depends:") { + let l = l.split(" ").into_iter().collect::>(); + if l.len() > 2 { + let pkgname = l[1].to_string(); + if !self.data.contains(&pkgname) { + self.data.insert(pkgname.to_owned()); + self.get_dependencies(pkgname, false); + } + } + } + } + } + } + Err(err) => { + log::error!("Cannot get package dependencies: {}", err); + return vec![]; + } + } + + self.data.clone().into_iter().collect::>() + } +} + +impl PkgDepTrace for DebPackageTrace { + fn trace(&mut self, pkgname: String) -> Vec { + log::info!("Getting dependencies for a package {}", pkgname); + + self.get_dependencies(pkgname, true) + } +} diff --git a/src/scanner/traceitf.rs b/src/scanner/traceitf.rs new file mode 100644 index 0000000..f31b2eb --- /dev/null +++ b/src/scanner/traceitf.rs @@ -0,0 +1,4 @@ +/// Package dependency trace +pub trait PkgDepTrace { + fn trace(&mut self, pkgname: String) -> Vec; +} From 06ab1f6ace84bc296b408c2bb595ddbf80ad811f Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 31 Oct 2023 20:55:51 +0100 Subject: [PATCH 04/20] Fix imports --- src/scanner/debpkg.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scanner/debpkg.rs b/src/scanner/debpkg.rs index 760cd5e..d71f33b 100644 --- a/src/scanner/debpkg.rs +++ b/src/scanner/debpkg.rs @@ -1,4 +1,8 @@ -use crate::scanner::general::{Scanner, ScannerCommons}; +use crate::scanner::{ + general::{Scanner, ScannerCommons}, + tracedeb, + traceitf::PkgDepTrace, +}; use std::{ io::{Error, ErrorKind}, path::PathBuf, From 1e095130c2052c6d1336eec1d50129cc5fab15cc Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:53:56 +0100 Subject: [PATCH 05/20] Use "autodeps" as just a helper. Decision is to do not implement profile autogen feature. --- src/clidef.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/clidef.rs b/src/clidef.rs index 64c5797..42d933a 100644 --- a/src/clidef.rs +++ b/src/clidef.rs @@ -51,12 +51,11 @@ pub fn cli(version: &'static str) -> Command { .help("Do not remove anything, only display what will be removed") ) .arg( - Arg::new("inspect") - .short('s') - .long("inspect") + Arg::new("autodeps") + .short('a') + .long("autodeps") .action(clap::ArgAction::SetTrue) - .help("Inspect a container to generate a possible profile") - .conflicts_with_all(["dry-run", "profile"]) + .help(format!("Include graph of package dependencies\n{}", "NOTE: This can increase the size, but might not always be useful".yellow())) ) .arg( Arg::new("root") From 6c192285f07c0c96661f6164db18bc337b6d9691 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:54:18 +0100 Subject: [PATCH 06/20] Rename arg keyword for picture/graphics filter --- src/clidef.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clidef.rs b/src/clidef.rs index 42d933a..22cb267 100644 --- a/src/clidef.rs +++ b/src/clidef.rs @@ -86,7 +86,7 @@ pub fn cli(version: &'static str) -> Command { Arg::new("f_log").long("logs").action(clap::ArgAction::SetTrue).help("Leave any kind of logs") ) .arg( - Arg::new("f_img").long("pic").action(clap::ArgAction::SetTrue).help("Leave any graphics (pictures)") + Arg::new("f_pic").long("pic").action(clap::ArgAction::SetTrue).help("Leave any graphics (pictures)") ) .arg( Arg::new("f_arc").long("arc").action(clap::ArgAction::SetTrue).help("Leave any kind of archives/tarballs") From b6c9035642f3b0bea2843753a71a259b0ff678f6 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:55:45 +0100 Subject: [PATCH 07/20] Set autodeps mode --- src/main.rs | 7 +++++-- src/procdata.rs | 10 +++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5c9237d..0784c16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,8 +140,11 @@ fn main() -> Result<(), std::io::Error> { log::info!("Launching scanner and data processor"); - if let Err(err) = - procdata::TintProcessor::new(rpth).set_profile(get_profile(cli, ¶ms)).set_dry_run(params.get_flag("dry-run")).start() + 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")) + .start() { log::error!("{}", err); process::exit(exitcode::IOERR); diff --git a/src/procdata.rs b/src/procdata.rs index 409a0e1..75e2ed3 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -22,11 +22,12 @@ pub struct TintProcessor { profile: Profile, root: PathBuf, dry_run: bool, + autodeps: bool, } impl TintProcessor { pub fn new(root: PathBuf) -> Self { - TintProcessor { profile: Profile::default(), root, dry_run: true } + TintProcessor { profile: Profile::default(), root, dry_run: true, autodeps: false } } /// Set configuration from a profile @@ -35,11 +36,18 @@ impl TintProcessor { self } + /// Set dry-run flag (no actual writes on the target image) pub fn set_dry_run(&mut self, dr: bool) -> &mut Self { self.dry_run = dr; self } + /// Set flag for automatic dependency tracing + pub fn set_autodeps(&mut self, ad: bool) -> &mut Self { + self.autodeps = ad; + self + } + // Chroot to the mount point fn switch_root(&self) -> Result<(), Error> { unix::fs::chroot(self.root.to_str().unwrap())?; From 06fef96dde8b5fcc6c564d2cee35542f504fc1f0 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:56:12 +0100 Subject: [PATCH 08/20] Lintfix: split by a char, remove unnecessary iter() --- src/scanner/tracedeb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scanner/tracedeb.rs b/src/scanner/tracedeb.rs index c95ee0f..8b78745 100644 --- a/src/scanner/tracedeb.rs +++ b/src/scanner/tracedeb.rs @@ -30,7 +30,7 @@ impl DebPackageTrace { if let Ok(out) = String::from_utf8(out.stdout) { for l in out.lines().map(|s| s.trim().to_string()).collect::>() { if l.to_lowercase().starts_with("depends:") { - let l = l.split(" ").into_iter().collect::>(); + let l = l.split(' ').collect::>(); if l.len() > 2 { let pkgname = l[1].to_string(); if !self.data.contains(&pkgname) { From f1e0ef51b36838be1d8372f892c99ddcdf6b940f Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:56:30 +0100 Subject: [PATCH 09/20] Fix imports --- src/procdata.rs | 6 +++++- src/scanner/debpkg.rs | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/procdata.rs b/src/procdata.rs index 75e2ed3..a0ec60b 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -1,10 +1,13 @@ -use std::fs::{self, canonicalize, remove_file, DirEntry}; use std::{ collections::HashSet, io::Error, os::unix, path::{Path, PathBuf}, }; +use std::{ + fs::{self, canonicalize, remove_file, DirEntry}, + os::unix::prelude::PermissionsExt, +}; use crate::{ filters::{dirs::PathsDataFilter, intf::DataFilter, resources::ResourcesDataFilter, texts::TextDataFilter}, @@ -14,6 +17,7 @@ use crate::{ }; use bytesize::ByteSize; +use colored::Colorize; use filesize::PathExt; /// Main processing of profiles or other data diff --git a/src/scanner/debpkg.rs b/src/scanner/debpkg.rs index d71f33b..d18eb50 100644 --- a/src/scanner/debpkg.rs +++ b/src/scanner/debpkg.rs @@ -1,3 +1,5 @@ +use colored::Colorize; + use crate::scanner::{ general::{Scanner, ScannerCommons}, tracedeb, From 0fee80efadbb5540ba58da31d8a275a67b468e88 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:56:49 +0100 Subject: [PATCH 10/20] Move removed data to debug level --- src/procdata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/procdata.rs b/src/procdata.rs index a0ec60b..8ff242a 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -119,7 +119,7 @@ impl TintProcessor { for p in paths { total_size += p.size_on_disk_fast(&p.metadata().unwrap()).unwrap(); total_files += 1; - log::info!(" - {}", p.to_str().unwrap()); + log::debug!(" - {}", p.to_str().unwrap()); } println!("\nTotal files to be removed: {}, disk size freed: {}\n", total_files, ByteSize::b(total_size)); From 7603561e8796ee64560244c4e317c16782fc7327 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:57:26 +0100 Subject: [PATCH 11/20] Sort the result of traced packages, so they do not appear randomly listed --- src/scanner/tracedeb.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scanner/tracedeb.rs b/src/scanner/tracedeb.rs index 8b78745..600d820 100644 --- a/src/scanner/tracedeb.rs +++ b/src/scanner/tracedeb.rs @@ -48,7 +48,9 @@ impl DebPackageTrace { } } - self.data.clone().into_iter().collect::>() + let mut data = self.data.clone().into_iter().collect::>(); + data.sort(); + data } } From 94b8428fba540afae7523fd3867022d6b408bf87 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:57:59 +0100 Subject: [PATCH 12/20] Trace package dependencies if requested --- src/procdata.rs | 5 +++-- src/scanner/debpkg.rs | 31 +++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/procdata.rs b/src/procdata.rs index 8ff242a..721045c 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -155,7 +155,8 @@ impl TintProcessor { paths.extend(ElfScanner::new().scan(Path::new(target_path).to_owned())); log::debug!("Find package dependencies for {target_path}"); - paths.extend(DebPackageScanner::new().scan(Path::new(target_path).to_owned())); + // XXX: This will re-scan again and again, if target_path belongs to the same package + paths.extend(DebPackageScanner::new(self.autodeps).scan(Path::new(target_path).to_owned())); // Add the target itself paths.insert(Path::new(target_path).to_owned()); @@ -165,7 +166,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(); + let pscan = DebPackageScanner::new(false); // XXX: Maybe --autodeps=LEVEL to optionally include these too? for p in self.profile.get_packages() { log::debug!("Getting content of package \"{}\"", p); paths.extend(pscan.get_package_contents(p.to_string())?); diff --git a/src/scanner/debpkg.rs b/src/scanner/debpkg.rs index d18eb50..6edb402 100644 --- a/src/scanner/debpkg.rs +++ b/src/scanner/debpkg.rs @@ -14,12 +14,13 @@ use std::{ /// a target belongs to. pub struct DebPackageScanner { commons: ScannerCommons, + autodeps: bool, } impl DebPackageScanner { /// Constructor - pub fn new() -> Self { - DebPackageScanner { commons: ScannerCommons::new() } + pub fn new(autodeps: bool) -> Self { + DebPackageScanner { commons: ScannerCommons::new(), autodeps } } /// Expands target taking to the account Linux /bin symlinks to /usr/bin etc. @@ -90,20 +91,38 @@ impl DebPackageScanner { impl Scanner for DebPackageScanner { fn scan(&mut self, pth: PathBuf) -> Vec { log::debug!("Scanning package contents for {:?}", pth.to_str()); + + let mut out: Vec = vec![]; let pkgname = self.get_package_for(pth.to_str().unwrap().to_string()); if let Ok(Some(pkgname)) = pkgname { log::debug!("{} corresponds to {}", pth.to_str().unwrap(), pkgname); - match self.get_package_contents(pkgname) { + + match self.get_package_contents(pkgname.to_owned()) { Ok(fp) => { - return fp; + out.extend(fp); } Err(err) => { - log::error!("{}", err); + log::error!("Failed getting contents of {}: {}", pkgname, err); + } + } + + if self.autodeps { + // Trace dependencies graph for the package + for p in tracedeb::DebPackageTrace::new().trace(pkgname.to_owned()) { + log::info!("Keeping dependency package: {}", p.bright_yellow()); + match self.get_package_contents(p.to_owned()) { + Ok(fp) => { + out.extend(fp); + } + Err(err) => { + log::error!("Failed getting contents of {}: {}", p, err); + } + } } } } - vec![] + out } } From 9ecb32c9faa703394099deb1f8b3fa3bc6dfe1fb Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 17:58:43 +0100 Subject: [PATCH 13/20] Print image contents in a "ls -lah" fashion (initial) --- src/procdata.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/procdata.rs b/src/procdata.rs index 721045c..a5d077f 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -210,8 +210,26 @@ impl TintProcessor { self.dry_run(p)?; log::info!("Preserve:"); - for x in paths { - log::info!(" + {}", x.to_str().unwrap()); + for p in paths { + if p.is_dir() { + println!("{}", p.to_str().unwrap().bright_blue().bold()); + } + + if p.is_symlink() { + println!( + "{} -> {}", + p.to_str().unwrap().bright_cyan(), + p.read_link().unwrap().as_path().to_str().unwrap().blue() + ); + } + + if p.is_file() { + if p.metadata().unwrap().permissions().mode() & 0o111 != 0 { + println!("{}", format!("*{}", p.to_str().unwrap()).bright_green()); + } else { + println!("{}", p.to_str().unwrap()); + } + } } } else { self.apply_changes(p)?; From 3ca554c50e48fde9a7f3509f601a5db83aaaf68f Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 20:53:18 +0100 Subject: [PATCH 14/20] Implement data formatter --- src/scanner/dlst.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/scanner/dlst.rs diff --git a/src/scanner/dlst.rs b/src/scanner/dlst.rs new file mode 100644 index 0000000..48a7105 --- /dev/null +++ b/src/scanner/dlst.rs @@ -0,0 +1,77 @@ +/* +Data lister (fancy STDOUT printer) +*/ + +use std::{ + ops::Add, + os::unix::prelude::PermissionsExt, + path::{Path, PathBuf}, +}; + +use bytesize::ByteSize; +use colored::Colorize; + +/// ContentFormatter is a lister for finally gathered information, +/// that needs to be displayed on the screen for the user for review +pub struct ContentFormatter<'a> { + fs_data: &'a Vec, + last_dir: String, +} + +impl<'a> ContentFormatter<'a> { + pub(crate) fn new(fs_data: &'a Vec) -> Self { + ContentFormatter { fs_data, last_dir: "".to_string() } + } + + pub(crate) fn format(&mut self) { + let d_len = self.fs_data.len() - 1; + let mut t_size: u64 = 0; + for (pi, p) in self.fs_data.iter().enumerate() { + t_size += p.metadata().unwrap().len(); + let (dname, fname) = self.dn(p); + + if self.last_dir != dname { + self.last_dir = dname.to_owned(); + println!("\n{}", self.last_dir.bright_blue().bold()); + println!("{}", "──┬──┄┄╌╌ ╌ ╌".blue()); + } + + let mut leaf = " ├─"; + if pi == d_len { + leaf = " ╰─"; + } else if pi < d_len { + if dname != self.fs_data[pi + 1].parent().unwrap().to_str().unwrap().to_string() { + leaf = " ╰─"; + } + } + + if p.is_symlink() { + println!( + "{} {} {} {}", + leaf.blue(), + fname.bright_cyan().bold(), + "⮕".yellow().dimmed(), + p.read_link().unwrap().as_path().to_str().unwrap().cyan() + ); + } else if p.metadata().unwrap().permissions().mode() & 0o111 != 0 { + println!("{} {}", leaf.blue(), fname.bright_green().bold()); + } else { + println!("{} {}", leaf.blue(), fname); + } + } + + println!("\nPreserved {} files, taking space: {}\n", d_len + 1, ByteSize::b(t_size)); + } + + /// Get dir/name split, painted accordingly + fn dn(&mut self, p: &Path) -> (String, String) { + let dname = p.parent().unwrap().to_str().unwrap().to_string(); + let fname = p.file_name().unwrap().to_str().unwrap().to_string(); + + if p.is_dir() { + return (format!("{}", dname.bright_blue().bold()), "".to_string()); + } + + (dname, fname) + } +} From 773d859550c601e8f5728ed9a8fd446e13e886f2 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 20:53:43 +0100 Subject: [PATCH 15/20] Print dry-run results with formatter, dropping tempcode --- src/procdata.rs | 32 +++----------------------------- src/scanner/mod.rs | 1 + 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/procdata.rs b/src/procdata.rs index a5d077f..6ff4b96 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -1,23 +1,19 @@ +use std::fs::{self, canonicalize, remove_file, DirEntry}; use std::{ collections::HashSet, io::Error, os::unix, path::{Path, PathBuf}, }; -use std::{ - fs::{self, canonicalize, remove_file, DirEntry}, - os::unix::prelude::PermissionsExt, -}; use crate::{ filters::{dirs::PathsDataFilter, intf::DataFilter, resources::ResourcesDataFilter, texts::TextDataFilter}, profile::Profile, rootfs, - scanner::{binlib::ElfScanner, debpkg::DebPackageScanner, general::Scanner}, + scanner::{binlib::ElfScanner, debpkg::DebPackageScanner, dlst::ContentFormatter, general::Scanner}, }; use bytesize::ByteSize; -use colored::Colorize; use filesize::PathExt; /// Main processing of profiles or other data @@ -208,29 +204,7 @@ impl TintProcessor { if self.dry_run { self.dry_run(p)?; - - log::info!("Preserve:"); - for p in paths { - if p.is_dir() { - println!("{}", p.to_str().unwrap().bright_blue().bold()); - } - - if p.is_symlink() { - println!( - "{} -> {}", - p.to_str().unwrap().bright_cyan(), - p.read_link().unwrap().as_path().to_str().unwrap().blue() - ); - } - - if p.is_file() { - if p.metadata().unwrap().permissions().mode() & 0o111 != 0 { - println!("{}", format!("*{}", p.to_str().unwrap()).bright_green()); - } else { - println!("{}", p.to_str().unwrap()); - } - } - } + ContentFormatter::new(&paths).format(); } else { self.apply_changes(p)?; } diff --git a/src/scanner/mod.rs b/src/scanner/mod.rs index 61b128e..d25cc80 100644 --- a/src/scanner/mod.rs +++ b/src/scanner/mod.rs @@ -1,5 +1,6 @@ pub mod binlib; pub mod debpkg; +pub(crate) mod dlst; pub mod general; pub mod tracedeb; pub mod traceitf; From ef379c6bde96950bb79fd16e03c8cfa477ed6545 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 21:52:39 +0100 Subject: [PATCH 16/20] Remove unused import --- src/scanner/dlst.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/scanner/dlst.rs b/src/scanner/dlst.rs index 48a7105..dbe5cf1 100644 --- a/src/scanner/dlst.rs +++ b/src/scanner/dlst.rs @@ -3,7 +3,6 @@ Data lister (fancy STDOUT printer) */ use std::{ - ops::Add, os::unix::prelude::PermissionsExt, path::{Path, PathBuf}, }; From 87559ad5cbda03128a6da73aaa06f809823ecbea Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 22:19:35 +0100 Subject: [PATCH 17/20] Add "junk" constants --- src/filters/defs.rs | 23 +++++++++++++++++++++++ src/filters/mod.rs | 1 + 2 files changed, 24 insertions(+) create mode 100644 src/filters/defs.rs diff --git a/src/filters/defs.rs b/src/filters/defs.rs new file mode 100644 index 0000000..e6861bf --- /dev/null +++ b/src/filters/defs.rs @@ -0,0 +1,23 @@ +/* +Definitions, constants +*/ + +/// Stub doc files +pub const DOC_STUB_FILES: &[&str] = + &["AUTHORS", "COPYING", "LICENSE", "DEBUG", "DISTRIB", "DOC", "HISTORY", "README", "TERMS", "TODO"]; + +/// Docfiles +pub const DOC_F_EXT: &[&str] = &[".txt", ".doc", ".rtf", ".md", ".rtx", ".tex", ".xml"]; + +/// Docfiles portable +pub const DOC_FP_EXT: &[&str] = &[".eps", ".pdf", ".ps"]; + +/// Headers +pub const H_SRC_F_EXT: &[&str] = &[".h", ".hpp"]; + +/// Archives +pub const ARC_F_EXT: &[&str] = &[".gz", ".bz2", ".xz", ".zip", ".tar"]; + +/// Graphic files +pub const IMG_F_EXT: &[&str] = + &[".bmp", ".jpg", ".jpeg", ".png", ".gif", ".xpm", ".xbm", ".tif", ".tiff", ".pbm", ".svg", ".ico"]; diff --git a/src/filters/mod.rs b/src/filters/mod.rs index f384baf..48eda1e 100644 --- a/src/filters/mod.rs +++ b/src/filters/mod.rs @@ -1,3 +1,4 @@ +pub mod defs; pub mod dirs; pub mod intf; pub mod resources; From 76e5dd0da13d7be31da656cc898f2aa5675b480f Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 22:20:10 +0100 Subject: [PATCH 18/20] Move resources definitions to the constants --- src/filters/resources.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/filters/resources.rs b/src/filters/resources.rs index 4b3f448..8e162d0 100644 --- a/src/filters/resources.rs +++ b/src/filters/resources.rs @@ -5,7 +5,7 @@ use std::{ use crate::profile::Profile; -use super::intf::DataFilter; +use super::{defs, intf::DataFilter}; pub struct ResourcesDataFilter { data: Vec, @@ -37,7 +37,7 @@ impl ResourcesDataFilter { let p = p.to_str().unwrap(); - for s in [".gz", ".bz2", ".xz", ".zip", ".tar"] { + for s in defs::ARC_F_EXT { if p.ends_with(s) { return true; } @@ -53,7 +53,7 @@ impl ResourcesDataFilter { } let p = p.to_str().unwrap(); - for s in [".bmp", ".jpg", ".jpeg", ".png", ".gif", ".xpm", ".tif", ".tiff", ".pbm", ".svg", ".ico"] { + for s in defs::IMG_F_EXT { if p.ends_with(s) { return true; } From 9114691a35f44df273ad83c842fbdf944f990877 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 22:20:34 +0100 Subject: [PATCH 19/20] Detect potential junk, add more coloring --- src/scanner/dlst.rs | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/scanner/dlst.rs b/src/scanner/dlst.rs index dbe5cf1..7e161fd 100644 --- a/src/scanner/dlst.rs +++ b/src/scanner/dlst.rs @@ -10,6 +10,8 @@ use std::{ use bytesize::ByteSize; use colored::Colorize; +use crate::filters::defs::{self}; + /// ContentFormatter is a lister for finally gathered information, /// that needs to be displayed on the screen for the user for review pub struct ContentFormatter<'a> { @@ -27,7 +29,7 @@ impl<'a> ContentFormatter<'a> { let mut t_size: u64 = 0; for (pi, p) in self.fs_data.iter().enumerate() { t_size += p.metadata().unwrap().len(); - let (dname, fname) = self.dn(p); + let (dname, mut fname) = self.dn(p); if self.last_dir != dname { self.last_dir = dname.to_owned(); @@ -36,12 +38,8 @@ impl<'a> ContentFormatter<'a> { } let mut leaf = " ├─"; - if pi == d_len { + if pi == d_len || (pi < d_len && dname != self.fs_data[pi + 1].parent().unwrap().to_str().unwrap()) { leaf = " ╰─"; - } else if pi < d_len { - if dname != self.fs_data[pi + 1].parent().unwrap().to_str().unwrap().to_string() { - leaf = " ╰─"; - } } if p.is_symlink() { @@ -55,6 +53,12 @@ impl<'a> ContentFormatter<'a> { } else if p.metadata().unwrap().permissions().mode() & 0o111 != 0 { println!("{} {}", leaf.blue(), fname.bright_green().bold()); } else { + if fname.ends_with(".so") || fname.contains(".so.") { + fname = fname.green().to_string(); + } else if self.is_potential_junk(&fname) { + fname = format!("{} {}", "⚠️".bright_red().bold(), fname.bright_red()); + } + println!("{} {}", leaf.blue(), fname); } } @@ -62,6 +66,29 @@ impl<'a> ContentFormatter<'a> { println!("\nPreserved {} files, taking space: {}\n", d_len + 1, ByteSize::b(t_size)); } + fn is_potential_junk(&self, fname: &str) -> bool { + for ext in + defs::DOC_F_EXT.iter().chain(defs::ARC_F_EXT.iter()).chain(defs::H_SRC_F_EXT.iter()).chain(defs::DOC_FP_EXT.iter()) + { + if fname.ends_with(ext) { + return true; + } + } + + for sf in defs::DOC_STUB_FILES { + if fname == *sf { + return true; + } + } + + // Potentially doc stubfile that doesn't look like a known one + if fname == fname.to_uppercase() { + return true; + } + + false + } + /// Get dir/name split, painted accordingly fn dn(&mut self, p: &Path) -> (String, String) { let dname = p.parent().unwrap().to_str().unwrap().to_string(); From 6a7ca8593e4f184b86e91f94ef277f97842f6173 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 1 Nov 2023 22:24:08 +0100 Subject: [PATCH 20/20] Fix imports --- src/filters/resources.rs | 6 ++---- src/main.rs | 4 +--- src/procdata.rs | 16 +++++++--------- src/scanner/debpkg.rs | 3 +-- src/scanner/dlst.rs | 8 +++----- src/scanner/tracedeb.rs | 3 +-- 6 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/filters/resources.rs b/src/filters/resources.rs index 8e162d0..6c48916 100644 --- a/src/filters/resources.rs +++ b/src/filters/resources.rs @@ -1,12 +1,10 @@ +use super::{defs, intf::DataFilter}; +use crate::profile::Profile; use std::{ collections::HashSet, path::{Path, PathBuf}, }; -use crate::profile::Profile; - -use super::{defs, intf::DataFilter}; - pub struct ResourcesDataFilter { data: Vec, remove_archives: bool, diff --git a/src/main.rs b/src/main.rs index 0784c16..04b2bf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,9 @@ mod procdata; mod profile; mod rootfs; mod scanner; - +use crate::profile::Profile; use clap::{ArgMatches, Command}; use colored::Colorize; - -use crate::profile::Profile; use std::{ env, path::{Path, PathBuf}, diff --git a/src/procdata.rs b/src/procdata.rs index 6ff4b96..cea1ecc 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -1,20 +1,18 @@ -use std::fs::{self, canonicalize, remove_file, DirEntry}; -use std::{ - collections::HashSet, - io::Error, - os::unix, - path::{Path, PathBuf}, -}; - use crate::{ filters::{dirs::PathsDataFilter, intf::DataFilter, resources::ResourcesDataFilter, texts::TextDataFilter}, profile::Profile, rootfs, scanner::{binlib::ElfScanner, debpkg::DebPackageScanner, dlst::ContentFormatter, general::Scanner}, }; - use bytesize::ByteSize; use filesize::PathExt; +use std::fs::{self, canonicalize, remove_file, DirEntry}; +use std::{ + collections::HashSet, + io::Error, + os::unix, + path::{Path, PathBuf}, +}; /// Main processing of profiles or other data #[derive(Clone)] diff --git a/src/scanner/debpkg.rs b/src/scanner/debpkg.rs index 6edb402..cb0c248 100644 --- a/src/scanner/debpkg.rs +++ b/src/scanner/debpkg.rs @@ -1,10 +1,9 @@ -use colored::Colorize; - use crate::scanner::{ general::{Scanner, ScannerCommons}, tracedeb, traceitf::PkgDepTrace, }; +use colored::Colorize; use std::{ io::{Error, ErrorKind}, path::PathBuf, diff --git a/src/scanner/dlst.rs b/src/scanner/dlst.rs index 7e161fd..45edd64 100644 --- a/src/scanner/dlst.rs +++ b/src/scanner/dlst.rs @@ -2,16 +2,14 @@ Data lister (fancy STDOUT printer) */ +use crate::filters::defs::{self}; +use bytesize::ByteSize; +use colored::Colorize; use std::{ os::unix::prelude::PermissionsExt, path::{Path, PathBuf}, }; -use bytesize::ByteSize; -use colored::Colorize; - -use crate::filters::defs::{self}; - /// ContentFormatter is a lister for finally gathered information, /// that needs to be displayed on the screen for the user for review pub struct ContentFormatter<'a> { diff --git a/src/scanner/tracedeb.rs b/src/scanner/tracedeb.rs index 600d820..c9484b4 100644 --- a/src/scanner/tracedeb.rs +++ b/src/scanner/tracedeb.rs @@ -1,6 +1,5 @@ -use std::{collections::HashSet, process::Command}; - use super::traceitf::PkgDepTrace; +use std::{collections::HashSet, process::Command}; pub struct DebPackageTrace { data: HashSet,