mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-30 04:27:45 +00:00
Merge branch 'master' into sort-disable-dictionary-mode
This commit is contained in:
commit
b41951614b
9 changed files with 267 additions and 44 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1212,9 +1212,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.4.5"
|
version = "1.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr 2.3.4",
|
"memchr 2.3.4",
|
||||||
|
|
|
@ -210,7 +210,6 @@ pub struct Options {
|
||||||
overwrite: OverwriteMode,
|
overwrite: OverwriteMode,
|
||||||
parents: bool,
|
parents: bool,
|
||||||
strip_trailing_slashes: bool,
|
strip_trailing_slashes: bool,
|
||||||
reflink: bool,
|
|
||||||
reflink_mode: ReflinkMode,
|
reflink_mode: ReflinkMode,
|
||||||
preserve_attributes: Vec<Attribute>,
|
preserve_attributes: Vec<Attribute>,
|
||||||
recursive: bool,
|
recursive: bool,
|
||||||
|
@ -633,12 +632,12 @@ impl Options {
|
||||||
update: matches.is_present(OPT_UPDATE),
|
update: matches.is_present(OPT_UPDATE),
|
||||||
verbose: matches.is_present(OPT_VERBOSE),
|
verbose: matches.is_present(OPT_VERBOSE),
|
||||||
strip_trailing_slashes: matches.is_present(OPT_STRIP_TRAILING_SLASHES),
|
strip_trailing_slashes: matches.is_present(OPT_STRIP_TRAILING_SLASHES),
|
||||||
reflink: matches.is_present(OPT_REFLINK),
|
|
||||||
reflink_mode: {
|
reflink_mode: {
|
||||||
if let Some(reflink) = matches.value_of(OPT_REFLINK) {
|
if let Some(reflink) = matches.value_of(OPT_REFLINK) {
|
||||||
match reflink {
|
match reflink {
|
||||||
"always" => ReflinkMode::Always,
|
"always" => ReflinkMode::Always,
|
||||||
"auto" => ReflinkMode::Auto,
|
"auto" => ReflinkMode::Auto,
|
||||||
|
"never" => ReflinkMode::Never,
|
||||||
value => {
|
value => {
|
||||||
return Err(Error::InvalidArgument(format!(
|
return Err(Error::InvalidArgument(format!(
|
||||||
"invalid argument '{}' for \'reflink\'",
|
"invalid argument '{}' for \'reflink\'",
|
||||||
|
@ -1196,7 +1195,7 @@ fn copy_file(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> {
|
||||||
///Copy the file from `source` to `dest` either using the normal `fs::copy` or the
|
///Copy the file from `source` to `dest` either using the normal `fs::copy` or the
|
||||||
///`FICLONE` ioctl if --reflink is specified and the filesystem supports it.
|
///`FICLONE` ioctl if --reflink is specified and the filesystem supports it.
|
||||||
fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> {
|
fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> {
|
||||||
if options.reflink {
|
if options.reflink_mode != ReflinkMode::Never {
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
return Err("--reflink is only supported on linux".to_string().into());
|
return Err("--reflink is only supported on linux".to_string().into());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::char::from_digit;
|
use std::char::from_digit;
|
||||||
|
|
||||||
const SPECIAL_SHELL_CHARS: &str = "~`#$&*()\\|[]{};'\"<>?! ";
|
const SPECIAL_SHELL_CHARS: &str = "~`#$&*()|[]{};\\'\"<>?! ";
|
||||||
|
|
||||||
pub(super) enum QuotingStyle {
|
pub(super) enum QuotingStyle {
|
||||||
Shell {
|
Shell {
|
||||||
|
@ -27,12 +27,10 @@ pub(super) enum Quotes {
|
||||||
// This implementation is heavily inspired by the std::char::EscapeDefault implementation
|
// This implementation is heavily inspired by the std::char::EscapeDefault implementation
|
||||||
// in the Rust standard library. This custom implementation is needed because the
|
// in the Rust standard library. This custom implementation is needed because the
|
||||||
// characters \a, \b, \e, \f & \v are not recognized by Rust.
|
// characters \a, \b, \e, \f & \v are not recognized by Rust.
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
struct EscapedChar {
|
struct EscapedChar {
|
||||||
state: EscapeState,
|
state: EscapeState,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum EscapeState {
|
enum EscapeState {
|
||||||
Done,
|
Done,
|
||||||
Char(char),
|
Char(char),
|
||||||
|
@ -41,14 +39,12 @@ enum EscapeState {
|
||||||
Octal(EscapeOctal),
|
Octal(EscapeOctal),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
struct EscapeOctal {
|
struct EscapeOctal {
|
||||||
c: char,
|
c: char,
|
||||||
state: EscapeOctalState,
|
state: EscapeOctalState,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum EscapeOctalState {
|
enum EscapeOctalState {
|
||||||
Done,
|
Done,
|
||||||
Backslash,
|
Backslash,
|
||||||
|
@ -135,7 +131,6 @@ impl EscapedChar {
|
||||||
'\x0B' => Backslash('v'),
|
'\x0B' => Backslash('v'),
|
||||||
'\x0C' => Backslash('f'),
|
'\x0C' => Backslash('f'),
|
||||||
'\r' => Backslash('r'),
|
'\r' => Backslash('r'),
|
||||||
'\\' => Backslash('\\'),
|
|
||||||
'\x00'..='\x1F' | '\x7F' => Octal(EscapeOctal::from(c)),
|
'\x00'..='\x1F' | '\x7F' => Octal(EscapeOctal::from(c)),
|
||||||
'\'' => match quotes {
|
'\'' => match quotes {
|
||||||
Quotes::Single => Backslash('\''),
|
Quotes::Single => Backslash('\''),
|
||||||
|
@ -511,6 +506,23 @@ mod tests {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// A control character followed by a special shell character
|
||||||
|
check_names(
|
||||||
|
"one\n&two",
|
||||||
|
vec![
|
||||||
|
("one?&two", "literal"),
|
||||||
|
("one\n&two", "literal-show"),
|
||||||
|
("one\\n&two", "escape"),
|
||||||
|
("\"one\\n&two\"", "c"),
|
||||||
|
("'one?&two'", "shell"),
|
||||||
|
("'one\n&two'", "shell-show"),
|
||||||
|
("'one?&two'", "shell-always"),
|
||||||
|
("'one\n&two'", "shell-always-show"),
|
||||||
|
("'one'$'\\n''&two'", "shell-escape"),
|
||||||
|
("'one'$'\\n''&two'", "shell-escape-always"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
// The first 16 control characters. NUL is also included, even though it is of
|
// The first 16 control characters. NUL is also included, even though it is of
|
||||||
// no importance for file names.
|
// no importance for file names.
|
||||||
check_names(
|
check_names(
|
||||||
|
@ -627,4 +639,22 @@ mod tests {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_backslash() {
|
||||||
|
// Escaped in C-style, but not in Shell-style escaping
|
||||||
|
check_names(
|
||||||
|
"one\\two",
|
||||||
|
vec![
|
||||||
|
("one\\two", "literal"),
|
||||||
|
("one\\two", "literal-show"),
|
||||||
|
("one\\\\two", "escape"),
|
||||||
|
("\"one\\\\two\"", "c"),
|
||||||
|
("'one\\two'", "shell"),
|
||||||
|
("\'one\\two\'", "shell-always"),
|
||||||
|
("'one\\two'", "shell-escape"),
|
||||||
|
("'one\\two'", "shell-escape-always"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,10 +397,10 @@ fn test_dev_full_show_all() {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn test_domain_socket() {
|
fn test_domain_socket() {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
use std::sync::{Arc, Barrier};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
use unix_socket::UnixListener;
|
use unix_socket::UnixListener;
|
||||||
use std::sync::{Barrier, Arc};
|
|
||||||
|
|
||||||
let dir = TempDir::new("unix_socket").expect("failed to create dir");
|
let dir = TempDir::new("unix_socket").expect("failed to create dir");
|
||||||
let socket_path = dir.path().join("sock");
|
let socket_path = dir.path().join("sock");
|
||||||
|
|
|
@ -965,3 +965,59 @@ fn test_cp_one_file_system() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_reflink_always() {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
let result = ucmd
|
||||||
|
.arg("--reflink=always")
|
||||||
|
.arg(TEST_HELLO_WORLD_SOURCE)
|
||||||
|
.arg(TEST_EXISTING_FILE)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
if result.succeeded() {
|
||||||
|
// Check the content of the destination file
|
||||||
|
assert_eq!(at.read(TEST_EXISTING_FILE), "Hello, World!\n");
|
||||||
|
} else {
|
||||||
|
// Older Linux versions do not support cloning.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_reflink_auto() {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
ucmd.arg("--reflink=auto")
|
||||||
|
.arg(TEST_HELLO_WORLD_SOURCE)
|
||||||
|
.arg(TEST_EXISTING_FILE)
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
// Check the content of the destination file
|
||||||
|
assert_eq!(at.read(TEST_EXISTING_FILE), "Hello, World!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_reflink_never() {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
ucmd.arg("--reflink=never")
|
||||||
|
.arg(TEST_HELLO_WORLD_SOURCE)
|
||||||
|
.arg(TEST_EXISTING_FILE)
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
// Check the content of the destination file
|
||||||
|
assert_eq!(at.read(TEST_EXISTING_FILE), "Hello, World!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_reflink_bad() {
|
||||||
|
let (_, mut ucmd) = at_and_ucmd!();
|
||||||
|
let _result = ucmd
|
||||||
|
.arg("--reflink=bad")
|
||||||
|
.arg(TEST_HELLO_WORLD_SOURCE)
|
||||||
|
.arg(TEST_EXISTING_FILE)
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("invalid argument");
|
||||||
|
}
|
||||||
|
|
|
@ -104,6 +104,12 @@ fn test_ls_width() {
|
||||||
.stdout_only("test-width-1\ntest-width-2\ntest-width-3\ntest-width-4\n");
|
.stdout_only("test-width-1\ntest-width-2\ntest-width-3\ntest-width-4\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-w=bad")
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("invalid line width");
|
||||||
|
|
||||||
for option in &["-w 1a", "-w=1a", "--width=1a", "--width 1a"] {
|
for option in &["-w 1a", "-w=1a", "--width=1a", "--width 1a"] {
|
||||||
scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
|
@ -444,6 +450,39 @@ fn test_ls_deref() {
|
||||||
assert!(!re.is_match(result.stdout_str().trim()));
|
assert!(!re.is_match(result.stdout_str().trim()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ls_sort_none() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
at.touch("test-3");
|
||||||
|
at.touch("test-1");
|
||||||
|
at.touch("test-2");
|
||||||
|
|
||||||
|
// Order is not specified so we just check that it doesn't
|
||||||
|
// give any errors.
|
||||||
|
scene.ucmd().arg("--sort=none").succeeds();
|
||||||
|
scene.ucmd().arg("-U").succeeds();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ls_sort_name() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
at.touch("test-3");
|
||||||
|
at.touch("test-1");
|
||||||
|
at.touch("test-2");
|
||||||
|
|
||||||
|
let sep = if cfg!(unix) { "\n" } else { " " };
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--sort=name")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is(["test-1", "test-2", "test-3\n"].join(sep));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ls_order_size() {
|
fn test_ls_order_size() {
|
||||||
let scene = TestScenario::new(util_name!());
|
let scene = TestScenario::new(util_name!());
|
||||||
|
@ -472,6 +511,18 @@ fn test_ls_order_size() {
|
||||||
result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n");
|
result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n");
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
result.stdout_only("test-1 test-2 test-3 test-4\n");
|
result.stdout_only("test-1 test-2 test-3 test-4\n");
|
||||||
|
|
||||||
|
let result = scene.ucmd().arg("--sort=size").succeeds();
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n");
|
||||||
|
#[cfg(windows)]
|
||||||
|
result.stdout_only("test-4 test-3 test-2 test-1\n");
|
||||||
|
|
||||||
|
let result = scene.ucmd().arg("--sort=size").arg("-r").succeeds();
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n");
|
||||||
|
#[cfg(windows)]
|
||||||
|
result.stdout_only("test-1 test-2 test-3 test-4\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -480,13 +531,16 @@ fn test_ls_long_ctime() {
|
||||||
let at = &scene.fixtures;
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
at.touch("test-long-ctime-1");
|
at.touch("test-long-ctime-1");
|
||||||
let result = scene.ucmd().arg("-lc").succeeds();
|
|
||||||
|
|
||||||
// Should show the time on Unix, but question marks on windows.
|
for arg in &["-c", "--time=ctime", "--time=status"] {
|
||||||
#[cfg(unix)]
|
let result = scene.ucmd().arg("-l").arg(arg).succeeds();
|
||||||
result.stdout_contains(":");
|
|
||||||
#[cfg(not(unix))]
|
// Should show the time on Unix, but question marks on windows.
|
||||||
result.stdout_contains("???");
|
#[cfg(unix)]
|
||||||
|
result.stdout_contains(":");
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
result.stdout_contains("???");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -527,32 +581,46 @@ fn test_ls_order_time() {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
result.stdout_only("test-4 test-3 test-2 test-1\n");
|
result.stdout_only("test-4 test-3 test-2 test-1\n");
|
||||||
|
|
||||||
|
let result = scene.ucmd().arg("--sort=time").succeeds();
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n");
|
||||||
|
#[cfg(windows)]
|
||||||
|
result.stdout_only("test-4 test-3 test-2 test-1\n");
|
||||||
|
|
||||||
let result = scene.ucmd().arg("-tr").succeeds();
|
let result = scene.ucmd().arg("-tr").succeeds();
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n");
|
result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n");
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
result.stdout_only("test-1 test-2 test-3 test-4\n");
|
result.stdout_only("test-1 test-2 test-3 test-4\n");
|
||||||
|
|
||||||
|
let result = scene.ucmd().arg("--sort=time").arg("-r").succeeds();
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
result.stdout_only("test-1\ntest-2\ntest-3\ntest-4\n");
|
||||||
|
#[cfg(windows)]
|
||||||
|
result.stdout_only("test-1 test-2 test-3 test-4\n");
|
||||||
|
|
||||||
// 3 was accessed last in the read
|
// 3 was accessed last in the read
|
||||||
// So the order should be 2 3 4 1
|
// So the order should be 2 3 4 1
|
||||||
let result = scene.ucmd().arg("-tu").succeeds();
|
for arg in &["-u", "--time=atime", "--time=access", "--time=use"] {
|
||||||
let file3_access = at.open("test-3").metadata().unwrap().accessed().unwrap();
|
let result = scene.ucmd().arg("-t").arg(arg).succeeds();
|
||||||
let file4_access = at.open("test-4").metadata().unwrap().accessed().unwrap();
|
let file3_access = at.open("test-3").metadata().unwrap().accessed().unwrap();
|
||||||
|
let file4_access = at.open("test-4").metadata().unwrap().accessed().unwrap();
|
||||||
|
|
||||||
// It seems to be dependent on the platform whether the access time is actually set
|
// It seems to be dependent on the platform whether the access time is actually set
|
||||||
if file3_access > file4_access {
|
if file3_access > file4_access {
|
||||||
if cfg!(not(windows)) {
|
if cfg!(not(windows)) {
|
||||||
result.stdout_only("test-3\ntest-4\ntest-2\ntest-1\n");
|
result.stdout_only("test-3\ntest-4\ntest-2\ntest-1\n");
|
||||||
|
} else {
|
||||||
|
result.stdout_only("test-3 test-4 test-2 test-1\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result.stdout_only("test-3 test-4 test-2 test-1\n");
|
// Access time does not seem to be set on Windows and some other
|
||||||
}
|
// systems so the order is 4 3 2 1
|
||||||
} else {
|
if cfg!(not(windows)) {
|
||||||
// Access time does not seem to be set on Windows and some other
|
result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n");
|
||||||
// systems so the order is 4 3 2 1
|
} else {
|
||||||
if cfg!(not(windows)) {
|
result.stdout_only("test-4 test-3 test-2 test-1\n");
|
||||||
result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n");
|
}
|
||||||
} else {
|
|
||||||
result.stdout_only("test-4 test-3 test-2 test-1\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1059,9 +1127,11 @@ fn test_ls_quoting_style() {
|
||||||
at.touch("one");
|
at.touch("one");
|
||||||
|
|
||||||
// It seems that windows doesn't allow \n in filenames.
|
// It seems that windows doesn't allow \n in filenames.
|
||||||
|
// And it also doesn't like \, of course.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
at.touch("one\ntwo");
|
at.touch("one\ntwo");
|
||||||
|
at.touch("one\\two");
|
||||||
// Default is shell-escape
|
// Default is shell-escape
|
||||||
scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
|
@ -1123,6 +1193,42 @@ fn test_ls_quoting_style() {
|
||||||
.succeeds()
|
.succeeds()
|
||||||
.stdout_only(format!("{}\n", correct));
|
.stdout_only(format!("{}\n", correct));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (arg, correct) in &[
|
||||||
|
("--quoting-style=literal", "one\\two"),
|
||||||
|
("-N", "one\\two"),
|
||||||
|
("--quoting-style=c", "\"one\\\\two\""),
|
||||||
|
("-Q", "\"one\\\\two\""),
|
||||||
|
("--quote-name", "\"one\\\\two\""),
|
||||||
|
("--quoting-style=escape", "one\\\\two"),
|
||||||
|
("-b", "one\\\\two"),
|
||||||
|
("--quoting-style=shell-escape", "'one\\two'"),
|
||||||
|
("--quoting-style=shell-escape-always", "'one\\two'"),
|
||||||
|
("--quoting-style=shell", "'one\\two'"),
|
||||||
|
("--quoting-style=shell-always", "'one\\two'"),
|
||||||
|
] {
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(arg)
|
||||||
|
.arg("one\\two")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only(format!("{}\n", correct));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for a character that forces quotation in shell-style escaping
|
||||||
|
// after a character in a dollar expression
|
||||||
|
at.touch("one\n&two");
|
||||||
|
for (arg, correct) in &[
|
||||||
|
("--quoting-style=shell-escape", "'one'$'\\n''&two'"),
|
||||||
|
("--quoting-style=shell-escape-always", "'one'$'\\n''&two'"),
|
||||||
|
] {
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(arg)
|
||||||
|
.arg("one\n&two")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only(format!("{}\n", correct));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scene
|
scene
|
||||||
|
@ -1323,6 +1429,43 @@ fn test_ls_ignore_hide() {
|
||||||
.stdout_is("CONTRIBUTING.md\nREADME.md\nREADMECAREFULLY.md\nsome_other_file\n");
|
.stdout_is("CONTRIBUTING.md\nREADME.md\nREADMECAREFULLY.md\nsome_other_file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ls_ignore_backups() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
at.touch("somefile");
|
||||||
|
at.touch("somebackup~");
|
||||||
|
at.touch(".somehiddenfile");
|
||||||
|
at.touch(".somehiddenbackup~");
|
||||||
|
|
||||||
|
scene.ucmd().arg("-B").succeeds().stdout_is("somefile\n");
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--ignore-backups")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("somefile\n");
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-aB")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_contains(".somehiddenfile")
|
||||||
|
.stdout_contains("somefile")
|
||||||
|
.stdout_does_not_contain("somebackup")
|
||||||
|
.stdout_does_not_contain(".somehiddenbackup~");
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-a")
|
||||||
|
.arg("--ignore-backups")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_contains(".somehiddenfile")
|
||||||
|
.stdout_contains("somefile")
|
||||||
|
.stdout_does_not_contain("somebackup")
|
||||||
|
.stdout_does_not_contain(".somehiddenbackup~");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ls_directory() {
|
fn test_ls_directory() {
|
||||||
let scene = TestScenario::new(util_name!());
|
let scene = TestScenario::new(util_name!());
|
||||||
|
|
|
@ -612,8 +612,8 @@ fn test_dictionary_and_nonprinting_conflicts() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trailing_separator() {
|
fn test_trailing_separator() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.args(&["-t", "x", "-k", "1,1"])
|
.args(&["-t", "x", "-k", "1,1"])
|
||||||
.pipe_in("aax\naaa\n")
|
.pipe_in("aax\naaa\n")
|
||||||
.succeeds()
|
.succeeds()
|
||||||
.stdout_is("aax\naaa\n");
|
.stdout_is("aax\naaa\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,9 +346,5 @@ fn test_negative_indexing() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sleep_interval() {
|
fn test_sleep_interval() {
|
||||||
new_ucmd!()
|
new_ucmd!().arg("-s").arg("10").arg(FOOBAR_TXT).succeeds();
|
||||||
.arg("-s")
|
|
||||||
.arg("10")
|
|
||||||
.arg(FOOBAR_TXT)
|
|
||||||
.succeeds();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,4 +79,3 @@ fn test_failed_incorrect_arg() {
|
||||||
let (_at, mut ucmd) = at_and_ucmd!();
|
let (_at, mut ucmd) = at_and_ucmd!();
|
||||||
ucmd.args(&["-s", "+5A", TFILE1]).fails();
|
ucmd.args(&["-s", "+5A", TFILE1]).fails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue