1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

ls: Improve the access to metadata of the files Should fix tests/ls/stat-free-color.sh

This commit is contained in:
Sylvestre Ledru 2023-12-16 18:24:33 +01:00
parent 95fa81250e
commit 147721c24b

View file

@ -2118,7 +2118,8 @@ fn sort_entries(entries: &mut [PathData], config: &Config, out: &mut BufWriter<S
!match md { !match md {
None | Some(None) => { None | Some(None) => {
// If it metadata cannot be determined, treat as a file. // If it metadata cannot be determined, treat as a file.
get_metadata(p.p_buf.as_path(), true).map_or_else(|_| false, |m| m.is_dir()) get_metadata(p.p_buf.as_path(), true)
.map_or_else(|_| false, |m| m.is_dir())
} }
Some(Some(m)) => m.is_dir(), Some(Some(m)) => m.is_dir(),
} }
@ -3068,18 +3069,7 @@ fn display_item_name(
} }
if let Some(ls_colors) = &config.color { if let Some(ls_colors) = &config.color {
let md = path.get_metadata(out); name = color_name(name, path, ls_colors, style_manager, out, false, None);
name = if md.is_some() {
color_name(name, path, md, ls_colors, style_manager)
} else {
color_name(
name,
path,
path.p_buf.symlink_metadata().ok().as_ref(),
ls_colors,
style_manager,
)
};
} }
if config.format != Format::Long && !more_info.is_empty() { if config.format != Format::Long && !more_info.is_empty() {
@ -3146,27 +3136,22 @@ fn display_item_name(
// Otherwise, we use path.md(), which will guarantee we color to the same // Otherwise, we use path.md(), which will guarantee we color to the same
// color of non-existent symlinks according to style_for_path_with_metadata. // color of non-existent symlinks according to style_for_path_with_metadata.
if path.get_metadata(out).is_none() if path.get_metadata(out).is_none()
&& get_metadata(target_data.p_buf.as_path(), target_data.must_dereference) && get_metadata(
target_data.p_buf.as_path(),
target_data.must_dereference,
)
.is_err() .is_err()
{ {
name.push_str(&path.p_buf.read_link().unwrap().to_string_lossy()); name.push_str(&path.p_buf.read_link().unwrap().to_string_lossy());
} else { } else {
// Use fn get_metadata instead of md() here and above because ls
// should not exit with an err, if we are unable to obtain the target_metadata
let target_metadata = match get_metadata(
target_data.p_buf.as_path(),
target_data.must_dereference,
) {
Ok(md) => md,
Err(_) => path.get_metadata(out).unwrap().clone(),
};
name.push_str(&color_name( name.push_str(&color_name(
escape_name(target.as_os_str(), &config.quoting_style), escape_name(target.as_os_str(), &config.quoting_style),
&target_data, path,
Some(&target_metadata),
ls_colors, ls_colors,
style_manager, style_manager,
out,
true,
Some(&target_data),
)); ));
} }
} else { } else {
@ -3263,13 +3248,18 @@ impl StyleManager {
} }
} }
/// Colors the provided name based on the style determined for the given path. /// Colors the provided name based on the style determined for the given path
/// This function is quite long because it tries to leverage DirEntry to avoid
/// unnecessary calls to stat()
/// and manages the symlink errors
fn color_name( fn color_name(
name: String, name: String,
path: &PathData, path: &PathData,
md: Option<&Metadata>,
ls_colors: &LsColors, ls_colors: &LsColors,
style_manager: &mut StyleManager, style_manager: &mut StyleManager,
out: &mut BufWriter<Stdout>,
check_for_deref: bool,
target_symlink: Option<&PathData>,
) -> String { ) -> String {
if !path.must_dereference { if !path.must_dereference {
// If we need to dereference (follow) a symlink, we will need to get the metadata // If we need to dereference (follow) a symlink, we will need to get the metadata
@ -3282,9 +3272,34 @@ fn color_name(
} }
} }
match ls_colors.style_for_path_with_metadata(&path.p_buf, md) { if check_for_deref {
// use the optional target_symlink
// Use fn get_metadata instead of md() here and above because ls
// should not exit with an err, if we are unable to obtain the target_metadata
let target = target_symlink.unwrap_or(path);
let md = match get_metadata(target.p_buf.as_path(), path.must_dereference) {
Ok(md) => md,
Err(_) => target.get_metadata(out).unwrap().clone(),
};
return match ls_colors.style_for_path_with_metadata(&path.p_buf, Some(&md)) {
Some(style) => style_manager.apply_style(style, &name), Some(style) => style_manager.apply_style(style, &name),
None => name, None => name,
};
} else {
let md_option = path.get_metadata(out);
let symlink_metadata = path.p_buf.symlink_metadata().ok();
let md = if md_option.is_some() {
md_option
} else {
symlink_metadata.as_ref()
};
return match ls_colors.style_for_path_with_metadata(&path.p_buf, md) {
Some(style) => style_manager.apply_style(style, &name),
None => name,
};
} }
} }