Skip to content

Commit 83710e4

Browse files
authored
Merge branch 'main' into date-positional-set-format
2 parents d6fab26 + adce17f commit 83710e4

6 files changed

Lines changed: 48 additions & 38 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fuzz/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/uu/factor/src/factor.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,22 +113,13 @@ impl Display for NumError<'_> {
113113
/// the invalid ones as escaped octal, like GNU. For example, the
114114
/// (escaped) string "\xFFabc\x1C" is formatted as "\377abc\034".
115115
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116-
match str::from_utf8(self.0) {
117-
Ok(s) => write!(f, "{s}"),
118-
Err(e) => {
119-
let valid = e.valid_up_to();
120-
let cont = valid + e.error_len().unwrap_or(1);
121-
// SAFETY: `self.0` has been checked to contain valid
122-
// UTF-8 sequences up to `valid`.
123-
write!(f, "{}", unsafe {
124-
str::from_utf8_unchecked(&self.0[..valid])
125-
})?;
126-
for b in &self.0[valid..cont] {
127-
write!(f, "\\{b:03o}")?;
128-
}
129-
<Self as Display>::fmt(&Self(&self.0[cont..]), f)
116+
for chunk in self.0.utf8_chunks() {
117+
f.write_str(chunk.valid())?;
118+
for &b in chunk.invalid() {
119+
write!(f, "\\{b:03o}")?;
130120
}
131121
}
122+
Ok(())
132123
}
133124
}
134125

src/uu/ls/src/ls.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,12 @@ fn sort_entries(entries: &mut [PathData], config: &Config) {
14811481
)
14821482
}),
14831483
Sort::Size => {
1484-
entries.sort_unstable_by_key(|k| Reverse(k.metadata().map_or(0, Metadata::len)));
1484+
entries.sort_unstable_by(|a, b| {
1485+
b.metadata()
1486+
.map_or(0, Metadata::len)
1487+
.cmp(&a.metadata().map_or(0, Metadata::len))
1488+
.then(a.file_name().cmp(b.file_name()))
1489+
});
14851490
}
14861491
// The default sort in GNU ls is case insensitive
14871492
Sort::Name => entries.sort_unstable_by(|a, b| a.display_name().cmp(b.display_name())),
@@ -1512,7 +1517,7 @@ fn sort_entries(entries: &mut [PathData], config: &Config) {
15121517
}
15131518

15141519
if config.group_directories_first && config.sort != Sort::None {
1515-
entries.sort_unstable_by_key(|p| {
1520+
entries.sort_by_key(|p| {
15161521
let ft = {
15171522
// We will always try to deref symlinks to group directories, so PathData.md
15181523
// is not always useful.

src/uu/yes/src/yes.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
2727
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
2828

2929
#[allow(clippy::unwrap_used, reason = "clap provides 'y' by default")]
30-
let mut buffer = args_into_buffer(matches.get_many::<OsString>("STRING").unwrap())?;
31-
#[cfg(any(target_os = "linux", target_os = "android"))]
32-
let aligned_before_growing = PAGE_SIZE.is_multiple_of(buffer.len());
33-
34-
prepare_buffer(&mut buffer);
35-
#[cfg(any(target_os = "linux", target_os = "android"))]
36-
let res = exec(&buffer, aligned_before_growing);
37-
#[cfg(not(any(target_os = "linux", target_os = "android")))]
38-
let res = exec(&buffer);
39-
match res {
30+
let buffer = args_into_buffer(matches.get_many::<OsString>("STRING").unwrap())?;
31+
32+
match exec(buffer) {
4033
Ok(()) => Ok(()),
4134
// On Windows, silently handle broken pipe since there's no SIGPIPE
4235
#[cfg(windows)]
@@ -98,7 +91,7 @@ fn args_into_buffer<'a>(i: impl Iterator<Item = &'a OsString>) -> UResult<Vec<u8
9891

9992
/// Assumes buf holds a single output line forged from the command line arguments, copies it
10093
/// repeatedly until the buffer holds as many copies as it can
101-
fn prepare_buffer(buf: &mut Vec<u8>) {
94+
fn repeat_content_to_capacity(buf: &mut Vec<u8>) {
10295
let line_len = buf.len();
10396
debug_assert!(line_len > 0, "buffer is not empty since we have newline");
10497
let target_size = line_len * (buf.capacity() / line_len); // 0 if line_len is already large enough
@@ -111,16 +104,21 @@ fn prepare_buffer(buf: &mut Vec<u8>) {
111104
}
112105

113106
#[cfg(not(any(target_os = "linux", target_os = "android")))]
114-
pub fn exec(bytes: &[u8]) -> io::Result<()> {
107+
pub fn exec(mut bytes: Vec<u8>) -> io::Result<()> {
108+
repeat_content_to_capacity(&mut bytes);
109+
let bytes = bytes.as_slice();
115110
let mut stdout = io::stdout().lock();
116111
loop {
117112
stdout.write_all(bytes)?;
118113
}
119114
}
120115

121116
#[cfg(any(target_os = "linux", target_os = "android"))]
122-
pub fn exec(bytes: &[u8], aligned: bool) -> io::Result<()> {
117+
pub fn exec(mut bytes: Vec<u8>) -> io::Result<()> {
123118
use uucore::pipes::{pipe, splice, tee};
119+
let aligned = PAGE_SIZE.is_multiple_of(bytes.len());
120+
repeat_content_to_capacity(&mut bytes);
121+
let bytes = bytes.as_slice();
124122
let mut stdout = io::stdout(); // no need to lock with zero-copy
125123
// don't show any error from fast-path and fallback to write for proper message
126124
if let Ok((p_read, mut p_write)) = pipe()
@@ -182,7 +180,7 @@ mod tests {
182180
for (line, final_len) in tests {
183181
let mut v = Vec::with_capacity(BUF_SIZE);
184182
v.extend(std::iter::repeat_n(b'a', line));
185-
prepare_buffer(&mut v);
183+
repeat_content_to_capacity(&mut v);
186184
assert_eq!(v.len(), final_len);
187185
}
188186
}

tests/by-util/test_ls.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,6 +1941,10 @@ fn test_ls_group_directories_first() {
19411941
}
19421942
filenames.sort_unstable();
19431943

1944+
for (i, name) in filenames.iter().enumerate() {
1945+
at.write_bytes(name, "a".repeat(i).as_bytes());
1946+
}
1947+
19441948
let dirnames = ["aaa", "bbb", "ccc", "yyy"];
19451949
for dirname in dirnames {
19461950
at.mkdir(dirname);
@@ -1954,27 +1958,39 @@ fn test_ls_group_directories_first() {
19541958
.arg("--group-directories-first")
19551959
.succeeds();
19561960
assert_eq!(
1957-
result.stdout_str().split('\n').collect::<Vec<_>>(),
1961+
result.stdout_str().lines().collect::<Vec<_>>(),
19581962
dots.into_iter()
19591963
.chain(dirnames.into_iter())
19601964
.chain(filenames.into_iter())
1961-
.chain([""].into_iter())
19621965
.collect::<Vec<_>>(),
19631966
);
19641967

1968+
let result = scene
1969+
.ucmd()
1970+
.arg("-1")
1971+
.arg("--group-directories-first")
1972+
.arg("--sort=size")
1973+
.succeeds();
1974+
assert_eq!(
1975+
result.stdout_str().lines().collect::<Vec<_>>(),
1976+
dirnames
1977+
.into_iter()
1978+
.chain(filenames.into_iter().rev())
1979+
.collect::<Vec<_>>()
1980+
);
1981+
19651982
let result = scene
19661983
.ucmd()
19671984
.arg("-1ar")
19681985
.arg("--group-directories-first")
19691986
.succeeds();
19701987
assert_eq!(
1971-
result.stdout_str().split('\n').collect::<Vec<_>>(),
1988+
result.stdout_str().lines().collect::<Vec<_>>(),
19721989
dirnames
19731990
.into_iter()
19741991
.rev()
19751992
.chain(dots.into_iter().rev())
19761993
.chain(filenames.into_iter().rev())
1977-
.chain([""].into_iter())
19781994
.collect::<Vec<_>>(),
19791995
);
19801996

0 commit comments

Comments
 (0)