1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

du: add support of --dereference-args

Should fix tests/du/deref.sh
This commit is contained in:
Sylvestre Ledru 2023-04-09 21:12:39 +02:00
parent 5a1d9cec7e
commit eea8d40e78
2 changed files with 55 additions and 13 deletions

View file

@ -68,6 +68,7 @@ mod options {
pub const TIME_STYLE: &str = "time-style"; pub const TIME_STYLE: &str = "time-style";
pub const ONE_FILE_SYSTEM: &str = "one-file-system"; pub const ONE_FILE_SYSTEM: &str = "one-file-system";
pub const DEREFERENCE: &str = "dereference"; pub const DEREFERENCE: &str = "dereference";
pub const DEREFERENCE_ARGS: &str = "dereference-args";
pub const INODES: &str = "inodes"; pub const INODES: &str = "inodes";
pub const EXCLUDE: &str = "exclude"; pub const EXCLUDE: &str = "exclude";
pub const EXCLUDE_FROM: &str = "exclude-from"; pub const EXCLUDE_FROM: &str = "exclude-from";
@ -89,6 +90,7 @@ struct Options {
separate_dirs: bool, separate_dirs: bool,
one_file_system: bool, one_file_system: bool,
dereference: bool, dereference: bool,
dereference_args: Vec<PathBuf>,
inodes: bool, inodes: bool,
verbose: bool, verbose: bool,
} }
@ -113,7 +115,7 @@ struct Stat {
impl Stat { impl Stat {
fn new(path: PathBuf, options: &Options) -> Result<Self> { fn new(path: PathBuf, options: &Options) -> Result<Self> {
let metadata = if options.dereference { let metadata = if options.dereference || options.dereference_args.contains(&path) {
fs::metadata(&path)? fs::metadata(&path)?
} else { } else {
fs::symlink_metadata(&path)? fs::symlink_metadata(&path)?
@ -505,17 +507,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
summarize, 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::<String>(options::FILE) { let files = match matches.get_one::<String>(options::FILE) {
Some(_) => matches Some(_) => matches
.get_many::<String>(options::FILE) .get_many::<String>(options::FILE)
@ -525,6 +516,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
None => vec!["."], 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 if options.inodes
&& (matches.get_flag(options::APPARENT_SIZE) || matches.get_flag(options::BYTES)) && (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") .help("dereference all symbolic links")
.action(ArgAction::SetTrue) .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(
// Arg::new("no-dereference") // Arg::new("no-dereference")
// .short('P') // .short('P')

View file

@ -3,7 +3,7 @@
// * For the full copyright and license information, please view the LICENSE // * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code. // * 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))] #[cfg(not(windows))]
use regex::Regex; use regex::Regex;
use std::io::Write; use std::io::Write;
@ -285,6 +285,30 @@ fn test_du_dereference() {
_du_dereference(result.stdout_str()); _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")] #[cfg(target_vendor = "apple")]
fn _du_dereference(s: &str) { fn _du_dereference(s: &str) {
assert_eq!(s, "4\tsubdir/links/deeper_dir\n16\tsubdir/links\n"); 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"); .stderr_contains("du: Invalid exclude syntax");
} }
#[cfg(not(windows))]
#[test] #[test]
fn test_du_symlink_fail() { fn test_du_symlink_fail() {
let ts = TestScenario::new(util_name!()); 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); ts.ucmd().arg("-L").arg("target.txt").fails().code_is(1);
} }
#[cfg(not(windows))]
#[test] #[test]
fn test_du_symlink_multiple_fail() { fn test_du_symlink_multiple_fail() {
let ts = TestScenario::new(util_name!()); let ts = TestScenario::new(util_name!());