Skip to content

Commit bb2fb66

Browse files
authored
Merge pull request #6882 from jtracey/quoting_style_bytes
quoting_style: Add support for non-UTF-8 bytes
2 parents 21e7149 + db1ed4c commit bb2fb66

File tree

10 files changed

+584
-175
lines changed

10 files changed

+584
-175
lines changed

.clippy.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
msrv = "1.77.0"
1+
msrv = "1.79.0"
22
cognitive-complexity-threshold = 24
33
missing-docs-in-crate-items = true
44
check-private-items = true

.github/workflows/CICD.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ env:
1111
PROJECT_NAME: coreutils
1212
PROJECT_DESC: "Core universal (cross-platform) utilities"
1313
PROJECT_AUTH: "uutils"
14-
RUST_MIN_SRV: "1.77.0"
14+
RUST_MIN_SRV: "1.79.0"
1515
# * style job configuration
1616
STYLE_FAIL_ON_FAULT: true ## (bool) fail the build if a style job contains a fault (error or warning); may be overridden on a per-job basis
1717

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ repository = "https://github.com/uutils/coreutils"
1616
readme = "README.md"
1717
keywords = ["coreutils", "uutils", "cross-platform", "cli", "utility"]
1818
categories = ["command-line-utilities"]
19-
rust-version = "1.77.0"
19+
rust-version = "1.79.0"
2020
edition = "2021"
2121

2222
build = "build.rs"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
[![dependency status](https://deps.rs/repo/github/uutils/coreutils/status.svg)](https://deps.rs/repo/github/uutils/coreutils)
1515

1616
[![CodeCov](https://codecov.io/gh/uutils/coreutils/branch/master/graph/badge.svg)](https://codecov.io/gh/uutils/coreutils)
17-
![MSRV](https://img.shields.io/badge/MSRV-1.77.0-brightgreen)
17+
![MSRV](https://img.shields.io/badge/MSRV-1.79.0-brightgreen)
1818

1919
</div>
2020

@@ -70,7 +70,7 @@ the [coreutils docs](https://github.com/uutils/uutils.github.io) repository.
7070
### Rust Version
7171

7272
uutils follows Rust's release channels and is tested against stable, beta and
73-
nightly. The current Minimum Supported Rust Version (MSRV) is `1.77.0`.
73+
nightly. The current Minimum Supported Rust Version (MSRV) is `1.79.0`.
7474

7575
## Building
7676

src/uu/ls/src/ls.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::os::windows::fs::MetadataExt;
2121
use std::{
2222
cmp::Reverse,
2323
error::Error,
24-
ffi::OsString,
24+
ffi::{OsStr, OsString},
2525
fmt::{Display, Write as FmtWrite},
2626
fs::{self, DirEntry, FileType, Metadata, ReadDir},
2727
io::{stdout, BufWriter, ErrorKind, Stdout, Write},
@@ -55,7 +55,7 @@ use uucore::libc::{dev_t, major, minor};
5555
#[cfg(unix)]
5656
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
5757
use uucore::line_ending::LineEnding;
58-
use uucore::quoting_style::{escape_dir_name, escape_name, QuotingStyle};
58+
use uucore::quoting_style::{self, QuotingStyle};
5959
use uucore::{
6060
display::Quotable,
6161
error::{set_exit_code, UError, UResult},
@@ -2048,7 +2048,11 @@ impl PathData {
20482048
/// file11
20492049
/// ```
20502050
fn show_dir_name(path_data: &PathData, out: &mut BufWriter<Stdout>, config: &Config) {
2051-
let escaped_name = escape_dir_name(path_data.p_buf.as_os_str(), &config.quoting_style);
2051+
// FIXME: replace this with appropriate behavior for literal unprintable bytes
2052+
let escaped_name =
2053+
quoting_style::escape_dir_name(path_data.p_buf.as_os_str(), &config.quoting_style)
2054+
.to_string_lossy()
2055+
.to_string();
20522056

20532057
let name = if config.hyperlink && !config.dired {
20542058
create_hyperlink(&escaped_name, path_data)
@@ -3002,7 +3006,6 @@ use std::sync::Mutex;
30023006
#[cfg(unix)]
30033007
use uucore::entries;
30043008
use uucore::fs::FileInformation;
3005-
use uucore::quoting_style;
30063009

30073010
#[cfg(unix)]
30083011
fn cached_uid2usr(uid: u32) -> String {
@@ -3542,3 +3545,10 @@ fn calculate_padding_collection(
35423545

35433546
padding_collections
35443547
}
3548+
3549+
// FIXME: replace this with appropriate behavior for literal unprintable bytes
3550+
fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
3551+
quoting_style::escape_name(name, style)
3552+
.to_string_lossy()
3553+
.to_string()
3554+
}

src/uu/wc/src/wc.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod word_count;
1313
use std::{
1414
borrow::{Borrow, Cow},
1515
cmp::max,
16-
ffi::OsString,
16+
ffi::{OsStr, OsString},
1717
fs::{self, File},
1818
io::{self, Write},
1919
iter,
@@ -28,7 +28,7 @@ use utf8::{BufReadDecoder, BufReadDecoderError};
2828
use uucore::{
2929
error::{FromIo, UError, UResult},
3030
format_usage, help_about, help_usage,
31-
quoting_style::{escape_name, QuotingStyle},
31+
quoting_style::{self, QuotingStyle},
3232
shortcut_value_parser::ShortcutValueParser,
3333
show,
3434
};
@@ -259,7 +259,7 @@ impl<'a> Input<'a> {
259259
match self {
260260
Self::Path(path) => Some(match path.to_str() {
261261
Some(s) if !s.contains('\n') => Cow::Borrowed(s),
262-
_ => Cow::Owned(escape_name(path.as_os_str(), QS_ESCAPE)),
262+
_ => Cow::Owned(escape_name_wrapper(path.as_os_str())),
263263
}),
264264
Self::Stdin(StdinKind::Explicit) => Some(Cow::Borrowed(STDIN_REPR)),
265265
Self::Stdin(StdinKind::Implicit) => None,
@@ -269,7 +269,7 @@ impl<'a> Input<'a> {
269269
/// Converts input into the form that appears in errors.
270270
fn path_display(&self) -> String {
271271
match self {
272-
Self::Path(path) => escape_name(path.as_os_str(), QS_ESCAPE),
272+
Self::Path(path) => escape_name_wrapper(path.as_os_str()),
273273
Self::Stdin(_) => String::from("standard input"),
274274
}
275275
}
@@ -361,7 +361,7 @@ impl WcError {
361361
Some((input, idx)) => {
362362
let path = match input {
363363
Input::Stdin(_) => STDIN_REPR.into(),
364-
Input::Path(path) => escape_name(path.as_os_str(), QS_ESCAPE).into(),
364+
Input::Path(path) => escape_name_wrapper(path.as_os_str()).into(),
365365
};
366366
Self::ZeroLengthFileNameCtx { path, idx }
367367
}
@@ -761,7 +761,9 @@ fn files0_iter_file<'a>(path: &Path) -> UResult<impl Iterator<Item = InputIterIt
761761
Err(e) => Err(e.map_err_context(|| {
762762
format!(
763763
"cannot open {} for reading",
764-
escape_name(path.as_os_str(), QS_QUOTE_ESCAPE)
764+
quoting_style::escape_name(path.as_os_str(), QS_QUOTE_ESCAPE)
765+
.into_string()
766+
.expect("All escaped names with the escaping option return valid strings.")
765767
)
766768
})),
767769
}
@@ -793,9 +795,9 @@ fn files0_iter<'a>(
793795
Ok(Input::Path(PathBuf::from(s).into()))
794796
}
795797
}
796-
Err(e) => Err(e.map_err_context(|| {
797-
format!("{}: read error", escape_name(&err_path, QS_ESCAPE))
798-
}) as Box<dyn UError>),
798+
Err(e) => Err(e
799+
.map_err_context(|| format!("{}: read error", escape_name_wrapper(&err_path)))
800+
as Box<dyn UError>),
799801
}),
800802
);
801803
// Loop until there is an error; yield that error and then nothing else.
@@ -808,6 +810,12 @@ fn files0_iter<'a>(
808810
})
809811
}
810812

813+
fn escape_name_wrapper(name: &OsStr) -> String {
814+
quoting_style::escape_name(name, QS_ESCAPE)
815+
.into_string()
816+
.expect("All escaped names with the escaping option return valid strings.")
817+
}
818+
811819
fn wc(inputs: &Inputs, settings: &Settings) -> UResult<()> {
812820
let mut total_word_count = WordCount::default();
813821
let mut num_inputs: usize = 0;

src/uucore/src/lib/features/format/argument.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ fn extract_value<T: Default>(p: Result<T, ParseError<'_, T>>, input: &str) -> T
112112
Default::default()
113113
}
114114
ParseError::PartialMatch(v, rest) => {
115-
if input.starts_with('\'') {
115+
let bytes = input.as_encoded_bytes();
116+
if !bytes.is_empty() && bytes[0] == b'\'' {
116117
show_warning!(
117118
"{}: character(s) following character constant have been ignored",
118119
&rest,

src/uucore/src/lib/features/format/spec.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -353,20 +353,20 @@ impl Spec {
353353
writer.write_all(&parsed).map_err(FormatError::IoError)
354354
}
355355
Self::QuotedString => {
356-
let s = args.get_str();
357-
writer
358-
.write_all(
359-
escape_name(
360-
s.as_ref(),
361-
&QuotingStyle::Shell {
362-
escape: true,
363-
always_quote: false,
364-
show_control: false,
365-
},
366-
)
367-
.as_bytes(),
368-
)
369-
.map_err(FormatError::IoError)
356+
let s = escape_name(
357+
args.get_str().as_ref(),
358+
&QuotingStyle::Shell {
359+
escape: true,
360+
always_quote: false,
361+
show_control: false,
362+
},
363+
);
364+
#[cfg(unix)]
365+
let bytes = std::os::unix::ffi::OsStringExt::into_vec(s);
366+
#[cfg(not(unix))]
367+
let bytes = s.to_string_lossy().as_bytes().to_owned();
368+
369+
writer.write_all(&bytes).map_err(FormatError::IoError)
370370
}
371371
Self::SignedInt {
372372
width,

0 commit comments

Comments
 (0)