du: deduplicate the input

Should fix:
tests/du/hard-link.sh
This commit is contained in:
Sylvestre Ledru 2024-11-24 13:12:55 +01:00
parent 79f991dd05
commit 95bd50e09a
2 changed files with 73 additions and 9 deletions

View file

@ -649,6 +649,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let summarize = matches.get_flag(options::SUMMARIZE);
let count_links = matches.get_flag(options::COUNT_LINKS);
let max_depth = parse_depth(
matches
.get_one::<String>(options::MAX_DEPTH)
@ -669,15 +671,19 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
read_files_from(file_from)?
} else {
match matches.get_one::<String>(options::FILE) {
Some(_) => matches
.get_many::<String>(options::FILE)
.unwrap()
.map(PathBuf::from)
.collect(),
None => vec![PathBuf::from(".")],
} else if let Some(files) = matches.get_many::<String>(options::FILE) {
let files = files.map(PathBuf::from);
if count_links {
files.collect()
} else {
// Deduplicate while preserving order
let mut seen = std::collections::HashSet::new();
files
.filter(|path| seen.insert(path.clone()))
.collect::<Vec<_>>()
}
} else {
vec![PathBuf::from(".")]
};
let time = matches.contains_id(options::TIME).then(|| {
@ -719,7 +725,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
} else {
Deref::None
},
count_links: matches.get_flag(options::COUNT_LINKS),
count_links,
verbose: matches.get_flag(options::VERBOSE),
excludes: build_exclude_patterns(&matches)?,
};

View file

@ -1194,3 +1194,61 @@ fn test_human_size() {
.succeeds()
.stdout_contains(format!("1.0K {dir}"));
}
#[cfg(not(target_os = "android"))]
#[test]
fn test_du_deduplicated_input_args() {
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
at.mkdir("d");
at.mkdir("d/d");
at.touch("d/f");
at.hard_link("d/f", "d/h");
let result = ts
.ucmd()
.arg("--inodes")
.arg("d")
.arg("d")
.arg("d")
.succeeds();
result.no_stderr();
let result_seq: Vec<String> = result
.stdout_str()
.lines()
.map(|x| x.parse().unwrap())
.collect();
#[cfg(windows)]
assert_eq!(result_seq, ["1\td\\d", "3\td"]);
#[cfg(not(windows))]
assert_eq!(result_seq, ["1\td/d", "3\td"]);
}
#[cfg(not(target_os = "android"))]
#[test]
fn test_du_no_deduplicated_input_args() {
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
at.mkdir("d");
at.touch("d/d");
let result = ts
.ucmd()
.arg("--inodes")
.arg("-l")
.arg("d")
.arg("d")
.arg("d")
.succeeds();
result.no_stderr();
let result_seq: Vec<String> = result
.stdout_str()
.lines()
.map(|x| x.parse().unwrap())
.collect();
assert_eq!(result_seq, ["2\td", "2\td", "2\td"]);
}