From eea8d40e781f667fb66856d62cb7827df998deac Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 9 Apr 2023 21:12:39 +0200 Subject: [PATCH] du: add support of --dereference-args Should fix tests/du/deref.sh --- src/uu/du/src/du.rs | 40 ++++++++++++++++++++++++++++------------ tests/by-util/test_du.rs | 28 +++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index fb490888a..74d86219b 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -68,6 +68,7 @@ mod options { pub const TIME_STYLE: &str = "time-style"; pub const ONE_FILE_SYSTEM: &str = "one-file-system"; pub const DEREFERENCE: &str = "dereference"; + pub const DEREFERENCE_ARGS: &str = "dereference-args"; pub const INODES: &str = "inodes"; pub const EXCLUDE: &str = "exclude"; pub const EXCLUDE_FROM: &str = "exclude-from"; @@ -89,6 +90,7 @@ struct Options { separate_dirs: bool, one_file_system: bool, dereference: bool, + dereference_args: Vec, inodes: bool, verbose: bool, } @@ -113,7 +115,7 @@ struct Stat { impl Stat { fn new(path: PathBuf, options: &Options) -> Result { - let metadata = if options.dereference { + let metadata = if options.dereference || options.dereference_args.contains(&path) { fs::metadata(&path)? } else { fs::symlink_metadata(&path)? @@ -505,17 +507,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { summarize, )?; - let options = Options { - all: matches.get_flag(options::ALL), - max_depth, - total: matches.get_flag(options::TOTAL), - separate_dirs: matches.get_flag(options::SEPARATE_DIRS), - one_file_system: matches.get_flag(options::ONE_FILE_SYSTEM), - dereference: matches.get_flag(options::DEREFERENCE), - inodes: matches.get_flag(options::INODES), - verbose: matches.get_flag(options::VERBOSE), - }; - let files = match matches.get_one::(options::FILE) { Some(_) => matches .get_many::(options::FILE) @@ -525,6 +516,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { None => vec!["."], }; + let options = Options { + all: matches.get_flag(options::ALL), + max_depth, + total: matches.get_flag(options::TOTAL), + separate_dirs: matches.get_flag(options::SEPARATE_DIRS), + one_file_system: matches.get_flag(options::ONE_FILE_SYSTEM), + dereference: matches.get_flag(options::DEREFERENCE), + dereference_args: if matches.get_flag(options::DEREFERENCE_ARGS) { + // Convert into a pathbuf as we will use it in a function using Pathbuf + // We don't care about the cost as it is rarely used + files.iter().map(PathBuf::from).collect() + } else { + vec![] + }, + inodes: matches.get_flag(options::INODES), + verbose: matches.get_flag(options::VERBOSE), + }; + if options.inodes && (matches.get_flag(options::APPARENT_SIZE) || matches.get_flag(options::BYTES)) { @@ -789,6 +798,13 @@ pub fn uu_app() -> Command { .help("dereference all symbolic links") .action(ArgAction::SetTrue) ) + .arg( + Arg::new(options::DEREFERENCE_ARGS) + .short('D') + .long(options::DEREFERENCE_ARGS) + .help("dereference only symlinks that are listed on the command line") + .action(ArgAction::SetTrue) + ) // .arg( // Arg::new("no-dereference") // .short('P') diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 73be82bf9..992f7f162 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -3,7 +3,7 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -// spell-checker:ignore (paths) sublink subwords azerty azeaze xcwww azeaz amaz azea qzerty tazerty +// spell-checker:ignore (paths) sublink subwords azerty azeaze xcwww azeaz amaz azea qzerty tazerty tsublink #[cfg(not(windows))] use regex::Regex; use std::io::Write; @@ -285,6 +285,30 @@ fn test_du_dereference() { _du_dereference(result.stdout_str()); } +#[cfg(not(windows))] +#[test] +fn test_du_dereference_args() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + at.mkdir_all("subdir"); + let mut file1 = at.make_file("subdir/file-ignore1"); + file1.write_all(b"azeaze").unwrap(); + let mut file2 = at.make_file("subdir/file-ignore1"); + file2.write_all(b"amaz?ng").unwrap(); + at.symlink_dir("subdir", "sublink"); + + let result = ts.ucmd().arg("-D").arg("-s").arg("sublink").succeeds(); + let stdout = result.stdout_str(); + + assert!(!stdout.starts_with("0")); + assert!(stdout.contains("sublink")); + + // Without the option + let result = ts.ucmd().arg("-s").arg("sublink").succeeds(); + result.stdout_contains("0\tsublink\n"); +} + #[cfg(target_vendor = "apple")] fn _du_dereference(s: &str) { assert_eq!(s, "4\tsubdir/links/deeper_dir\n16\tsubdir/links\n"); @@ -851,6 +875,7 @@ fn test_du_exclude_invalid_syntax() { .stderr_contains("du: Invalid exclude syntax"); } +#[cfg(not(windows))] #[test] fn test_du_symlink_fail() { let ts = TestScenario::new(util_name!()); @@ -861,6 +886,7 @@ fn test_du_symlink_fail() { ts.ucmd().arg("-L").arg("target.txt").fails().code_is(1); } +#[cfg(not(windows))] #[test] fn test_du_symlink_multiple_fail() { let ts = TestScenario::new(util_name!());