mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Merge pull request #2358 from siebenHeaven/du_threshold
Implement du threshold argument handling
This commit is contained in:
commit
b6f27a9a63
2 changed files with 91 additions and 13 deletions
|
@ -28,6 +28,7 @@ use std::os::windows::io::AsRawHandle;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
use uucore::parse_size::{parse_size, ParseSizeError};
|
use uucore::parse_size::{parse_size, ParseSizeError};
|
||||||
use uucore::InvalidEncodingHandling;
|
use uucore::InvalidEncodingHandling;
|
||||||
|
@ -56,6 +57,7 @@ mod options {
|
||||||
pub const BLOCK_SIZE_1M: &str = "m";
|
pub const BLOCK_SIZE_1M: &str = "m";
|
||||||
pub const SEPARATE_DIRS: &str = "S";
|
pub const SEPARATE_DIRS: &str = "S";
|
||||||
pub const SUMMARIZE: &str = "s";
|
pub const SUMMARIZE: &str = "s";
|
||||||
|
pub const THRESHOLD: &str = "threshold";
|
||||||
pub const SI: &str = "si";
|
pub const SI: &str = "si";
|
||||||
pub const TIME: &str = "time";
|
pub const TIME: &str = "time";
|
||||||
pub const TIME_STYLE: &str = "time-style";
|
pub const TIME_STYLE: &str = "time-style";
|
||||||
|
@ -510,6 +512,17 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
.long(options::ONE_FILE_SYSTEM)
|
.long(options::ONE_FILE_SYSTEM)
|
||||||
.help("skip directories on different file systems")
|
.help("skip directories on different file systems")
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::THRESHOLD)
|
||||||
|
.short("t")
|
||||||
|
.long(options::THRESHOLD)
|
||||||
|
.alias("th")
|
||||||
|
.value_name("SIZE")
|
||||||
|
.number_of_values(1)
|
||||||
|
.allow_hyphen_values(true)
|
||||||
|
.help("exclude entries smaller than SIZE if positive, \
|
||||||
|
or entries greater than SIZE if negative")
|
||||||
|
)
|
||||||
// .arg(
|
// .arg(
|
||||||
// Arg::with_name("")
|
// Arg::with_name("")
|
||||||
// .short("x")
|
// .short("x")
|
||||||
|
@ -586,6 +599,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
|
|
||||||
let block_size = u64::try_from(read_block_size(matches.value_of(options::BLOCK_SIZE))).unwrap();
|
let block_size = u64::try_from(read_block_size(matches.value_of(options::BLOCK_SIZE))).unwrap();
|
||||||
|
|
||||||
|
let threshold = matches.value_of(options::THRESHOLD).map(|s| {
|
||||||
|
Threshold::from_str(s)
|
||||||
|
.unwrap_or_else(|e| crash!(1, "{}", format_error_message(e, s, options::THRESHOLD)))
|
||||||
|
});
|
||||||
|
|
||||||
let multiplier: u64 = if matches.is_present(options::SI) {
|
let multiplier: u64 = if matches.is_present(options::SI) {
|
||||||
1000
|
1000
|
||||||
} else {
|
} else {
|
||||||
|
@ -654,6 +672,11 @@ Try '{} --help' for more information.",
|
||||||
// See: http://linux.die.net/man/2/stat
|
// See: http://linux.die.net/man/2/stat
|
||||||
stat.blocks * 512
|
stat.blocks * 512
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if threshold.map_or(false, |threshold| threshold.should_exclude(size)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if matches.is_present(options::TIME) {
|
if matches.is_present(options::TIME) {
|
||||||
let tm = {
|
let tm = {
|
||||||
let secs = {
|
let secs = {
|
||||||
|
@ -720,6 +743,37 @@ Try '{} --help' for more information.",
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum Threshold {
|
||||||
|
Lower(u64),
|
||||||
|
Upper(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Threshold {
|
||||||
|
type Err = ParseSizeError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
let offset = if s.starts_with(&['-', '+'][..]) { 1 } else { 0 };
|
||||||
|
|
||||||
|
let size = u64::try_from(parse_size(&s[offset..])?).unwrap();
|
||||||
|
|
||||||
|
if s.starts_with('-') {
|
||||||
|
Ok(Threshold::Upper(size))
|
||||||
|
} else {
|
||||||
|
Ok(Threshold::Lower(size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Threshold {
|
||||||
|
fn should_exclude(&self, size: u64) -> bool {
|
||||||
|
match *self {
|
||||||
|
Threshold::Upper(threshold) => size > threshold,
|
||||||
|
Threshold::Lower(threshold) => size < threshold,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn format_error_message(error: ParseSizeError, s: &str, option: &str) -> String {
|
fn format_error_message(error: ParseSizeError, s: &str, option: &str) -> String {
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// GNU's du echos affected flag, -B or --block-size (-t or --threshold), depending user's selection
|
// GNU's du echos affected flag, -B or --block-size (-t or --threshold), depending user's selection
|
||||||
|
|
|
@ -80,19 +80,22 @@ fn _du_basics_subdir(s: &str) {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_du_invalid_size() {
|
fn test_du_invalid_size() {
|
||||||
new_ucmd!()
|
let args = &["block-size", "threshold"];
|
||||||
.arg("--block-size=1fb4t")
|
for s in args {
|
||||||
.arg("/tmp")
|
new_ucmd!()
|
||||||
.fails()
|
.arg(format!("--{}=1fb4t", s))
|
||||||
.code_is(1)
|
.arg("/tmp")
|
||||||
.stderr_only("du: invalid --block-size argument '1fb4t'");
|
.fails()
|
||||||
#[cfg(not(target_pointer_width = "128"))]
|
.code_is(1)
|
||||||
new_ucmd!()
|
.stderr_only(format!("du: invalid --{} argument '1fb4t'", s));
|
||||||
.arg("--block-size=1Y")
|
#[cfg(not(target_pointer_width = "128"))]
|
||||||
.arg("/tmp")
|
new_ucmd!()
|
||||||
.fails()
|
.arg(format!("--{}=1Y", s))
|
||||||
.code_is(1)
|
.arg("/tmp")
|
||||||
.stderr_only("du: --block-size argument '1Y' too large");
|
.fails()
|
||||||
|
.code_is(1)
|
||||||
|
.stderr_only(format!("du: --{} argument '1Y' too large", s));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -351,3 +354,24 @@ fn test_du_one_file_system() {
|
||||||
}
|
}
|
||||||
_du_basics_subdir(result.stdout_str());
|
_du_basics_subdir(result.stdout_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_du_threshold() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
|
||||||
|
let threshold = if cfg!(windows) { "7K" } else { "10K" };
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(format!("--threshold={}", threshold))
|
||||||
|
.succeeds()
|
||||||
|
.stdout_contains("links")
|
||||||
|
.stdout_does_not_contain("deeper");
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(format!("--threshold=-{}", threshold))
|
||||||
|
.succeeds()
|
||||||
|
.stdout_does_not_contain("links")
|
||||||
|
.stdout_contains("deeper");
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue