mirror of
https://github.com/bootandy/dust.git
synced 2025-12-12 07:40:40 -08:00
* v1.0 * renamed operations to be more clear * put info later because there is still operations par of the preparing process * updated the last line clearing * changed name of module and structs to ones that make more sens * Disable size computation when file_count option is set * added sleep during the thread waiting * use 1024 powered instead of 10 to compute showed number * include DS_Store * added files directories skipped information * small format update * implement the -H option * put wait back * remove PAtomicInfo since it's not used * cargo fmt * wrapped atomic operations to reduce overhead * updated comments * Use AtomicU64Wrapper instead of AtomicU64 in TotalSize * update size suffix * sto dividing size when larger than terabytes * Fix use_iso flag not be set properly * update properties display * some reformating * use stdout instead of print * Moved config instance into main because it's easier to read * merge base formatting into macro * update name to be more intuitive and separated math operations for more flexibility * print currently indexed path * cargo fmt * reset size between each target dirs * Access to TotalSize rather than it's inner * small comment change * Update sysinfo version to 0.26.7 * fix: update use of sysinfo.system System is now much quicker to start but requires an explicit call to refresh memory else it deafults to 0 (oops) * clippy: Fix new clippy * fix: bug where hard links could be double counted When running: dust dir_a dir_b if a file was hard linked in both dir_a and dir_b it would be double counted. This fix resolves this by keeping the shared hashmap around between runs for the second and subsequent arguments. https://github.com/bootandy/dust/issues/282 * Fix: depth=0 bug for multiple arguments https://github.com/bootandy/dust/issues/282 * refactor filter.rs * refactor filter.rs * refactor create AggregateData for filter.rs * feature: Support for dereference links -L follow du has -L flag which allows it to dereference or follow symlinks. Clone this feature into dust. https://github.com/bootandy/dust/issues/276 * refactor dir_walker I find this layout cleaner * v1.0 * changed name of module and structs to ones that make more sens * Disable size computation when file_count option is set * added files directories skipped information * implement the -H option * wrapped atomic operations to reduce overhead * used human_readable_number function in display module rather than our own * implemented progress disabling * cargo fmt & cargo clippy Co-authored-by: Guillaume Gomez <guillaume1.gomez@gmail.com> Co-authored-by: andy.boot <bootandy@gmail.com>
157 lines
5.4 KiB
Rust
157 lines
5.4 KiB
Rust
use clap::ArgMatches;
|
|
use config_file::FromConfigFile;
|
|
use serde::Deserialize;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
use crate::display::UNITS;
|
|
|
|
#[derive(Deserialize, Default)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct Config {
|
|
pub display_full_paths: Option<bool>,
|
|
pub display_apparent_size: Option<bool>,
|
|
pub reverse: Option<bool>,
|
|
pub no_colors: Option<bool>,
|
|
pub no_bars: Option<bool>,
|
|
pub skip_total: Option<bool>,
|
|
pub ignore_hidden: Option<bool>,
|
|
pub iso: Option<bool>,
|
|
pub min_size: Option<String>,
|
|
pub only_dir: Option<bool>,
|
|
pub disable_progress: Option<bool>,
|
|
}
|
|
|
|
impl Config {
|
|
pub fn get_no_colors(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.no_colors || options.is_present("no_colors")
|
|
}
|
|
pub fn get_disable_progress(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.disable_progress || options.is_present("disable_progress")
|
|
}
|
|
pub fn get_apparent_size(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.display_apparent_size || options.is_present("display_apparent_size")
|
|
}
|
|
pub fn get_ignore_hidden(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.ignore_hidden || options.is_present("ignore_hidden")
|
|
}
|
|
pub fn get_full_paths(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.display_full_paths || options.is_present("display_full_paths")
|
|
}
|
|
pub fn get_reverse(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.reverse || options.is_present("reverse")
|
|
}
|
|
pub fn get_no_bars(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.no_bars || options.is_present("no_bars")
|
|
}
|
|
pub fn get_iso(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.iso || options.is_present("iso")
|
|
}
|
|
pub fn get_skip_total(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.skip_total || options.is_present("skip_total")
|
|
}
|
|
pub fn get_min_size(&self, options: &ArgMatches, iso: bool) -> Option<usize> {
|
|
let size_from_param = options.value_of("min_size");
|
|
self._get_min_size(size_from_param, iso)
|
|
}
|
|
fn _get_min_size(&self, min_size: Option<&str>, iso: bool) -> Option<usize> {
|
|
let size_from_param = min_size.and_then(|a| convert_min_size(a, iso));
|
|
|
|
if size_from_param.is_none() {
|
|
self.min_size
|
|
.as_ref()
|
|
.and_then(|a| convert_min_size(a.as_ref(), iso))
|
|
} else {
|
|
size_from_param
|
|
}
|
|
}
|
|
pub fn get_only_dir(&self, options: &ArgMatches) -> bool {
|
|
Some(true) == self.only_dir || options.is_present("only_dir")
|
|
}
|
|
}
|
|
|
|
fn convert_min_size(input: &str, iso: bool) -> Option<usize> {
|
|
let chars_as_vec: Vec<char> = input.chars().collect();
|
|
match chars_as_vec.split_last() {
|
|
Some((last, start)) => {
|
|
let mut starts: String = start.iter().collect::<String>();
|
|
|
|
for (i, u) in UNITS.iter().rev().enumerate() {
|
|
if Some(*u) == last.to_uppercase().next() {
|
|
return match starts.parse::<usize>() {
|
|
Ok(pure) => {
|
|
let num: usize = if iso { 1000 } else { 1024 };
|
|
let marker = pure * num.pow((i + 1) as u32);
|
|
Some(marker)
|
|
}
|
|
Err(_) => {
|
|
eprintln!("Ignoring invalid min-size: {}", input);
|
|
None
|
|
}
|
|
};
|
|
}
|
|
}
|
|
starts.push(*last);
|
|
starts
|
|
.parse()
|
|
.map_err(|_| {
|
|
eprintln!("Ignoring invalid min-size: {}", input);
|
|
})
|
|
.ok()
|
|
}
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
fn get_config_locations(base: &Path) -> Vec<PathBuf> {
|
|
vec![
|
|
base.join(".dust.toml"),
|
|
base.join(".config").join("dust").join("config.toml"),
|
|
]
|
|
}
|
|
|
|
pub fn get_config() -> Config {
|
|
if let Some(home) = directories::BaseDirs::new() {
|
|
for path in get_config_locations(home.home_dir()) {
|
|
if path.exists() {
|
|
if let Ok(config) = Config::from_config_file(path) {
|
|
return config;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Config {
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
mod tests {
|
|
#[allow(unused_imports)]
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_conversion() {
|
|
assert_eq!(convert_min_size("55", false), Some(55));
|
|
assert_eq!(convert_min_size("12344321", false), Some(12344321));
|
|
assert_eq!(convert_min_size("95RUBBISH", false), None);
|
|
assert_eq!(convert_min_size("10K", false), Some(10 * 1024));
|
|
assert_eq!(convert_min_size("10M", false), Some(10 * 1024usize.pow(2)));
|
|
assert_eq!(convert_min_size("10M", true), Some(10 * 1000usize.pow(2)));
|
|
assert_eq!(convert_min_size("2G", false), Some(2 * 1024usize.pow(3)));
|
|
}
|
|
|
|
#[test]
|
|
fn test_min_size_from_config_applied_or_overridden() {
|
|
let c = Config {
|
|
min_size: Some("1K".to_owned()),
|
|
..Default::default()
|
|
};
|
|
assert_eq!(c._get_min_size(None, false), Some(1024));
|
|
assert_eq!(c._get_min_size(Some("2K"), false), Some(2048));
|
|
|
|
assert_eq!(c._get_min_size(None, true), Some(1000));
|
|
assert_eq!(c._get_min_size(Some("2K"), true), Some(2000));
|
|
}
|
|
}
|