du: refactor pattern building in du

This commit is contained in:
Ackerley Tng 2022-07-28 20:45:43 -07:00 committed by Sylvestre Ledru
parent defde8c91e
commit 898689d924

View file

@ -488,55 +488,28 @@ fn file_as_vec(filename: impl AsRef<Path>) -> Vec<String> {
// Given the --exclude-from and/or --exclude arguments, returns the globset lists // Given the --exclude-from and/or --exclude arguments, returns the globset lists
// to ignore the files // to ignore the files
fn get_glob_ignore(matches: &ArgMatches) -> UResult<Vec<Pattern>> { fn build_exclude_patterns(matches: &ArgMatches) -> UResult<Vec<Pattern>> {
let mut excludes_from = if matches.contains_id(options::EXCLUDE_FROM) { let exclude_from_iterator = matches
match matches.values_of(options::EXCLUDE_FROM) { .values_of(options::EXCLUDE_FROM)
Some(all_files) => { .unwrap_or_default()
let mut exclusion = Vec::<String>::new(); .flat_map(|f| file_as_vec(&f));
// Read the exclude lists from all the files
// and add them into a vector of string
let files: Vec<String> = all_files.clone().map(|v| v.to_owned()).collect();
for f in files {
exclusion.extend(file_as_vec(&f));
}
exclusion
}
None => Vec::<String>::new(),
}
} else {
Vec::<String>::new()
};
let mut excludes = if matches.contains_id(options::EXCLUDE) { let excludes_iterator = matches
match matches.values_of(options::EXCLUDE) { .values_of(options::EXCLUDE)
Some(v) => { .unwrap_or_default()
// Read the various arguments .map(|v| v.to_owned());
v.clone().map(|v| v.to_owned()).collect()
}
None => Vec::<String>::new(),
}
} else {
Vec::<String>::new()
};
// Merge the two lines let mut exclude_patterns = Vec::new();
excludes.append(&mut excludes_from); for f in excludes_iterator.chain(exclude_from_iterator) {
if !&excludes.is_empty() { if matches.is_present(options::VERBOSE) {
let mut builder = Vec::new(); println!("adding {:?} to the exclude list ", &f);
// Create the `Vec` of excludes }
for f in excludes { match Pattern::new(&f) {
if matches.contains_id(options::VERBOSE) { Ok(glob) => exclude_patterns.push(glob),
println!("adding {:?} to the exclude list ", &f); Err(err) => return Err(DuError::InvalidGlob(err.to_string()).into()),
}
match Pattern::new(&f) {
Ok(glob) => builder.push(glob),
Err(err) => return Err(DuError::InvalidGlob(err.to_string()).into()),
};
} }
Ok(builder)
} else {
Ok(Vec::new())
} }
Ok(exclude_patterns)
} }
#[uucore::main] #[uucore::main]
@ -615,85 +588,80 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
"\n" "\n"
}; };
let excludes = get_glob_ignore(&matches)?; let excludes = build_exclude_patterns(&matches)?;
let mut grand_total = 0; let mut grand_total = 0;
'loop_file: for path_string in files { 'loop_file: for path_string in files {
// Skip if we don't want to ignore anything // Skip if we don't want to ignore anything
if !&excludes.is_empty() { if !&excludes.is_empty() {
for pattern in &excludes { for pattern in &excludes {
{ if pattern.matches(path_string) {
if pattern.matches(path_string) { // if the directory is ignored, leave early
// if the directory is ignored, leave early if options.verbose {
if options.verbose { println!("{} ignored", path_string.quote());
println!("{} ignored", path_string.quote());
}
continue 'loop_file;
} }
continue 'loop_file;
} }
} }
} }
let path = PathBuf::from(&path_string); let path = PathBuf::from(&path_string);
match Stat::new(path, &options) { if let Ok(stat) = Stat::new(path, &options) {
Ok(stat) => { let mut inodes: HashSet<FileInfo> = HashSet::new();
let mut inodes: HashSet<FileInfo> = HashSet::new(); if let Some(inode) = stat.inode {
if let Some(inode) = stat.inode { inodes.insert(inode);
inodes.insert(inode); }
let iter = du(stat, &options, 0, &mut inodes, &excludes);
let (_, len) = iter.size_hint();
let len = len.unwrap();
for (index, stat) in iter.enumerate() {
let size = choose_size(&matches, &stat);
if threshold.map_or(false, |threshold| threshold.should_exclude(size)) {
continue;
} }
let iter = du(stat, &options, 0, &mut inodes, &excludes);
let (_, len) = iter.size_hint();
let len = len.unwrap();
for (index, stat) in iter.enumerate() {
let size = choose_size(&matches, &stat);
if threshold.map_or(false, |threshold| threshold.should_exclude(size)) { if matches.is_present(options::TIME) {
continue; let tm = {
} let secs = {
match matches.value_of(options::TIME) {
if matches.contains_id(options::TIME) { Some(s) => match s {
let tm = { "ctime" | "status" => stat.modified,
let secs = { "access" | "atime" | "use" => stat.accessed,
match matches.value_of(options::TIME) { "birth" | "creation" => stat
Some(s) => match s { .created
"ctime" | "status" => stat.modified, .ok_or_else(|| DuError::InvalidTimeArg(s.into()))?,
"access" | "atime" | "use" => stat.accessed, // below should never happen as clap already restricts the values.
"birth" | "creation" => stat _ => unreachable!("Invalid field for --time"),
.created },
.ok_or_else(|| DuError::InvalidTimeArg(s.into()))?, None => stat.modified,
// below should never happen as clap already restricts the values. }
_ => unreachable!("Invalid field for --time"),
},
None => stat.modified,
}
};
DateTime::<Local>::from(UNIX_EPOCH + Duration::from_secs(secs))
}; };
if !summarize || index == len - 1 { DateTime::<Local>::from(UNIX_EPOCH + Duration::from_secs(secs))
let time_str = tm.format(time_format_str).to_string(); };
print!("{}\t{}\t", convert_size(size), time_str); if !summarize || index == len - 1 {
print_verbatim(stat.path).unwrap(); let time_str = tm.format(time_format_str).to_string();
print!("{}", line_separator); print!("{}\t{}\t", convert_size(size), time_str);
}
} else if !summarize || index == len - 1 {
print!("{}\t", convert_size(size));
print_verbatim(stat.path).unwrap(); print_verbatim(stat.path).unwrap();
print!("{}", line_separator); print!("{}", line_separator);
} }
if options.total && index == (len - 1) { } else if !summarize || index == len - 1 {
// The last element will be the total size of the the path under print!("{}\t", convert_size(size));
// path_string. We add it to the grand total. print_verbatim(stat.path).unwrap();
grand_total += size; print!("{}", line_separator);
} }
if options.total && index == (len - 1) {
// The last element will be the total size of the the path under
// path_string. We add it to the grand total.
grand_total += size;
} }
} }
Err(_) => { } else {
show_error!( show_error!(
"{}: {}", "{}: {}",
path_string.maybe_quote(), path_string.maybe_quote(),
"No such file or directory" "No such file or directory"
); );
}
} }
} }