From 483a5fd1d4cd0508af81ef41a97cdb5500d300b6 Mon Sep 17 00:00:00 2001 From: Jan Verbeek Date: Tue, 31 Aug 2021 12:57:39 +0200 Subject: [PATCH] ls: Process OsStrings instead of Strings --- src/uu/ls/src/ls.rs | 20 +++++++++----------- src/uu/ls/src/quoting_style.rs | 16 ++++++++++------ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 3cfb0ad2c..fcb0b28ff 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -21,6 +21,7 @@ use lscolors::LsColors; use number_prefix::NumberPrefix; use once_cell::unsync::OnceCell; use quoting_style::{escape_name, QuotingStyle}; +use std::ffi::OsString; #[cfg(windows)] use std::os::windows::fs::MetadataExt; use std::{ @@ -1173,7 +1174,7 @@ struct PathData { md: OnceCell>, ft: OnceCell>, // Name of the file - will be empty for . or .. - display_name: String, + display_name: OsString, // PathBuf that all above data corresponds to p_buf: PathBuf, must_dereference: bool, @@ -1183,7 +1184,7 @@ impl PathData { fn new( p_buf: PathBuf, file_type: Option>, - file_name: Option, + file_name: Option, config: &Config, command_line: bool, ) -> Self { @@ -1191,16 +1192,13 @@ impl PathData { // For '..', the filename is None let display_name = if let Some(name) = file_name { name + } else if command_line { + p_buf.clone().into() } else { - let display_os_str = if command_line { - p_buf.as_os_str() - } else { - p_buf - .file_name() - .unwrap_or_else(|| p_buf.iter().next_back().unwrap()) - }; - - display_os_str.to_string_lossy().into_owned() + p_buf + .file_name() + .unwrap_or_else(|| p_buf.iter().next_back().unwrap()) + .to_owned() }; let must_dereference = match &config.dereference { Dereference::All => true, diff --git a/src/uu/ls/src/quoting_style.rs b/src/uu/ls/src/quoting_style.rs index 5f421b2ee..4839370ee 100644 --- a/src/uu/ls/src/quoting_style.rs +++ b/src/uu/ls/src/quoting_style.rs @@ -1,4 +1,5 @@ use std::char::from_digit; +use std::ffi::OsStr; // These are characters with special meaning in the shell (e.g. bash). // The first const contains characters that only have a special meaning when they appear at the beginning of a name. @@ -255,19 +256,21 @@ fn shell_with_escape(name: &str, quotes: Quotes) -> (String, bool) { (escaped_str, must_quote) } -pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String { +pub(super) fn escape_name(name: &OsStr, style: &QuotingStyle) -> String { match style { QuotingStyle::Literal { show_control } => { if !show_control { - name.chars() + name.to_string_lossy() + .chars() .flat_map(|c| EscapedChar::new_literal(c).hide_control()) .collect() } else { - name.into() + name.to_string_lossy().into_owned() } } QuotingStyle::C { quotes } => { let escaped_str: String = name + .to_string_lossy() .chars() .flat_map(|c| EscapedChar::new_c(c, *quotes)) .collect(); @@ -283,6 +286,7 @@ pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String { always_quote, show_control, } => { + let name = name.to_string_lossy(); let (quotes, must_quote) = if name.contains('"') { (Quotes::Single, true) } else if name.contains('\'') { @@ -294,9 +298,9 @@ pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String { }; let (escaped_str, contains_quote_chars) = if *escape { - shell_with_escape(name, quotes) + shell_with_escape(&name, quotes) } else { - shell_without_escape(name, quotes, *show_control) + shell_without_escape(&name, quotes, *show_control) }; match (must_quote | contains_quote_chars, quotes) { @@ -362,7 +366,7 @@ mod tests { fn check_names(name: &str, map: Vec<(&str, &str)>) { assert_eq!( map.iter() - .map(|(_, style)| escape_name(name, &get_style(style))) + .map(|(_, style)| escape_name(name.as_ref(), &get_style(style))) .collect::>(), map.iter() .map(|(correct, _)| correct.to_string())