Compare commits

..

No commits in common. "948d3763b51bf084bca4605c2a3de7cd41d2d203" and "0c157927b893567f6692754a545e1509f02fc6c0" have entirely different histories.

4 changed files with 28 additions and 41 deletions

View File

@ -5,7 +5,6 @@ use rayon::ThreadPoolBuilder;
use crate::unit::Unit; use crate::unit::Unit;
use std::fs::{symlink_metadata, Metadata}; use std::fs::{symlink_metadata, Metadata};
use std::os::unix::fs::MetadataExt;
use std::path::{Component, Path}; use std::path::{Component, Path};
use std::slice::Iter; use std::slice::Iter;
use std::iter::once_with; use std::iter::once_with;
@ -32,7 +31,7 @@ pub struct Args {
#[arg( #[arg(
short, long, short, long,
help = "minimize output", help = "minimize output",
long_help = "print nothing but the total size for all directories, without a newline or units. Also supresses all error messages", long_help = "print nothing but the total size for all directories, without a newline. Also supresses all error messages",
conflicts_with = "total", conflicts_with = "total",
default_value_t = false, default_value_t = false,
)] )]
@ -73,7 +72,7 @@ pub struct Args {
#[arg( #[arg(
short, long, short, long,
help = "unit to print in", help = "unit to print in",
long_help = "printing unit (case insensitive): b = bytes, kb = kilobytes, ki = kibibytes, gb = gigabytes, gi = gibibytes, tb = terabytes, ti = tibibytes, blk/blks/blck/blcks/block/blocks = file system blocks", long_help = "printing unit (case insensitive): b = bytes, kb = kilobytes, ki = kibibytes, gb = gigabytes, gi = gibibytes, tb = terabytes, ti = tibibytes",
value_parser = Unit::parse, value_parser = Unit::parse,
default_value_t = Unit::Byte, default_value_t = Unit::Byte,
conflicts_with_all = ["base_two","si"], conflicts_with_all = ["base_two","si"],
@ -130,7 +129,7 @@ pub struct Args {
help = "items to summate", help = "items to summate",
action = ArgAction::Append, action = ArgAction::Append,
)] )]
paths: Vec<String>, path: Vec<String>,
} }
impl Args { impl Args {
/// utility method to chuck default values on the end. /// utility method to chuck default values on the end.
@ -147,8 +146,8 @@ impl Args {
self.exclude_print.clear(); self.exclude_print.clear();
} }
if self.paths.is_empty() { if self.path.is_empty() {
self.paths = vec![ ".".to_owned() ]; self.path = vec![ ".".to_owned() ];
} }
ThreadPoolBuilder::new() ThreadPoolBuilder::new()
@ -159,13 +158,6 @@ impl Args {
self self
} }
pub fn len(&self, meta: &Metadata) -> u64 {
match self.unit {
Unit::Blocks => meta.blocks(),
_ => meta.len(),
}
}
pub fn should_exclude(&self, path: &Path, file: &Metadata) -> bool { pub fn should_exclude(&self, path: &Path, file: &Metadata) -> bool {
if !self.follow_links if !self.follow_links
&& file.is_symlink() && file.is_symlink()
@ -210,7 +202,7 @@ impl Args {
} }
pub fn paths(&self) -> Iter<'_, String> { pub fn paths(&self) -> Iter<'_, String> {
self.paths.iter() self.path.iter()
} }
} }
@ -236,7 +228,7 @@ fn any_pattern_matches_any_component(patterns: &[Pattern], path: &Path) -> bool
continue continue
}; };
let Some(s) = cmp.to_str() else { let Some(s) = cmp.to_str() else {
// TODO: this is a code smell // this is a code smell
// I don't believe it, but I can't think // I don't believe it, but I can't think
// of anything worthwhile to do when // of anything worthwhile to do when
// you can't get a usable &str // you can't get a usable &str

View File

@ -21,6 +21,11 @@ impl Directory {
self.size self.size
} }
#[inline]
pub fn path(&self) -> &Path {
self.name.as_ref()
}
pub fn new< P: AsRef<Path> >(path: P, args: &Args) -> Result<Option<Self>> { pub fn new< P: AsRef<Path> >(path: P, args: &Args) -> Result<Option<Self>> {
let path = path.as_ref(); let path = path.as_ref();
// NOTE: I go back and forth on canonicalize()ing all the time. // NOTE: I go back and forth on canonicalize()ing all the time.
@ -41,7 +46,6 @@ impl Directory {
// symlink_metadata() is the same as metadata() but it doesn't // symlink_metadata() is the same as metadata() but it doesn't
// traverse symlinks, so that we can exclude them if necessary // traverse symlinks, so that we can exclude them if necessary
// note: sizeof(Metadata) == 176
let meta = match path.symlink_metadata() { let meta = match path.symlink_metadata() {
Ok(md) => md, Ok(md) => md,
Err(_) if args.persistant() => return Ok(None), Err(_) if args.persistant() => return Ok(None),
@ -62,7 +66,7 @@ impl Directory {
return Ok(Some( return Ok(Some(
Self { Self {
name, name,
size: args.len(&meta), size: meta.len(),
children: Vec::new() children: Vec::new()
} }
)) ))
@ -81,7 +85,7 @@ impl Directory {
(Err(e), false) => return Err(e), (Err(e), false) => return Err(e),
}; };
size += dir.size; size += dir.size;
if args.tree() && args.should_print(&dir.name) { if args.tree() && args.should_print(dir.path()) {
// since size was increased, this just prevents // since size was increased, this just prevents
// the directory from appearing in printing // the directory from appearing in printing
children.push(dir); children.push(dir);
@ -140,7 +144,7 @@ impl Directory {
pub fn tree(self, unit: Unit) -> String { pub fn tree(self, unit: Unit) -> String {
// since self.size is definitionally the greatest value, the tab length // since self.size is definitionally the greatest value, the tab length
// is just the length of self.len, plus two for a tab width // is just the length of self.len, plus two for a tab width
let tab_size = unit.convert_with_units(self.size).len() + 2; let tab_size = unit.convert(self.size).len() + 2;
self.vectorise(unit) self.vectorise(unit)
.iter() .iter()
.map(|e| e.stringify_tabbed(tab_size)) .map(|e| e.stringify_tabbed(tab_size))
@ -205,7 +209,7 @@ impl TreeEntry {
} }
fn stringify_tabbed(&self, tab_size: usize) -> String { fn stringify_tabbed(&self, tab_size: usize) -> String {
let mut result = format!("{:<tab_size$}", self.unit.convert_with_units(self.size)); let mut result = format!("{:<tab_size$}", self.unit.convert(self.size));
for part in self.parts.iter().rev() { for part in self.parts.iter().rev() {
result += part.display(); result += part.display();

View File

@ -42,17 +42,17 @@ fn main() -> ExitCode {
println!( println!(
"{}: {}", "{}: {}",
path, path,
args.unit().convert_with_units(dir_structure.size()) args.unit().convert(dir_structure.size())
); );
} }
} }
let total = args.unit().convert(total);
if args.total() { if args.total() {
let total = args.unit().convert_with_units(total);
println!("total: {total}"); println!("total: {total}");
} }
else if args.minimal() { else if args.minimal() {
let total = args.unit().convert(total);
print!("{total}"); print!("{total}");
} }

View File

@ -34,22 +34,19 @@ impl Unit {
"blk" | "blks" "blk" | "blks"
| "blck" |"blcks" | "blck" |"blcks"
| "block" | "blocks" => Ok(Self::Blocks), | "block" | "blocks" => Ok(Self::Blocks),
_ => Err("use --help to get a list of units".into()), _ => Err(s),
} }
} }
pub fn convert(self, n: u64) -> String { pub fn convert(self, n: u64) -> String {
format!("{}", n/self.integer_value()) let n = if self == Self::Blocks {
n.next_multiple_of(self.integer_value())
} else {
n
};
format!("{}{}", n/self.integer_value(), self.units_pretty())
} }
pub fn convert_with_units(self, n: u64) -> String {
self.convert(n) + self.units_pretty()
}
/// Units to print for each different unit.
/// They all have a space between at the front
/// for style reasons, except for bytes which are
/// basically unindicated
const fn units_pretty(self) -> &'static str { const fn units_pretty(self) -> &'static str {
match self { match self {
Self::Byte => "", Self::Byte => "",
@ -65,16 +62,9 @@ impl Unit {
} }
} }
/// The size is always held in bytes, so
/// this returns the scale factor.
/// A special case is made for
/// blocks, because the number of blocks
/// is repeatedly queried throughout
/// the search process, it needn't be
/// altered here
const fn integer_value(self) -> u64 { const fn integer_value(self) -> u64 {
match self { match self {
Self::Byte | Self::Blocks => 1, Self::Byte => 1,
Self::Kilo => 1_000, Self::Kilo => 1_000,
Self::Kibi => 1_024, Self::Kibi => 1_024,
Self::Mega => 1_000_000, Self::Mega => 1_000_000,
@ -83,6 +73,7 @@ impl Unit {
Self::Gibi => 1_073_741_824, Self::Gibi => 1_073_741_824,
Self::Tera => 1_000_000_000_000, Self::Tera => 1_000_000_000_000,
Self::Tibi => 1_099_511_627_776, Self::Tibi => 1_099_511_627_776,
Self::Blocks => 512,
} }
} }
} }