1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

Merge branch 'master' into chown_refactor_tests

This commit is contained in:
Jan Scheer 2021-04-17 11:48:43 +02:00
commit 9046e03a48
81 changed files with 711 additions and 668 deletions

2
Cargo.lock generated
View file

@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "advapi32-sys"
version = "0.2.0"

View file

@ -111,6 +111,7 @@ fn basename(fullname: &str, suffix: &str) -> String {
}
}
#[allow(clippy::manual_strip)] // can be replaced with strip_suffix once the minimum rust version is 1.45
fn strip_suffix(name: &str, suffix: &str) -> String {
if name == suffix {
return name.to_owned();

View file

@ -286,7 +286,7 @@ impl Chgrper {
ret = match wrap_chgrp(path, &meta, self.dest_gid, follow, self.verbosity.clone()) {
Ok(n) => {
if n != "" {
if !n.is_empty() {
show_info!("{}", n);
}
0

View file

@ -171,13 +171,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// of a prefix '-' if it's associated with MODE
// e.g. "chmod -v -xw -R FILE" -> "chmod -v xw -R FILE"
pub fn strip_minus_from_mode(args: &mut Vec<String>) -> bool {
for i in 0..args.len() {
if args[i].starts_with("-") {
if let Some(second) = args[i].chars().nth(1) {
for arg in args {
if arg.starts_with('-') {
if let Some(second) = arg.chars().nth(1) {
match second {
'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'..='7' => {
// TODO: use strip_prefix() once minimum rust version reaches 1.45.0
args[i] = args[i][1..args[i].len()].to_string();
*arg = arg[1..arg.len()].to_string();
return true;
}
_ => {}

View file

@ -391,7 +391,7 @@ impl Chowner {
self.verbosity.clone(),
) {
Ok(n) => {
if n != "" {
if !n.is_empty() {
show_info!("{}", n);
}
0
@ -446,7 +446,7 @@ impl Chowner {
self.verbosity.clone(),
) {
Ok(n) => {
if n != "" {
if !n.is_empty() {
show_info!("{}", n);
}
0

View file

@ -104,7 +104,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
_ => {
let mut vector: Vec<&str> = Vec::new();
for (&k, v) in matches.args.iter() {
vector.push(k.clone());
vector.push(k);
vector.push(&v.vals[0].to_str().unwrap());
}
vector
@ -133,7 +133,7 @@ fn set_context(root: &Path, options: &clap::ArgMatches) {
let userspec = match userspec_str {
Some(ref u) => {
let s: Vec<&str> = u.split(':').collect();
if s.len() != 2 || s.iter().any(|&spec| spec == "") {
if s.len() != 2 || s.iter().any(|&spec| spec.is_empty()) {
crash!(1, "invalid userspec: `{}`", u)
};
s
@ -142,16 +142,16 @@ fn set_context(root: &Path, options: &clap::ArgMatches) {
};
let (user, group) = if userspec.is_empty() {
(&user_str[..], &group_str[..])
(user_str, group_str)
} else {
(&userspec[0][..], &userspec[1][..])
(userspec[0], userspec[1])
};
enter_chroot(root);
set_groups_from_str(&groups_str[..]);
set_main_group(&group[..]);
set_user(&user[..]);
set_groups_from_str(groups_str);
set_main_group(group);
set_user(user);
}
fn enter_chroot(root: &Path) {

View file

@ -132,7 +132,9 @@ macro_rules! prompt_yes(
pub type CopyResult<T> = Result<T, Error>;
pub type Source = PathBuf;
pub type SourceSlice = Path;
pub type Target = PathBuf;
pub type TargetSlice = Path;
/// Specifies whether when overwrite files
#[derive(Clone, Eq, PartialEq)]
@ -547,14 +549,13 @@ impl FromStr for Attribute {
}
fn add_all_attributes() -> Vec<Attribute> {
let mut attr = Vec::new();
use Attribute::*;
let mut attr = vec![Ownership, Timestamps, Context, Xattr, Links];
#[cfg(unix)]
attr.push(Attribute::Mode);
attr.push(Attribute::Ownership);
attr.push(Attribute::Timestamps);
attr.push(Attribute::Context);
attr.push(Attribute::Xattr);
attr.push(Attribute::Links);
attr.insert(0, Mode);
attr
}
@ -665,7 +666,7 @@ impl TargetType {
///
/// Treat target as a dir if we have multiple sources or the target
/// exists and already is a directory
fn determine(sources: &[Source], target: &Target) -> TargetType {
fn determine(sources: &[Source], target: &TargetSlice) -> TargetType {
if sources.len() > 1 || target.is_dir() {
TargetType::Directory
} else {
@ -714,7 +715,7 @@ fn parse_path_args(path_args: &[String], options: &Options) -> CopyResult<(Vec<S
fn preserve_hardlinks(
hard_links: &mut Vec<(String, u64)>,
source: &std::path::PathBuf,
source: &std::path::Path,
dest: std::path::PathBuf,
found_hard_link: &mut bool,
) -> CopyResult<()> {
@ -788,7 +789,7 @@ fn preserve_hardlinks(
/// Behavior depends on `options`, see [`Options`] for details.
///
/// [`Options`]: ./struct.Options.html
fn copy(sources: &[Source], target: &Target, options: &Options) -> CopyResult<()> {
fn copy(sources: &[Source], target: &TargetSlice, options: &Options) -> CopyResult<()> {
let target_type = TargetType::determine(sources, target);
verify_target_type(target, &target_type)?;
@ -840,7 +841,7 @@ fn copy(sources: &[Source], target: &Target, options: &Options) -> CopyResult<()
fn construct_dest_path(
source_path: &Path,
target: &Target,
target: &TargetSlice,
target_type: &TargetType,
options: &Options,
) -> CopyResult<PathBuf> {
@ -870,8 +871,8 @@ fn construct_dest_path(
}
fn copy_source(
source: &Source,
target: &Target,
source: &SourceSlice,
target: &TargetSlice,
target_type: &TargetType,
options: &Options,
) -> CopyResult<()> {
@ -912,7 +913,7 @@ fn adjust_canonicalization(p: &Path) -> Cow<Path> {
///
/// Any errors encountered copying files in the tree will be logged but
/// will not cause a short-circuit.
fn copy_directory(root: &Path, target: &Target, options: &Options) -> CopyResult<()> {
fn copy_directory(root: &Path, target: &TargetSlice, options: &Options) -> CopyResult<()> {
if !options.recursive {
return Err(format!("omitting directory '{}'", root.display()).into());
}
@ -1068,6 +1069,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
}
#[cfg(not(windows))]
#[allow(clippy::unnecessary_wraps)] // needed for windows version
fn symlink_file(source: &Path, dest: &Path, context: &str) -> CopyResult<()> {
match std::os::unix::fs::symlink(source, dest).context(context) {
Ok(_) => Ok(()),

View file

@ -406,7 +406,7 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> i32 {
continue;
}
if !path.metadata().is_ok() {
if path.metadata().is_err() {
show_error!("{}: No such file or directory", filename);
continue;
}
@ -535,8 +535,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
matches.value_of(options::CHARACTERS),
matches.value_of(options::FIELDS),
) {
(Some(byte_ranges), None, None) => {
list_to_ranges(&byte_ranges[..], complement).map(|ranges| {
(Some(byte_ranges), None, None) => list_to_ranges(byte_ranges, complement).map(|ranges| {
Mode::Bytes(
ranges,
Options {
@ -549,10 +548,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
},
)
})
}
(None, Some(char_ranges), None) => {
list_to_ranges(&char_ranges[..], complement).map(|ranges| {
}),
(None, Some(char_ranges), None) => list_to_ranges(char_ranges, complement).map(|ranges| {
Mode::Characters(
ranges,
Options {
@ -565,10 +562,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
},
)
})
}
}),
(None, None, Some(field_ranges)) => {
list_to_ranges(&field_ranges[..], complement).and_then(|ranges| {
list_to_ranges(field_ranges, complement).and_then(|ranges| {
let out_delim = match matches.value_of(options::OUTPUT_DELIMITER) {
Some(s) => {
if s.is_empty() {

View file

@ -116,7 +116,6 @@ struct Options {
show_listed_fs: bool,
show_fs_type: bool,
show_inode_instead: bool,
print_grand_total: bool,
// block_size: usize,
human_readable_base: i64,
fs_selector: FsSelector,
@ -286,7 +285,6 @@ impl Options {
show_listed_fs: false,
show_fs_type: false,
show_inode_instead: false,
print_grand_total: false,
// block_size: match env::var("BLOCKSIZE") {
// Ok(size) => size.parse().unwrap(),
// Err(_) => 512,
@ -871,9 +869,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if matches.is_present(OPT_ALL) {
opt.show_all_fs = true;
}
if matches.is_present(OPT_TOTAL) {
opt.print_grand_total = true;
}
if matches.is_present(OPT_INODES) {
opt.show_inode_instead = true;
}

View file

@ -15,7 +15,7 @@ use chrono::Local;
use std::collections::HashSet;
use std::env;
use std::fs;
use std::io::{stderr, Result, Write};
use std::io::{stderr, ErrorKind, Result, Write};
use std::iter;
#[cfg(not(windows))]
use std::os::unix::fs::MetadataExt;
@ -296,7 +296,21 @@ fn du(
}
}
}
Err(error) => show_error!("{}", error),
Err(error) => match error.kind() {
ErrorKind::PermissionDenied => {
let description = format!(
"cannot access '{}'",
entry
.path()
.as_os_str()
.to_str()
.unwrap_or("<Un-printable path>")
);
let error_message = "Permission denied";
show_error_custom_description!(description, "{}", error_message)
}
_ => show_error!("{}", error),
},
},
Err(error) => show_error!("{}", error),
}
@ -322,7 +336,7 @@ fn convert_size_human(size: u64, multiplier: u64, _block_size: u64) -> String {
}
}
if size == 0 {
return format!("0");
return "0".to_string();
}
format!("{}B", size)
}

View file

@ -51,7 +51,7 @@ fn print_expr_error(expr_error: &str) -> ! {
crash!(2, "{}", expr_error)
}
fn evaluate_ast(maybe_ast: Result<Box<syntax_tree::ASTNode>, String>) -> Result<String, String> {
fn evaluate_ast(maybe_ast: Result<Box<syntax_tree::AstNode>, String>) -> Result<String, String> {
if maybe_ast.is_err() {
Err(maybe_ast.err().unwrap())
} else {

View file

@ -17,10 +17,10 @@ use onig::{Regex, RegexOptions, Syntax};
use crate::tokens::Token;
type TokenStack = Vec<(usize, Token)>;
pub type OperandsList = Vec<Box<ASTNode>>;
pub type OperandsList = Vec<Box<AstNode>>;
#[derive(Debug)]
pub enum ASTNode {
pub enum AstNode {
Leaf {
token_idx: usize,
value: String,
@ -31,7 +31,7 @@ pub enum ASTNode {
operands: OperandsList,
},
}
impl ASTNode {
impl AstNode {
fn debug_dump(&self) {
self.debug_dump_impl(1);
}
@ -40,7 +40,7 @@ impl ASTNode {
print!("\t",);
}
match *self {
ASTNode::Leaf {
AstNode::Leaf {
ref token_idx,
ref value,
} => println!(
@ -49,7 +49,7 @@ impl ASTNode {
token_idx,
self.evaluate()
),
ASTNode::Node {
AstNode::Node {
ref token_idx,
ref op_type,
ref operands,
@ -67,23 +67,23 @@ impl ASTNode {
}
}
fn new_node(token_idx: usize, op_type: &str, operands: OperandsList) -> Box<ASTNode> {
Box::new(ASTNode::Node {
fn new_node(token_idx: usize, op_type: &str, operands: OperandsList) -> Box<AstNode> {
Box::new(AstNode::Node {
token_idx,
op_type: op_type.into(),
operands,
})
}
fn new_leaf(token_idx: usize, value: &str) -> Box<ASTNode> {
Box::new(ASTNode::Leaf {
fn new_leaf(token_idx: usize, value: &str) -> Box<AstNode> {
Box::new(AstNode::Leaf {
token_idx,
value: value.into(),
})
}
pub fn evaluate(&self) -> Result<String, String> {
match *self {
ASTNode::Leaf { ref value, .. } => Ok(value.clone()),
ASTNode::Node { ref op_type, .. } => match self.operand_values() {
AstNode::Leaf { ref value, .. } => Ok(value.clone()),
AstNode::Node { ref op_type, .. } => match self.operand_values() {
Err(reason) => Err(reason),
Ok(operand_values) => match op_type.as_ref() {
"+" => infix_operator_two_ints(
@ -161,7 +161,7 @@ impl ASTNode {
}
}
pub fn operand_values(&self) -> Result<Vec<String>, String> {
if let ASTNode::Node { ref operands, .. } = *self {
if let AstNode::Node { ref operands, .. } = *self {
let mut out = Vec::with_capacity(operands.len());
for operand in operands {
match operand.evaluate() {
@ -178,7 +178,7 @@ impl ASTNode {
pub fn tokens_to_ast(
maybe_tokens: Result<Vec<(usize, Token)>, String>,
) -> Result<Box<ASTNode>, String> {
) -> Result<Box<AstNode>, String> {
if maybe_tokens.is_err() {
Err(maybe_tokens.err().unwrap())
} else {
@ -212,7 +212,7 @@ pub fn tokens_to_ast(
}
}
fn maybe_dump_ast(result: &Result<Box<ASTNode>, String>) {
fn maybe_dump_ast(result: &Result<Box<AstNode>, String>) {
use std::env;
if let Ok(debug_var) = env::var("EXPR_DEBUG_AST") {
if debug_var == "1" {
@ -238,11 +238,11 @@ fn maybe_dump_rpn(rpn: &TokenStack) {
}
}
fn ast_from_rpn(rpn: &mut TokenStack) -> Result<Box<ASTNode>, String> {
fn ast_from_rpn(rpn: &mut TokenStack) -> Result<Box<AstNode>, String> {
match rpn.pop() {
None => Err("syntax error (premature end of expression)".to_owned()),
Some((token_idx, Token::Value { value })) => Ok(ASTNode::new_leaf(token_idx, &value)),
Some((token_idx, Token::Value { value })) => Ok(AstNode::new_leaf(token_idx, &value)),
Some((token_idx, Token::InfixOp { value, .. })) => {
maybe_ast_node(token_idx, &value, 2, rpn)
@ -262,7 +262,7 @@ fn maybe_ast_node(
op_type: &str,
arity: usize,
rpn: &mut TokenStack,
) -> Result<Box<ASTNode>, String> {
) -> Result<Box<AstNode>, String> {
let mut operands = Vec::with_capacity(arity);
for _ in 0..arity {
match ast_from_rpn(rpn) {
@ -271,7 +271,7 @@ fn maybe_ast_node(
}
}
operands.reverse();
Ok(ASTNode::new_node(token_idx, op_type, operands))
Ok(AstNode::new_node(token_idx, op_type, operands))
}
fn move_rest_of_ops_to_out(

View file

@ -267,7 +267,7 @@ impl<'a> ParagraphStream<'a> {
#[allow(clippy::match_like_matches_macro)]
// `matches!(...)` macro not stabilized until rust v1.42
l_slice[..colon_posn].chars().all(|x| match x as usize {
y if y < 33 || y > 126 => false,
y if !(33..=126).contains(&y) => false,
_ => true,
})
}

View file

@ -66,7 +66,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true),
)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
.get_matches_from(args.clone());
.get_matches_from(args);
let bytes = matches.is_present(options::BYTES);
let spaces = matches.is_present(options::SPACES);

View file

@ -78,7 +78,7 @@ fn detect_algo<'a>(
"sha512sum" => ("SHA512", Box::new(Sha512::new()) as Box<dyn Digest>, 512),
"b2sum" => ("BLAKE2", Box::new(Blake2b::new(64)) as Box<dyn Digest>, 512),
"sha3sum" => match matches.value_of("bits") {
Some(bits_str) => match usize::from_str_radix(&bits_str, 10) {
Some(bits_str) => match (&bits_str).parse::<usize>() {
Ok(224) => (
"SHA3-224",
Box::new(Sha3_224::new()) as Box<dyn Digest>,
@ -128,7 +128,7 @@ fn detect_algo<'a>(
512,
),
"shake128sum" => match matches.value_of("bits") {
Some(bits_str) => match usize::from_str_radix(&bits_str, 10) {
Some(bits_str) => match (&bits_str).parse::<usize>() {
Ok(bits) => (
"SHAKE128",
Box::new(Shake128::new()) as Box<dyn Digest>,
@ -139,7 +139,7 @@ fn detect_algo<'a>(
None => crash!(1, "--bits required for SHAKE-128"),
},
"shake256sum" => match matches.value_of("bits") {
Some(bits_str) => match usize::from_str_radix(&bits_str, 10) {
Some(bits_str) => match (&bits_str).parse::<usize>() {
Ok(bits) => (
"SHAKE256",
Box::new(Shake256::new()) as Box<dyn Digest>,
@ -182,7 +182,7 @@ fn detect_algo<'a>(
}
if matches.is_present("sha3") {
match matches.value_of("bits") {
Some(bits_str) => match usize::from_str_radix(&bits_str, 10) {
Some(bits_str) => match (&bits_str).parse::<usize>() {
Ok(224) => set_or_crash(
"SHA3-224",
Box::new(Sha3_224::new()) as Box<dyn Digest>,
@ -226,7 +226,7 @@ fn detect_algo<'a>(
}
if matches.is_present("shake128") {
match matches.value_of("bits") {
Some(bits_str) => match usize::from_str_radix(&bits_str, 10) {
Some(bits_str) => match (&bits_str).parse::<usize>() {
Ok(bits) => set_or_crash("SHAKE128", Box::new(Shake128::new()), bits),
Err(err) => crash!(1, "{}", err),
},
@ -235,7 +235,7 @@ fn detect_algo<'a>(
}
if matches.is_present("shake256") {
match matches.value_of("bits") {
Some(bits_str) => match usize::from_str_radix(&bits_str, 10) {
Some(bits_str) => match (&bits_str).parse::<usize>() {
Ok(bits) => set_or_crash("SHAKE256", Box::new(Shake256::new()), bits),
Err(err) => crash!(1, "{}", err),
},
@ -253,7 +253,7 @@ fn detect_algo<'a>(
// TODO: return custom error type
fn parse_bit_num(arg: &str) -> Result<usize, ParseIntError> {
usize::from_str_radix(arg, 10)
arg.parse()
}
fn is_valid_bit_num(arg: String) -> Result<(), String> {

View file

@ -625,7 +625,7 @@ mod tests {
assert_eq!(arg_outputs("head"), Ok("head".to_owned()));
}
#[test]
#[cfg(linux)]
#[cfg(target_os = "linux")]
fn test_arg_iterate_bad_encoding() {
let invalid = unsafe { std::str::from_utf8_unchecked(b"\x80\x81") };
// this arises from a conversion from OsString to &str

View file

@ -302,7 +302,7 @@ fn behavior(matches: &ArgMatches) -> Result<Behavior, i32> {
let specified_mode: Option<u32> = if matches.is_present(OPT_MODE) {
match matches.value_of(OPT_MODE) {
Some(x) => match mode::parse(&x[..], considering_dir) {
Some(x) => match mode::parse(x, considering_dir) {
Ok(y) => Some(y),
Err(err) => {
show_error!("Invalid mode string: {}", err);
@ -429,7 +429,7 @@ fn standard(paths: Vec<String>, b: Behavior) -> i32 {
/// _files_ must all exist as non-directories.
/// _target_dir_ must be a directory.
///
fn copy_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) -> i32 {
fn copy_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> i32 {
if !target_dir.is_dir() {
show_error!("target '{}' is not a directory", target_dir.display());
return 1;
@ -453,7 +453,7 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) ->
continue;
}
let mut targetpath = target_dir.clone().to_path_buf();
let mut targetpath = target_dir.to_path_buf();
let filename = sourcepath.components().last().unwrap();
targetpath.push(filename);
@ -478,7 +478,7 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) ->
/// _file_ must exist as a non-directory.
/// _target_ must be a non-directory
///
fn copy_file_to_file(file: &PathBuf, target: &PathBuf, b: &Behavior) -> i32 {
fn copy_file_to_file(file: &Path, target: &Path, b: &Behavior) -> i32 {
if copy(file, &target, b).is_err() {
1
} else {
@ -497,7 +497,7 @@ fn copy_file_to_file(file: &PathBuf, target: &PathBuf, b: &Behavior) -> i32 {
///
/// If the copy system call fails, we print a verbose error and return an empty error value.
///
fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
fn copy(from: &Path, to: &Path, b: &Behavior) -> Result<(), ()> {
if b.compare && !need_copy(from, to, b) {
return Ok(());
}
@ -556,7 +556,7 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
};
let gid = meta.gid();
match wrap_chown(
to.as_path(),
to,
&meta,
Some(owner_id),
Some(gid),
@ -582,7 +582,7 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
Ok(g) => g,
_ => crash!(1, "no such group: {}", b.group),
};
match wrap_chgrp(to.as_path(), &meta, group_id, false, Verbosity::Normal) {
match wrap_chgrp(to, &meta, group_id, false, Verbosity::Normal) {
Ok(n) => {
if !n.is_empty() {
show_info!("{}", n);
@ -601,7 +601,7 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
let modified_time = FileTime::from_last_modification_time(&meta);
let accessed_time = FileTime::from_last_access_time(&meta);
match set_file_times(to.as_path(), accessed_time, modified_time) {
match set_file_times(to, accessed_time, modified_time) {
Ok(_) => {}
Err(e) => show_info!("{}", e),
}
@ -630,7 +630,7 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
///
/// Crashes the program if a nonexistent owner or group is specified in _b_.
///
fn need_copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> bool {
fn need_copy(from: &Path, to: &Path, b: &Behavior) -> bool {
let from_meta = match fs::metadata(from) {
Ok(meta) => meta,
Err(_) => return true,

View file

@ -303,7 +303,7 @@ fn exec(files: &[PathBuf], settings: &Settings) -> i32 {
}
}
fn link_files_in_dir(files: &[PathBuf], target_dir: &PathBuf, settings: &Settings) -> i32 {
fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings) -> i32 {
if !target_dir.is_dir() {
show_error!("target '{}' is not a directory", target_dir.display());
return 1;
@ -329,7 +329,7 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &PathBuf, settings: &Setting
};
}
}
target_dir.clone()
target_dir.to_path_buf()
} else {
match srcpath.as_os_str().to_str() {
Some(name) => {
@ -370,7 +370,7 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &PathBuf, settings: &Setting
}
}
fn relative_path<'a>(src: &PathBuf, dst: &PathBuf) -> Result<Cow<'a, Path>> {
fn relative_path<'a>(src: &Path, dst: &Path) -> Result<Cow<'a, Path>> {
let abssrc = canonicalize(src, CanonicalizeMode::Normal)?;
let absdst = canonicalize(dst, CanonicalizeMode::Normal)?;
let suffix_pos = abssrc
@ -390,7 +390,7 @@ fn relative_path<'a>(src: &PathBuf, dst: &PathBuf) -> Result<Cow<'a, Path>> {
Ok(result.into())
}
fn link(src: &PathBuf, dst: &PathBuf, settings: &Settings) -> Result<()> {
fn link(src: &Path, dst: &Path, settings: &Settings) -> Result<()> {
let mut backup_path = None;
let source: Cow<'_, Path> = if settings.relative {
relative_path(&src, dst)?
@ -453,13 +453,13 @@ fn read_yes() -> bool {
}
}
fn simple_backup_path(path: &PathBuf, suffix: &str) -> PathBuf {
fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
let mut p = path.as_os_str().to_str().unwrap().to_owned();
p.push_str(suffix);
PathBuf::from(p)
}
fn numbered_backup_path(path: &PathBuf) -> PathBuf {
fn numbered_backup_path(path: &Path) -> PathBuf {
let mut i: u64 = 1;
loop {
let new_path = simple_backup_path(path, &format!(".~{}~", i));
@ -470,7 +470,7 @@ fn numbered_backup_path(path: &PathBuf) -> PathBuf {
}
}
fn existing_backup_path(path: &PathBuf, suffix: &str) -> PathBuf {
fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
let test_path = simple_backup_path(path, &".~1~".to_owned());
if test_path.exists() {
return numbered_backup_path(path);

View file

@ -370,6 +370,7 @@ impl Config {
})
.or_else(|| termsize::get().map(|s| s.cols));
#[allow(clippy::needless_bool)]
let show_control = if options.is_present(options::HIDE_CONTROL_CHARS) {
false
} else if options.is_present(options::SHOW_CONTROL_CHARS) {
@ -1042,7 +1043,7 @@ fn sort_entries(entries: &mut Vec<PathBuf>, config: &Config) {
.sort_by_key(|k| Reverse(get_metadata(k, config).map(|md| md.len()).unwrap_or(0))),
// The default sort in GNU ls is case insensitive
Sort::Name => entries.sort_by_key(|k| k.to_string_lossy().to_lowercase()),
Sort::Version => entries.sort_by(version_cmp::version_cmp),
Sort::Version => entries.sort_by(|a, b| version_cmp::version_cmp(a, b)),
Sort::None => {}
}
@ -1076,7 +1077,7 @@ fn should_display(entry: &DirEntry, config: &Config) -> bool {
true
}
fn enter_directory(dir: &PathBuf, config: &Config) {
fn enter_directory(dir: &Path, config: &Config) {
let mut entries: Vec<_> = safe_unwrap!(fs::read_dir(dir).and_then(Iterator::collect));
entries.retain(|e| should_display(e, config));
@ -1101,7 +1102,7 @@ fn enter_directory(dir: &PathBuf, config: &Config) {
}
}
fn get_metadata(entry: &PathBuf, config: &Config) -> std::io::Result<Metadata> {
fn get_metadata(entry: &Path, config: &Config) -> std::io::Result<Metadata> {
if config.dereference {
entry.metadata().or_else(|_| entry.symlink_metadata())
} else {
@ -1109,7 +1110,7 @@ fn get_metadata(entry: &PathBuf, config: &Config) -> std::io::Result<Metadata> {
}
}
fn display_dir_entry_size(entry: &PathBuf, config: &Config) -> (usize, usize) {
fn display_dir_entry_size(entry: &Path, config: &Config) -> (usize, usize) {
if let Ok(md) = get_metadata(entry, config) {
(
display_symlink_count(&md).len(),
@ -1204,7 +1205,7 @@ fn display_grid(names: impl Iterator<Item = Cell>, width: u16, direction: Direct
use uucore::fs::display_permissions;
fn display_item_long(
item: &PathBuf,
item: &Path,
strip: Option<&Path>,
max_links: usize,
max_size: usize,

View file

@ -1,8 +1,9 @@
use std::{cmp::Ordering, path::PathBuf};
use std::cmp::Ordering;
use std::path::Path;
/// Compare pathbufs in a way that matches the GNU version sort, meaning that
/// Compare paths in a way that matches the GNU version sort, meaning that
/// numbers get sorted in a natural way.
pub(crate) fn version_cmp(a: &PathBuf, b: &PathBuf) -> Ordering {
pub(crate) fn version_cmp(a: &Path, b: &Path) -> Ordering {
let a_string = a.to_string_lossy();
let b_string = b.to_string_lossy();
let mut a = a_string.chars().peekable();

View file

@ -335,7 +335,7 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
0
}
fn move_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) -> i32 {
fn move_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> i32 {
if !target_dir.is_dir() {
show_error!("target {} is not a directory", target_dir.display());
return 1;
@ -373,7 +373,7 @@ fn move_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) ->
}
}
fn rename(from: &PathBuf, to: &PathBuf, b: &Behavior) -> io::Result<()> {
fn rename(from: &Path, to: &Path, b: &Behavior) -> io::Result<()> {
let mut backup_path = None;
if to.exists() {
@ -429,7 +429,7 @@ fn rename(from: &PathBuf, to: &PathBuf, b: &Behavior) -> io::Result<()> {
/// A wrapper around `fs::rename`, so that if it fails, we try falling back on
/// copying and removing.
fn rename_with_fallback(from: &PathBuf, to: &PathBuf) -> io::Result<()> {
fn rename_with_fallback(from: &Path, to: &Path) -> io::Result<()> {
if fs::rename(from, to).is_err() {
// Get metadata without following symlinks
let metadata = from.symlink_metadata()?;
@ -464,7 +464,7 @@ fn rename_with_fallback(from: &PathBuf, to: &PathBuf) -> io::Result<()> {
/// Move the given symlink to the given destination. On Windows, dangling
/// symlinks return an error.
#[inline]
fn rename_symlink_fallback(from: &PathBuf, to: &PathBuf) -> io::Result<()> {
fn rename_symlink_fallback(from: &Path, to: &Path) -> io::Result<()> {
let path_symlink_points_to = fs::read_link(from)?;
#[cfg(unix)]
{
@ -507,20 +507,20 @@ fn read_yes() -> bool {
}
}
fn simple_backup_path(path: &PathBuf, suffix: &str) -> PathBuf {
fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
let mut p = path.to_string_lossy().into_owned();
p.push_str(suffix);
PathBuf::from(p)
}
fn numbered_backup_path(path: &PathBuf) -> PathBuf {
fn numbered_backup_path(path: &Path) -> PathBuf {
(1_u64..)
.map(|i| path.with_extension(format!("~{}~", i)))
.find(|p| !p.exists())
.expect("cannot create backup")
}
fn existing_backup_path(path: &PathBuf, suffix: &str) -> PathBuf {
fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
let test_path = path.with_extension("~1~");
if test_path.exists() {
numbered_backup_path(path)
@ -529,7 +529,7 @@ fn existing_backup_path(path: &PathBuf, suffix: &str) -> PathBuf {
}
}
fn is_empty_dir(path: &PathBuf) -> bool {
fn is_empty_dir(path: &Path) -> bool {
match fs::read_dir(path) {
Ok(contents) => contents.peekable().peek().is_none(),
Err(_e) => false,

View file

@ -118,7 +118,7 @@ struct OdOptions {
}
impl OdOptions {
fn new<'a>(matches: ArgMatches<'a>, args: Vec<String>) -> Result<OdOptions, String> {
fn new(matches: ArgMatches, args: Vec<String>) -> Result<OdOptions, String> {
let byte_order = match matches.value_of(options::ENDIAN) {
None => ByteOrder::Native,
Some("little") => ByteOrder::Little,

View file

@ -63,7 +63,7 @@ pub fn parse_inputs(matches: &dyn CommandLineOpts) -> Result<CommandLineInputs,
}
if input_strings.len() == 2 {
return Ok(CommandLineInputs::FileAndOffset((
input_strings[0].clone().to_owned(),
input_strings[0].to_string(),
n,
None,
)));
@ -106,7 +106,7 @@ pub fn parse_inputs_traditional(input_strings: Vec<&str>) -> Result<CommandLineI
Some(m),
))),
(_, Ok(m)) => Ok(CommandLineInputs::FileAndOffset((
input_strings[0].clone().to_owned(),
input_strings[0].to_string(),
m,
None,
))),
@ -118,7 +118,7 @@ pub fn parse_inputs_traditional(input_strings: Vec<&str>) -> Result<CommandLineI
let label = parse_offset_operand(&input_strings[2]);
match (offset, label) {
(Ok(n), Ok(m)) => Ok(CommandLineInputs::FileAndOffset((
input_strings[0].clone().to_owned(),
input_strings[0].to_string(),
n,
Some(m),
))),

View file

@ -15,7 +15,6 @@ use uucore::utmpx::{self, time, Utmpx};
use std::io::prelude::*;
use std::io::BufReader;
use std::io::Result as IOResult;
use std::fs::File;
use std::os::unix::fs::MetadataExt;
@ -136,12 +135,8 @@ The utmp file will be {}",
};
if do_short_format {
if let Err(e) = pk.short_pinky() {
show_usage_error!("{}", e);
1
} else {
pk.short_pinky();
0
}
} else {
pk.long_pinky()
}
@ -282,7 +277,7 @@ impl Pinky {
println!();
}
fn short_pinky(&self) -> IOResult<()> {
fn short_pinky(&self) {
if self.include_heading {
self.print_heading();
}
@ -295,7 +290,6 @@ impl Pinky {
}
}
}
Ok(())
}
fn long_pinky(&self) -> i32 {

View file

@ -199,8 +199,7 @@ pub fn arrnum_int_add(arrnum: &[u8], basenum: u8, base_ten_int_term: u8) -> Vec<
}
pub fn base_conv_vec(src: &[u8], radix_src: u8, radix_dest: u8) -> Vec<u8> {
let mut result: Vec<u8> = Vec::new();
result.push(0);
let mut result = vec![0];
for i in src {
result = arrnum_int_mult(&result, radix_dest, radix_src);
result = arrnum_int_add(&result, radix_dest, *i);
@ -226,8 +225,7 @@ pub fn base_conv_float(src: &[u8], radix_src: u8, radix_dest: u8) -> f64 {
// to implement this for arbitrary string input.
// until then, the below operates as an outline
// of how it would work.
let mut result: Vec<u8> = Vec::new();
result.push(0);
let result: Vec<u8> = vec![0];
let mut factor: f64 = 1_f64;
let radix_src_float: f64 = f64::from(radix_src);
let mut r: f64 = 0_f64;

View file

@ -263,9 +263,5 @@ pub fn num_format(field: &FormatField, in_str_opt: Option<&String>) -> Option<St
};
// if we have a formatPrimitive, print its results
// according to the field-char appropriate Formatter
if let Some(prim) = prim_opt {
Some(fmtr.primitive_to_str(&prim, field.clone()))
} else {
None
}
prim_opt.map(|prim| fmtr.primitive_to_str(&prim, field.clone()))
}

View file

@ -177,14 +177,14 @@ fn get_config(matches: &clap::ArgMatches) -> Config {
}
if matches.is_present(options::WIDTH) {
let width_str = matches.value_of(options::WIDTH).expect(err_msg).to_string();
config.line_width = crash_if_err!(1, usize::from_str_radix(&width_str, 10));
config.line_width = crash_if_err!(1, (&width_str).parse::<usize>());
}
if matches.is_present(options::GAP_SIZE) {
let gap_str = matches
.value_of(options::GAP_SIZE)
.expect(err_msg)
.to_string();
config.gap_size = crash_if_err!(1, usize::from_str_radix(&gap_str, 10));
config.gap_size = crash_if_err!(1, (&gap_str).parse::<usize>());
}
if matches.is_present(options::FORMAT_ROFF) {
config.format = OutFormat::Roff;

View file

@ -13,7 +13,7 @@ extern crate uucore;
use clap::{App, Arg};
use std::fs;
use std::io::{stdout, Write};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use uucore::fs::{canonicalize, CanonicalizeMode};
const NAME: &str = "readlink";
@ -160,8 +160,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
fn show(path: &PathBuf, no_newline: bool, use_zero: bool) {
let path = path.as_path().to_str().unwrap();
fn show(path: &Path, no_newline: bool, use_zero: bool) {
let path = path.to_str().unwrap();
if use_zero {
print!("{}\0", path);
} else if no_newline {

View file

@ -12,7 +12,7 @@ extern crate uucore;
use clap::{App, Arg};
use std::fs;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use uucore::fs::{canonicalize, CanonicalizeMode};
static ABOUT: &str = "print the resolved path";
@ -82,7 +82,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
retcode
}
fn resolve_path(p: &PathBuf, strip: bool, zero: bool, quiet: bool) -> bool {
fn resolve_path(p: &Path, strip: bool, zero: bool, quiet: bool) -> bool {
let abs = canonicalize(p, CanonicalizeMode::Normal).unwrap();
if strip {

View file

@ -176,7 +176,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
} else if matches.is_present(OPT_PROMPT_MORE) {
InteractiveMode::Once
} else if matches.is_present(OPT_INTERACTIVE) {
match &matches.value_of(OPT_INTERACTIVE).unwrap()[..] {
match matches.value_of(OPT_INTERACTIVE).unwrap() {
"none" => InteractiveMode::None,
"once" => InteractiveMode::Once,
"always" => InteractiveMode::Always,

View file

@ -102,7 +102,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let mut largest_dec = 0;
let mut padding = 0;
let first = if numbers.len() > 1 {
let slice = &numbers[0][..];
let slice = numbers[0];
let len = slice.len();
let dec = slice.find('.').unwrap_or(len);
largest_dec = len - dec;
@ -118,7 +118,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
1.0
};
let increment = if numbers.len() > 2 {
let slice = &numbers[1][..];
let slice = numbers[1];
let len = slice.len();
let dec = slice.find('.').unwrap_or(len);
largest_dec = cmp::max(largest_dec, len - dec);
@ -134,11 +134,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
1.0
};
if increment == 0.0 {
show_error!("increment value: '{}'", &numbers[1][..]);
show_error!("increment value: '{}'", numbers[1]);
return 1;
}
let last = {
let slice = &numbers[numbers.len() - 1][..];
let slice = numbers[numbers.len() - 1];
padding = cmp::max(padding, slice.find('.').unwrap_or_else(|| slice.len()));
match parse_float(slice) {
Ok(n) => n,

View file

@ -363,10 +363,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let force = matches.is_present(options::FORCE);
let remove = matches.is_present(options::REMOVE);
let size_arg = match matches.value_of(options::SIZE) {
Some(s) => Some(s.to_string()),
None => None,
};
let size_arg = matches.value_of(options::SIZE).map(|s| s.to_string());
let size = get_size(size_arg);
let exact = matches.is_present(options::EXACT) && size.is_none(); // if -s is given, ignore -x
let zero = matches.is_present(options::ZERO);
@ -439,6 +436,7 @@ fn pass_name(pass_type: PassType) -> String {
}
}
#[allow(clippy::too_many_arguments)]
fn wipe_file(
path_str: &str,
n_passes: usize,
@ -472,13 +470,10 @@ fn wipe_file(
let mut perms = metadata.permissions();
perms.set_readonly(false);
match fs::set_permissions(path, perms) {
Err(e) => {
if let Err(e) = fs::set_permissions(path, perms) {
show_error!("{}", e);
return;
}
_ => {}
}
}
// Fill up our pass sequence

View file

@ -677,7 +677,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.arg(
Arg::with_name(OPT_PARALLEL)
.long(OPT_PARALLEL)
.help("change the number of threads running concurrently to N")
.help("change the number of threads running concurrently to NUM_THREADS")
.takes_value(true)
.value_name("NUM_THREADS"),
)
@ -1226,7 +1226,7 @@ fn month_parse(line: &str) -> Month {
// GNU splits at any 3 letter match "JUNNNN" is JUN
let pattern = if line.trim().len().ge(&3) {
// Split a 3 and get first element of tuple ".0"
line.split_at(3).0
line.trim().split_at(3).0
} else {
""
};
@ -1262,10 +1262,21 @@ fn month_compare(a: &str, b: &str) -> Ordering {
}
}
fn version_parse(a: &str) -> Version {
let result = Version::parse(a);
match result {
Ok(vers_a) => vers_a,
// Non-version lines parse to 0.0.0
Err(_e) => Version::parse("0.0.0").unwrap(),
}
}
fn version_compare(a: &str, b: &str) -> Ordering {
#![allow(clippy::comparison_chain)]
let ver_a = Version::parse(a);
let ver_b = Version::parse(b);
let ver_a = version_parse(a);
let ver_b = version_parse(b);
// Version::cmp is not implemented; implement comparison directly
if ver_a > ver_b {
Ordering::Greater

View file

@ -35,8 +35,8 @@ extern "C" {
fn set_buffer(stream: *mut FILE, value: &str) {
let (mode, size): (c_int, size_t) = match value {
"0" => (_IONBF, 0 as size_t),
"L" => (_IOLBF, 0 as size_t),
"0" => (_IONBF, 0_usize),
"L" => (_IOLBF, 0_usize),
input => {
let buff_size: usize = match input.parse() {
Ok(num) => num,

View file

@ -141,12 +141,10 @@ fn parse_size(size: &str) -> Option<u64> {
fn check_option(matches: &ArgMatches, name: &str) -> Result<BufferType, ProgramOptionsError> {
match matches.value_of(name) {
Some(value) => match &value[..] {
Some(value) => match value {
"L" => {
if name == options::INPUT {
Err(ProgramOptionsError(format!(
"line buffering stdin is meaningless"
)))
Err(ProgramOptionsError("line buffering stdin is meaningless".to_string()))
} else {
Ok(BufferType::Line)
}

View file

@ -75,7 +75,7 @@ fn open(name: &str) -> Result<Box<dyn Read>> {
"Is a directory",
));
};
if !path.metadata().is_ok() {
if path.metadata().is_err() {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"No such file or directory",

View file

@ -90,7 +90,7 @@ fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {
Box::new(stdin()) as Box<dyn Read>
} else {
let path = Path::new(filename);
if path.is_dir() || !path.metadata().is_ok() {
if path.is_dir() || path.metadata().is_err() {
show_error!(
"failed to open '{}' for reading: No such file or directory",
filename

View file

@ -55,16 +55,16 @@ fn two(args: &[&[u8]], error: &mut bool) -> bool {
b"-d" => path(args[1], PathCondition::Directory),
b"-e" => path(args[1], PathCondition::Exists),
b"-f" => path(args[1], PathCondition::Regular),
b"-g" => path(args[1], PathCondition::GroupIDFlag),
b"-g" => path(args[1], PathCondition::GroupIdFlag),
b"-h" => path(args[1], PathCondition::SymLink),
b"-L" => path(args[1], PathCondition::SymLink),
b"-n" => one(&args[1..]),
b"-p" => path(args[1], PathCondition::FIFO),
b"-p" => path(args[1], PathCondition::Fifo),
b"-r" => path(args[1], PathCondition::Readable),
b"-S" => path(args[1], PathCondition::Socket),
b"-s" => path(args[1], PathCondition::NonEmpty),
b"-t" => isatty(args[1]),
b"-u" => path(args[1], PathCondition::UserIDFlag),
b"-u" => path(args[1], PathCondition::UserIdFlag),
b"-w" => path(args[1], PathCondition::Writable),
b"-x" => path(args[1], PathCondition::Executable),
b"-z" => !one(&args[1..]),
@ -322,13 +322,13 @@ enum PathCondition {
Directory,
Exists,
Regular,
GroupIDFlag,
GroupIdFlag,
SymLink,
FIFO,
Fifo,
Readable,
Socket,
NonEmpty,
UserIDFlag,
UserIdFlag,
Writable,
Executable,
}
@ -390,13 +390,13 @@ fn path(path: &[u8], cond: PathCondition) -> bool {
PathCondition::Directory => file_type.is_dir(),
PathCondition::Exists => true,
PathCondition::Regular => file_type.is_file(),
PathCondition::GroupIDFlag => metadata.mode() & S_ISGID != 0,
PathCondition::GroupIdFlag => metadata.mode() & S_ISGID != 0,
PathCondition::SymLink => metadata.file_type().is_symlink(),
PathCondition::FIFO => file_type.is_fifo(),
PathCondition::Fifo => file_type.is_fifo(),
PathCondition::Readable => perm(metadata, Permission::Read),
PathCondition::Socket => file_type.is_socket(),
PathCondition::NonEmpty => metadata.size() > 0,
PathCondition::UserIDFlag => metadata.mode() & S_ISUID != 0,
PathCondition::UserIdFlag => metadata.mode() & S_ISUID != 0,
PathCondition::Writable => perm(metadata, Permission::Write),
PathCondition::Executable => perm(metadata, Permission::Execute),
}
@ -416,13 +416,13 @@ fn path(path: &[u8], cond: PathCondition) -> bool {
PathCondition::Directory => stat.is_dir(),
PathCondition::Exists => true,
PathCondition::Regular => stat.is_file(),
PathCondition::GroupIDFlag => false,
PathCondition::GroupIdFlag => false,
PathCondition::SymLink => false,
PathCondition::FIFO => false,
PathCondition::Fifo => false,
PathCondition::Readable => false, // TODO
PathCondition::Socket => false,
PathCondition::NonEmpty => stat.len() > 0,
PathCondition::UserIDFlag => false,
PathCondition::UserIdFlag => false,
PathCondition::Writable => false, // TODO
PathCondition::Executable => false, // TODO
}

View file

@ -18,6 +18,7 @@ use filetime::*;
use std::fs::{self, File};
use std::io::Error;
use std::path::Path;
use std::process;
static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Update the access and modification times of each FILE to the current time.";
@ -137,7 +138,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let (mut atime, mut mtime) = if matches.is_present(options::sources::REFERENCE) {
stat(
&matches.value_of(options::sources::REFERENCE).unwrap()[..],
matches.value_of(options::sources::REFERENCE).unwrap(),
!matches.is_present(options::NO_DEREF),
)
} else if matches.is_present(options::sources::DATE)
@ -261,7 +262,27 @@ fn parse_timestamp(s: &str) -> FileTime {
};
match time::strptime(&ts, format) {
Ok(tm) => local_tm_to_filetime(to_local(tm)),
Ok(tm) => {
let mut local = to_local(tm);
local.tm_isdst = -1;
let ft = local_tm_to_filetime(local);
// We have to check that ft is valid time. Due to daylight saving
// time switch, local time can jump from 1:59 AM to 3:00 AM,
// in which case any time between 2:00 AM and 2:59 AM is not valid.
// Convert back to local time and see if we got the same value back.
let ts = time::Timespec {
sec: ft.unix_seconds(),
nsec: 0,
};
let tm2 = time::at(ts);
if tm.tm_hour != tm2.tm_hour {
show_error!("invalid date format {}", s);
process::exit(1);
}
ft
}
Err(e) => panic!("Unable to parse timestamp\n{}", e),
}
}

View file

@ -24,7 +24,7 @@ use std::ops::RangeInclusive;
fn parse_sequence(s: &str) -> (char, usize) {
let c = s.chars().next().expect("invalid escape: empty string");
if '0' <= c && c <= '7' {
if ('0'..='7').contains(&c) {
let mut v = c.to_digit(8).unwrap();
let mut consumed = 1;
let bits_per_digit = 3;

View file

@ -32,13 +32,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.version(VERSION)
.usage(USAGE)
.about(SUMMARY)
.arg(Arg::with_name(options::FILE).hidden(true))
.arg(
Arg::with_name(options::FILE)
.default_value("-")
.hidden(true),
)
.get_matches_from(args);
let input = match matches.value_of(options::FILE) {
Some(v) => v,
None => "-",
};
let input = matches
.value_of(options::FILE)
.expect("Value is required by clap");
let mut stdin_buf;
let mut file_buf;

View file

@ -65,9 +65,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
return if is_stdin_interactive() {
if is_stdin_interactive() {
libc::EXIT_SUCCESS
} else {
libc::EXIT_FAILURE
};
}
}

View file

@ -149,10 +149,8 @@ fn next_tabstop(tabstops: &[usize], col: usize) -> Option<usize> {
Some(tabstops[0] - col % tabstops[0])
} else {
// find next larger tab
match tabstops.iter().find(|&&t| t > col) {
Some(t) => Some(t - col),
None => None, // if there isn't one in the list, tab becomes a single space
}
// if there isn't one in the list, tab becomes a single space
tabstops.iter().find(|&&t| t > col).map(|t| t-col)
}
}

View file

@ -72,8 +72,7 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> WcResult<usi
#[cfg(unix)]
{
let fd = handle.as_raw_fd();
match fstat(fd) {
Ok(stat) => {
if let Ok(stat) = fstat(fd) {
// If the file is regular, then the `st_size` should hold
// the file's size in bytes.
if (stat.st_mode & S_IFREG) != 0 {
@ -90,12 +89,10 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> WcResult<usi
}
}
}
_ => {}
}
}
// Fall back on `read`, but without the overhead of counting words and lines.
let mut buf = [0 as u8; BUF_SIZE];
let mut buf = [0_u8; BUF_SIZE];
let mut byte_count = 0;
loop {
match handle.read(&mut buf) {

View file

@ -138,11 +138,8 @@ impl AddAssign for WordCount {
}
impl WordCount {
fn with_title<'a>(self, title: &'a str) -> TitledWordCount<'a> {
return TitledWordCount {
title: title,
count: self,
};
fn with_title(self, title: &str) -> TitledWordCount {
TitledWordCount { title, count: self }
}
}
@ -251,7 +248,7 @@ fn is_word_separator(byte: u8) -> bool {
fn word_count_from_reader<T: WordCountable>(
mut reader: T,
settings: &Settings,
path: &String,
path: &str,
) -> WcResult<WordCount> {
let only_count_bytes = settings.show_bytes
&& (!(settings.show_chars
@ -333,18 +330,18 @@ fn word_count_from_reader<T: WordCountable>(
})
}
fn word_count_from_path(path: &String, settings: &Settings) -> WcResult<WordCount> {
fn word_count_from_path(path: &str, settings: &Settings) -> WcResult<WordCount> {
if path == "-" {
let stdin = io::stdin();
let stdin_lock = stdin.lock();
return Ok(word_count_from_reader(stdin_lock, settings, path)?);
word_count_from_reader(stdin_lock, settings, path)
} else {
let path_obj = Path::new(path);
if path_obj.is_dir() {
return Err(WcError::IsDirectory(path.clone()));
Err(WcError::IsDirectory(path.to_owned()))
} else {
let file = File::open(path)?;
return Ok(word_count_from_reader(file, settings, path)?);
word_count_from_reader(file, settings, path)
}
}
}
@ -425,7 +422,7 @@ fn print_stats(
}
if result.title == "-" {
writeln!(stdout_lock, "")?;
writeln!(stdout_lock)?;
} else {
writeln!(stdout_lock, " {}", result.title)?;
}

View file

@ -222,7 +222,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
need_runlevel,
need_users,
my_line_only,
has_records: false,
args: matches.free,
};
@ -247,7 +246,6 @@ struct Who {
need_runlevel: bool,
need_users: bool,
my_line_only: bool,
has_records: bool,
args: Vec<String>,
}
@ -321,8 +319,7 @@ impl Who {
println!("{}", users.join(" "));
println!("# users={}", users.len());
} else {
let mut records = Utmpx::iter_all_records().read_from(f).peekable();
self.has_records = records.peek().is_some();
let records = Utmpx::iter_all_records().read_from(f).peekable();
if self.include_heading {
self.print_heading()

View file

@ -31,9 +31,9 @@ fn chgrp<P: AsRef<Path>>(path: P, dgid: gid_t, follow: bool) -> IOResult<()> {
let s = CString::new(path.as_os_str().as_bytes()).unwrap();
let ret = unsafe {
if follow {
libc::chown(s.as_ptr(), (0 as gid_t).wrapping_sub(1), dgid)
libc::chown(s.as_ptr(), 0_u32.wrapping_sub(1), dgid)
} else {
lchown(s.as_ptr(), (0 as gid_t).wrapping_sub(1), dgid)
lchown(s.as_ptr(), 0_u32.wrapping_sub(1), dgid)
}
};
if ret == 0 {

View file

@ -31,6 +31,14 @@ macro_rules! show_error(
);
/// Show a warning to stderr in a silimar style to GNU coreutils.
#[macro_export]
macro_rules! show_error_custom_description (
($err:expr,$($args:tt)+) => ({
eprint!("{}: {}: ", executable!(), $err);
eprintln!($($args)+);
})
);
#[macro_export]
macro_rules! show_warning(
($($args:tt)+) => ({

View file

@ -2,17 +2,13 @@ use crate::common::util::*;
#[test]
fn test_arch() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
assert!(result.success);
new_ucmd!().succeeds();
}
#[test]
fn test_arch_help() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("--help").run();
assert!(result.success);
assert!(result.stdout.contains("architecture name"));
new_ucmd!()
.arg("--help")
.succeeds()
.stdout_contains("architecture name");
}

View file

@ -66,7 +66,7 @@ fn test_zero_param() {
}
fn expect_error(input: Vec<&str>) {
assert!(new_ucmd!().args(&input).fails().no_stdout().stderr.len() > 0);
assert!(new_ucmd!().args(&input).fails().no_stdout().stderr().len() > 0);
}
#[test]

View file

@ -26,6 +26,7 @@ fn test_no_options() {
}
#[test]
#[cfg(unix)]
fn test_no_options_big_input() {
for &n in &[
0,
@ -108,6 +109,7 @@ fn test_directory_and_file() {
}
#[test]
#[cfg(unix)]
fn test_three_directories_and_file_and_stdin() {
let s = TestScenario::new(util_name!());
s.fixtures.mkdir("test_directory3");

View file

@ -149,7 +149,7 @@ fn test_big_h() {
.arg("bin")
.arg("/proc/self/fd")
.fails()
.stderr
.stderr_str()
.lines()
.fold(0, |acc, _| acc + 1)
> 1

View file

@ -48,7 +48,7 @@ fn run_single_test(test: &TestCase, at: AtPath, mut ucmd: UCommand) {
}
let r = ucmd.run();
if !r.success {
println!("{}", r.stderr);
println!("{}", r.stderr_str());
panic!("{:?}: failed", ucmd.raw);
}
@ -297,13 +297,14 @@ fn test_chmod_recursive() {
mkfile(&at.plus_as_string("a/b/c/c"), 0o100444);
mkfile(&at.plus_as_string("z/y"), 0o100444);
let result = ucmd
.arg("-R")
ucmd.arg("-R")
.arg("--verbose")
.arg("-r,a+w")
.arg("a")
.arg("z")
.succeeds();
.succeeds()
.stderr_contains(&"to 333 (-wx-wx-wx)")
.stderr_contains(&"to 222 (-w--w--w-)");
assert_eq!(at.metadata("z/y").permissions().mode(), 0o100222);
assert_eq!(at.metadata("a/a").permissions().mode(), 0o100222);
@ -312,8 +313,6 @@ fn test_chmod_recursive() {
println!("mode {:o}", at.metadata("a").permissions().mode());
assert_eq!(at.metadata("a").permissions().mode(), 0o40333);
assert_eq!(at.metadata("z").permissions().mode(), 0o40333);
assert!(result.stderr.contains("to 333 (-wx-wx-wx)"));
assert!(result.stderr.contains("to 222 (-w--w--w-)"));
unsafe {
umask(original_umask);
@ -322,30 +321,24 @@ fn test_chmod_recursive() {
#[test]
fn test_chmod_non_existing_file() {
let (_at, mut ucmd) = at_and_ucmd!();
let result = ucmd
new_ucmd!()
.arg("-R")
.arg("--verbose")
.arg("-r,a+w")
.arg("dont-exist")
.fails();
assert!(result
.stderr
.contains("cannot access 'dont-exist': No such file or directory"));
.fails()
.stderr_contains(&"cannot access 'dont-exist': No such file or directory");
}
#[test]
fn test_chmod_preserve_root() {
let (_at, mut ucmd) = at_and_ucmd!();
let result = ucmd
new_ucmd!()
.arg("-R")
.arg("--preserve-root")
.arg("755")
.arg("/")
.fails();
assert!(result
.stderr
.contains("chmod: error: it is dangerous to operate recursively on '/'"));
.fails()
.stderr_contains(&"chmod: error: it is dangerous to operate recursively on '/'");
}
#[test]
@ -362,33 +355,27 @@ fn test_chmod_symlink_non_existing_file() {
let expected_stderr = &format!("cannot operate on dangling symlink '{}'", test_symlink);
at.symlink_file(non_existing, test_symlink);
let mut result;
// this cannot succeed since the symbolic link dangles
result = scene.ucmd().arg("755").arg("-v").arg(test_symlink).fails();
println!("stdout = {:?}", result.stdout);
println!("stderr = {:?}", result.stderr);
assert!(result.stdout.contains(expected_stdout));
assert!(result.stderr.contains(expected_stderr));
assert_eq!(result.code, Some(1));
scene.ucmd()
.arg("755")
.arg("-v")
.arg(test_symlink)
.fails()
.code_is(1)
.stdout_contains(expected_stdout)
.stderr_contains(expected_stderr);
// this should be the same than with just '-v' but without stderr
result = scene
.ucmd()
scene.ucmd()
.arg("755")
.arg("-v")
.arg("-f")
.arg(test_symlink)
.fails();
println!("stdout = {:?}", result.stdout);
println!("stderr = {:?}", result.stderr);
assert!(result.stdout.contains(expected_stdout));
assert!(result.stderr.is_empty());
assert_eq!(result.code, Some(1));
.run()
.code_is(1)
.no_stderr()
.stdout_contains(expected_stdout);
}
#[test]
@ -405,18 +392,15 @@ fn test_chmod_symlink_non_existing_file_recursive() {
non_existing,
&format!("{}/{}", test_directory, test_symlink),
);
let mut result;
// this should succeed
result = scene
.ucmd()
scene.ucmd()
.arg("-R")
.arg("755")
.arg(test_directory)
.succeeds();
assert_eq!(result.code, Some(0));
assert!(result.stdout.is_empty());
assert!(result.stderr.is_empty());
.succeeds()
.no_stderr()
.no_stdout();
let expected_stdout = &format!(
"mode of '{}' retained as 0755 (rwxr-xr-x)\nneither symbolic link '{}/{}' nor referent has been changed",
@ -424,37 +408,25 @@ fn test_chmod_symlink_non_existing_file_recursive() {
);
// '-v': this should succeed without stderr
result = scene
.ucmd()
scene.ucmd()
.arg("-R")
.arg("-v")
.arg("755")
.arg(test_directory)
.succeeds();
println!("stdout = {:?}", result.stdout);
println!("stderr = {:?}", result.stderr);
assert!(result.stdout.contains(expected_stdout));
assert!(result.stderr.is_empty());
assert_eq!(result.code, Some(0));
.succeeds()
.stdout_contains(expected_stdout)
.no_stderr();
// '-vf': this should be the same than with just '-v'
result = scene
.ucmd()
scene.ucmd()
.arg("-R")
.arg("-v")
.arg("-f")
.arg("755")
.arg(test_directory)
.succeeds();
println!("stdout = {:?}", result.stdout);
println!("stderr = {:?}", result.stderr);
assert!(result.stdout.contains(expected_stdout));
assert!(result.stderr.is_empty());
assert_eq!(result.code, Some(0));
.succeeds()
.stdout_contains(expected_stdout)
.no_stderr();
}
#[test]

View file

@ -64,14 +64,14 @@ fn test_preference_of_userspec() {
// As seems to be a configuration issue, ignoring it
return;
}
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
let username = result.stdout.trim_end();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let username = result.stdout_str().trim_end();
let ts = TestScenario::new("id");
let result = ts.cmd("id").arg("-g").arg("-n").run();
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return id.
@ -79,7 +79,7 @@ fn test_preference_of_userspec() {
return;
}
let group_name = result.stdout.trim_end();
let group_name = result.stdout_str().trim_end();
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("a");
@ -93,6 +93,6 @@ fn test_preference_of_userspec() {
.arg(format!("--userspec={}:{}", username, group_name))
.run();
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
}

View file

@ -35,14 +35,19 @@ fn test_empty() {
}
#[test]
#[ignore]
fn test_arg_overrides_stdin() {
let (at, mut ucmd) = at_and_ucmd!();
let input = "foobarfoobar";
at.touch("a");
let result = ucmd.arg("a").pipe_in(input.as_bytes()).run();
let result = ucmd
.arg("a")
.pipe_in(input.as_bytes())
// the command might have exited before all bytes have been pipe in.
// in that case, we don't care about the error (broken pipe)
.ignore_stdin_write_error()
.run();
println!("{}, {}", result.stdout, result.stderr);

View file

@ -275,8 +275,8 @@ fn test_cp_arg_no_clobber_twice() {
.arg("dest.txt")
.run();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
println!("stderr = {:?}", result.stderr_str());
println!("stdout = {:?}", result.stdout_str());
assert!(result.success);
assert!(result.stderr.is_empty());
assert_eq!(at.read("source.txt"), "");
@ -317,8 +317,8 @@ fn test_cp_arg_force() {
.arg(TEST_HELLO_WORLD_DEST)
.run();
println!("{:?}", result.stderr);
println!("{:?}", result.stdout);
println!("{:?}", result.stderr_str());
println!("{:?}", result.stdout_str());
assert!(result.success);
assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
@ -602,7 +602,7 @@ fn test_cp_deref_folder_to_folder() {
.arg(TEST_COPY_FROM_FOLDER)
.arg(TEST_COPY_TO_FOLDER_NEW)
.run();
println!("cp output {}", result.stdout);
println!("cp output {}", result.stdout_str());
// Check that the exit code represents a successful copy.
assert!(result.success);
@ -611,12 +611,12 @@ fn test_cp_deref_folder_to_folder() {
{
let scene2 = TestScenario::new("ls");
let result = scene2.cmd("ls").arg("-al").arg(path_to_new_symlink).run();
println!("ls source {}", result.stdout);
println!("ls source {}", result.stdout_str());
let path_to_new_symlink = at.subdir.join(TEST_COPY_TO_FOLDER_NEW);
let result = scene2.cmd("ls").arg("-al").arg(path_to_new_symlink).run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
}
#[cfg(windows)]
@ -706,7 +706,7 @@ fn test_cp_no_deref_folder_to_folder() {
.arg(TEST_COPY_FROM_FOLDER)
.arg(TEST_COPY_TO_FOLDER_NEW)
.run();
println!("cp output {}", result.stdout);
println!("cp output {}", result.stdout_str());
// Check that the exit code represents a successful copy.
assert!(result.success);
@ -715,12 +715,12 @@ fn test_cp_no_deref_folder_to_folder() {
{
let scene2 = TestScenario::new("ls");
let result = scene2.cmd("ls").arg("-al").arg(path_to_new_symlink).run();
println!("ls source {}", result.stdout);
println!("ls source {}", result.stdout_str());
let path_to_new_symlink = at.subdir.join(TEST_COPY_TO_FOLDER_NEW);
let result = scene2.cmd("ls").arg("-al").arg(path_to_new_symlink).run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
}
#[cfg(windows)]
@ -809,7 +809,7 @@ fn test_cp_archive() {
let scene2 = TestScenario::new("ls");
let result = scene2.cmd("ls").arg("-al").arg(at.subdir).run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
assert_eq!(creation, creation2);
assert!(result.success);
}
@ -863,7 +863,7 @@ fn test_cp_archive_recursive() {
.arg(&at.subdir.join(TEST_COPY_TO_FOLDER))
.run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
let scene2 = TestScenario::new("ls");
let result = scene2
@ -872,7 +872,7 @@ fn test_cp_archive_recursive() {
.arg(&at.subdir.join(TEST_COPY_TO_FOLDER_NEW))
.run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
assert!(at.file_exists(
&at.subdir
.join(TEST_COPY_TO_FOLDER_NEW)
@ -946,7 +946,7 @@ fn test_cp_preserve_timestamps() {
let scene2 = TestScenario::new("ls");
let result = scene2.cmd("ls").arg("-al").arg(at.subdir).run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
assert_eq!(creation, creation2);
assert!(result.success);
}
@ -984,7 +984,7 @@ fn test_cp_dont_preserve_timestamps() {
let scene2 = TestScenario::new("ls");
let result = scene2.cmd("ls").arg("-al").arg(at.subdir).run();
println!("ls dest {}", result.stdout);
println!("ls dest {}", result.stdout_str());
println!("creation {:?} / {:?}", creation, creation2);
assert_ne!(creation, creation2);

View file

@ -28,13 +28,13 @@ fn test_date_rfc_3339() {
// Check that the output matches the regexp
let rfc_regexp = r"(\d+)-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])\s([01]\d|2[0-3]):([0-5]\d):([0-5]\d|60)(\.\d+)?(([Zz])|([\+|\-]([01]\d|2[0-3])))";
let re = Regex::new(rfc_regexp).unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
result = scene.ucmd().arg("--rfc-3339=seconds").succeeds();
// Check that the output matches the regexp
let re = Regex::new(rfc_regexp).unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
}
#[test]
@ -73,13 +73,13 @@ fn test_date_format_y() {
assert!(result.success);
let mut re = Regex::new(r"^\d{4}$").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
result = scene.ucmd().arg("+%y").succeeds();
assert!(result.success);
re = Regex::new(r"^\d{2}$").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
}
#[test]
@ -90,13 +90,13 @@ fn test_date_format_m() {
assert!(result.success);
let mut re = Regex::new(r"\S+").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
result = scene.ucmd().arg("+%m").succeeds();
assert!(result.success);
re = Regex::new(r"^\d{2}$").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
}
#[test]
@ -107,20 +107,20 @@ fn test_date_format_day() {
assert!(result.success);
let mut re = Regex::new(r"\S+").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
result = scene.ucmd().arg("+%A").succeeds();
assert!(result.success);
re = Regex::new(r"\S+").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
result = scene.ucmd().arg("+%u").succeeds();
assert!(result.success);
re = Regex::new(r"^\d{1}$").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
}
#[test]
@ -131,7 +131,7 @@ fn test_date_format_full_day() {
assert!(result.success);
let re = Regex::new(r"\S+ \d{4}-\d{2}-\d{2}").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str().trim()));
}
#[test]

View file

@ -7,10 +7,9 @@ const SUB_LINK: &str = "subdir/links/sublink.txt";
#[test]
fn test_du_basics() {
let (_at, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
assert!(result.success);
assert_eq!(result.stderr, "");
new_ucmd!()
.succeeds()
.no_stderr();
}
#[cfg(target_vendor = "apple")]
fn _du_basics(s: String) {
@ -22,7 +21,7 @@ fn _du_basics(s: String) {
assert_eq!(s, answer);
}
#[cfg(not(target_vendor = "apple"))]
fn _du_basics(s: String) {
fn _du_basics(s: &str) {
let answer = "28\t./subdir
8\t./subdir/deeper
16\t./subdir/links
@ -38,19 +37,19 @@ fn test_du_basics_subdir() {
let result = ucmd.arg(SUB_DIR).run();
assert!(result.success);
assert_eq!(result.stderr, "");
_du_basics_subdir(result.stdout);
_du_basics_subdir(result.stdout_str());
}
#[cfg(target_vendor = "apple")]
fn _du_basics_subdir(s: String) {
fn _du_basics_subdir(s: &str) {
assert_eq!(s, "4\tsubdir/deeper\n");
}
#[cfg(target_os = "windows")]
fn _du_basics_subdir(s: String) {
fn _du_basics_subdir(s: &str) {
assert_eq!(s, "0\tsubdir/deeper\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_basics_subdir(s: String) {
fn _du_basics_subdir(s: &str) {
// MS-WSL linux has altered expected output
if !is_wsl() {
assert_eq!(s, "8\tsubdir/deeper\n");
@ -64,7 +63,7 @@ fn test_du_basics_bad_name() {
let (_at, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("bad_name").run();
assert_eq!(result.stdout, "");
assert_eq!(result.stdout_str(), "");
assert_eq!(
result.stderr,
"du: error: bad_name: No such file or directory\n"
@ -81,20 +80,20 @@ fn test_du_soft_link() {
let result = ts.ucmd().arg(SUB_DIR_LINKS).run();
assert!(result.success);
assert_eq!(result.stderr, "");
_du_soft_link(result.stdout);
_du_soft_link(result.stdout_str());
}
#[cfg(target_vendor = "apple")]
fn _du_soft_link(s: String) {
fn _du_soft_link(s: &str) {
// 'macos' host variants may have `du` output variation for soft links
assert!((s == "12\tsubdir/links\n") || (s == "16\tsubdir/links\n"));
}
#[cfg(target_os = "windows")]
fn _du_soft_link(s: String) {
fn _du_soft_link(s: &str) {
assert_eq!(s, "8\tsubdir/links\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_soft_link(s: String) {
fn _du_soft_link(s: &str) {
// MS-WSL linux has altered expected output
if !is_wsl() {
assert_eq!(s, "16\tsubdir/links\n");
@ -114,19 +113,19 @@ fn test_du_hard_link() {
assert!(result.success);
assert_eq!(result.stderr, "");
// We do not double count hard links as the inodes are identical
_du_hard_link(result.stdout);
_du_hard_link(result.stdout_str());
}
#[cfg(target_vendor = "apple")]
fn _du_hard_link(s: String) {
fn _du_hard_link(s: &str) {
assert_eq!(s, "12\tsubdir/links\n")
}
#[cfg(target_os = "windows")]
fn _du_hard_link(s: String) {
fn _du_hard_link(s: &str) {
assert_eq!(s, "8\tsubdir/links\n")
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_hard_link(s: String) {
fn _du_hard_link(s: &str) {
// MS-WSL linux has altered expected output
if !is_wsl() {
assert_eq!(s, "16\tsubdir/links\n");
@ -142,19 +141,19 @@ fn test_du_d_flag() {
let result = ts.ucmd().arg("-d").arg("1").run();
assert!(result.success);
assert_eq!(result.stderr, "");
_du_d_flag(result.stdout);
_du_d_flag(result.stdout_str());
}
#[cfg(target_vendor = "apple")]
fn _du_d_flag(s: String) {
fn _du_d_flag(s: &str) {
assert_eq!(s, "16\t./subdir\n20\t./\n");
}
#[cfg(target_os = "windows")]
fn _du_d_flag(s: String) {
fn _du_d_flag(s: &str) {
assert_eq!(s, "8\t./subdir\n8\t./\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_d_flag(s: String) {
fn _du_d_flag(s: &str) {
// MS-WSL linux has altered expected output
if !is_wsl() {
assert_eq!(s, "28\t./subdir\n36\t./\n");
@ -167,10 +166,11 @@ fn _du_d_flag(s: String) {
fn test_du_h_flag_empty_file() {
let ts = TestScenario::new("du");
let result = ts.ucmd().arg("-h").arg("empty.txt").run();
assert!(result.success);
assert_eq!(result.stderr, "");
assert_eq!(result.stdout, "0\tempty.txt\n");
ts.ucmd()
.arg("-h")
.arg("empty.txt")
.succeeds()
.stdout_only("0\tempty.txt\n");
}
#[cfg(feature = "touch")]
@ -190,3 +190,33 @@ fn test_du_time() {
assert_eq!(result.stderr, "");
assert_eq!(result.stdout, "0\t2015-05-15 00:00\tdate_test\n");
}
#[cfg(not(target_os = "windows"))]
#[cfg(feature = "chmod")]
#[test]
fn test_du_no_permission() {
let ts = TestScenario::new("du");
let chmod = ts.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).run();
println!("chmod output: {:?}", chmod);
assert!(chmod.success);
let result = ts.ucmd().arg(SUB_DIR_LINKS).run();
ts.ccmd("chmod").arg("+r").arg(SUB_DIR_LINKS).run();
assert!(result.success);
assert_eq!(
result.stderr,
"du: cannot read directory subdir/links: Permission denied (os error 13)\n"
);
_du_no_permission(result.stdout);
}
#[cfg(target_vendor = "apple")]
fn _du_no_permission(s: String) {
assert_eq!(s, "0\tsubdir/links\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_no_permission(s: String) {
assert_eq!(s, "4\tsubdir/links\n");
}

View file

@ -2,22 +2,20 @@ use crate::common::util::*;
#[test]
fn test_default() {
//CmdResult.stdout_only(...) trims trailing newlines
assert_eq!("hi\n", new_ucmd!().arg("hi").succeeds().no_stderr().stdout);
new_ucmd!()
.arg("hi")
.succeeds()
.stdout_only("hi\n");
}
#[test]
fn test_no_trailing_newline() {
//CmdResult.stdout_only(...) trims trailing newlines
assert_eq!(
"hi",
new_ucmd!()
.arg("-n")
.arg("hi")
.succeeds()
.no_stderr()
.stdout
);
.stdout_only("hi");
}
#[test]
@ -192,39 +190,38 @@ fn test_hyphen_values_inside_string() {
new_ucmd!()
.arg("'\"\n'CXXFLAGS=-g -O2'\n\"'")
.succeeds()
.stdout
.contains("CXXFLAGS");
.stdout_contains("CXXFLAGS");
}
#[test]
fn test_hyphen_values_at_start() {
let result = new_ucmd!()
new_ucmd!()
.arg("-E")
.arg("-test")
.arg("araba")
.arg("-merci")
.run();
assert!(result.success);
assert_eq!(false, result.stdout.contains("-E"));
assert_eq!(result.stdout, "-test araba -merci\n");
.run()
.success()
.stdout_does_not_contain("-E")
.stdout_is("-test araba -merci\n");
}
#[test]
fn test_hyphen_values_between() {
let result = new_ucmd!().arg("test").arg("-E").arg("araba").run();
new_ucmd!()
.arg("test")
.arg("-E")
.arg("araba")
.run()
.success()
.stdout_is("test -E araba\n");
assert!(result.success);
assert_eq!(result.stdout, "test -E araba\n");
let result = new_ucmd!()
new_ucmd!()
.arg("dumdum ")
.arg("dum dum dum")
.arg("-e")
.arg("dum")
.run();
assert!(result.success);
assert_eq!(result.stdout, "dumdum dum dum dum -e dum\n");
assert_eq!(true, result.stdout.contains("-e"));
.run()
.success()
.stdout_is("dumdum dum dum dum -e dum\n");
}

View file

@ -8,45 +8,35 @@ use tempfile::tempdir;
#[test]
fn test_env_help() {
assert!(new_ucmd!()
new_ucmd!()
.arg("--help")
.succeeds()
.no_stderr()
.stdout
.contains("OPTIONS:"));
.stdout_contains("OPTIONS:");
}
#[test]
fn test_env_version() {
assert!(new_ucmd!()
new_ucmd!()
.arg("--version")
.succeeds()
.no_stderr()
.stdout
.contains(util_name!()));
.stdout_contains(util_name!());
}
#[test]
fn test_echo() {
// assert!(new_ucmd!().arg("printf").arg("FOO-bar").succeeds().no_stderr().stdout.contains("FOO-bar"));
let mut cmd = new_ucmd!();
cmd.arg("echo").arg("FOO-bar");
println!("cmd={:?}", cmd);
let result = new_ucmd!()
.arg("echo")
.arg("FOO-bar")
.succeeds();
let result = cmd.run();
println!("success={:?}", result.success);
println!("stdout={:?}", result.stdout);
println!("stderr={:?}", result.stderr);
assert!(result.success);
let out = result.stdout.trim_end();
assert_eq!(out, "FOO-bar");
assert_eq!(result.stdout_str().trim(), "FOO-bar");
}
#[test]
fn test_file_option() {
let out = new_ucmd!().arg("-f").arg("vars.conf.txt").run().stdout;
let out = new_ucmd!().arg("-f").arg("vars.conf.txt").run().stdout_move_str();
assert_eq!(
out.lines()
@ -63,7 +53,7 @@ fn test_combined_file_set() {
.arg("vars.conf.txt")
.arg("FOO=bar.alt")
.run()
.stdout;
.stdout_move_str();
assert_eq!(out.lines().filter(|&line| line == "FOO=bar.alt").count(), 1);
}
@ -76,8 +66,8 @@ fn test_combined_file_set_unset() {
.arg("-f")
.arg("vars.conf.txt")
.arg("FOO=bar.alt")
.run()
.stdout;
.succeeds()
.stdout_move_str();
assert_eq!(
out.lines()
@ -89,17 +79,17 @@ fn test_combined_file_set_unset() {
#[test]
fn test_single_name_value_pair() {
let out = new_ucmd!().arg("FOO=bar").run().stdout;
let out = new_ucmd!().arg("FOO=bar").run();
assert!(out.lines().any(|line| line == "FOO=bar"));
assert!(out.stdout_str().lines().any(|line| line == "FOO=bar"));
}
#[test]
fn test_multiple_name_value_pairs() {
let out = new_ucmd!().arg("FOO=bar").arg("ABC=xyz").run().stdout;
let out = new_ucmd!().arg("FOO=bar").arg("ABC=xyz").run();
assert_eq!(
out.lines()
out.stdout_str().lines()
.filter(|&line| line == "FOO=bar" || line == "ABC=xyz")
.count(),
2
@ -110,13 +100,8 @@ fn test_multiple_name_value_pairs() {
fn test_ignore_environment() {
let scene = TestScenario::new(util_name!());
let out = scene.ucmd().arg("-i").run().stdout;
assert_eq!(out, "");
let out = scene.ucmd().arg("-").run().stdout;
assert_eq!(out, "");
scene.ucmd().arg("-i").run().no_stdout();
scene.ucmd().arg("-").run().no_stdout();
}
#[test]
@ -126,8 +111,8 @@ fn test_null_delimiter() {
.arg("--null")
.arg("FOO=bar")
.arg("ABC=xyz")
.run()
.stdout;
.succeeds()
.stdout_move_str();
let mut vars: Vec<_> = out.split('\0').collect();
assert_eq!(vars.len(), 3);
@ -145,8 +130,8 @@ fn test_unset_variable() {
.ucmd_keepenv()
.arg("-u")
.arg("HOME")
.run()
.stdout;
.succeeds()
.stdout_move_str();
assert_eq!(out.lines().any(|line| line.starts_with("HOME=")), false);
}
@ -173,8 +158,8 @@ fn test_change_directory() {
.arg("--chdir")
.arg(&temporary_path)
.arg(pwd)
.run()
.stdout;
.succeeds()
.stdout_move_str();
assert_eq!(out.trim(), temporary_path.as_os_str())
}
@ -193,8 +178,8 @@ fn test_change_directory() {
.ucmd()
.arg("--chdir")
.arg(&temporary_path)
.run()
.stdout;
.succeeds()
.stdout_move_str();
assert_eq!(
out.lines()
.any(|line| line.ends_with(temporary_path.file_name().unwrap().to_str().unwrap())),
@ -214,6 +199,6 @@ fn test_fail_change_directory() {
.arg(some_non_existing_path)
.arg("pwd")
.fails()
.stderr;
.stderr_move_str();
assert!(out.contains("env: cannot change directory to "));
}

View file

@ -2,57 +2,54 @@ use crate::common::util::*;
#[test]
fn test_with_tab() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("with-tab.txt").run();
assert!(result.success);
assert!(result.stdout.contains(" "));
assert!(!result.stdout.contains("\t"));
new_ucmd!()
.arg("with-tab.txt")
.succeeds()
.stdout_contains(" ")
.stdout_does_not_contain("\t");
}
#[test]
fn test_with_trailing_tab() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("with-trailing-tab.txt").run();
assert!(result.success);
assert!(result.stdout.contains("with tabs=> "));
assert!(!result.stdout.contains("\t"));
new_ucmd!()
.arg("with-trailing-tab.txt")
.succeeds()
.stdout_contains("with tabs=> ")
.stdout_does_not_contain("\t");
}
#[test]
fn test_with_trailing_tab_i() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("with-trailing-tab.txt").arg("-i").run();
assert!(result.success);
assert!(result.stdout.contains(" // with tabs=>\t"));
new_ucmd!()
.arg("with-trailing-tab.txt")
.arg("-i")
.succeeds()
.stdout_contains(" // with tabs=>\t");
}
#[test]
fn test_with_tab_size() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("with-tab.txt").arg("--tabs=10").run();
assert!(result.success);
assert!(result.stdout.contains(" "));
new_ucmd!()
.arg("with-tab.txt")
.arg("--tabs=10")
.succeeds()
.stdout_contains(" ");
}
#[test]
fn test_with_space() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("with-spaces.txt").run();
assert!(result.success);
assert!(result.stdout.contains(" return"));
new_ucmd!()
.arg("with-spaces.txt")
.succeeds()
.stdout_contains(" return");
}
#[test]
fn test_with_multiple_files() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("with-spaces.txt").arg("with-tab.txt").run();
assert!(result.success);
assert!(result.stdout.contains(" return"));
assert!(result.stdout.contains(" "));
new_ucmd!()
.arg("with-spaces.txt")
.arg("with-tab.txt")
.succeeds()
.stdout_contains(" return")
.stdout_contains(" ");
}

View file

@ -32,13 +32,10 @@ fn test_first_100000_integers() {
}
println!("STDIN='{}'", instring);
let result = new_ucmd!().pipe_in(instring.as_bytes()).run();
let stdout = result.stdout;
assert!(result.success);
let result = new_ucmd!().pipe_in(instring.as_bytes()).succeeds();
// `seq 0 100000 | factor | sha1sum` => "4ed2d8403934fa1c76fe4b84c5d4b8850299c359"
let hash_check = sha1::Sha1::from(stdout.as_bytes()).hexdigest();
let hash_check = sha1::Sha1::from(result.stdout()).hexdigest();
assert_eq!(hash_check, "4ed2d8403934fa1c76fe4b84c5d4b8850299c359");
}

View file

@ -5,7 +5,7 @@ fn test_fmt() {
let result = new_ucmd!().arg("one-word-per-line.txt").run();
//.stdout_is_fixture("call_graph.expected");
assert_eq!(
result.stdout.trim(),
result.stdout_str().trim(),
"this is a file with one word per line"
);
}
@ -15,7 +15,7 @@ fn test_fmt_q() {
let result = new_ucmd!().arg("-q").arg("one-word-per-line.txt").run();
//.stdout_is_fixture("call_graph.expected");
assert_eq!(
result.stdout.trim(),
result.stdout_str().trim(),
"this is a file with one word per line"
);
}
@ -42,7 +42,7 @@ fn test_fmt_w() {
.arg("one-word-per-line.txt")
.run();
//.stdout_is_fixture("call_graph.expected");
assert_eq!(result.stdout.trim(), "this is a file with one word per line");
assert_eq!(result.stdout_str().trim(), "this is a file with one word per line");
}

View file

@ -2,26 +2,25 @@ use crate::common::util::*;
#[test]
fn test_groups() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
if is_ci() && result.stdout.trim().is_empty() {
let result = new_ucmd!().run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stdout_str().trim().is_empty() {
// In the CI, some server are failing to return the group.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
assert!(!result.stdout.trim().is_empty());
assert!(!result.stdout_str().trim().is_empty());
}
#[test]
fn test_groups_arg() {
// get the username with the "id -un" command
let result = TestScenario::new("id").ucmd_keepenv().arg("-un").run();
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
let s1 = String::from(result.stdout.trim());
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let s1 = String::from(result.stdout_str().trim());
if is_ci() && s1.parse::<f64>().is_ok() {
// In the CI, some server are failing to return id -un.
// So, if we are getting a uid, just skip this test
@ -29,18 +28,18 @@ fn test_groups_arg() {
return;
}
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
assert!(result.success);
assert!(!result.stdout.is_empty());
let username = result.stdout.trim();
assert!(!result.stdout_str().is_empty());
let username = result.stdout_str().trim();
// call groups with the user name to check that we
// are getting something
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg(username).run();
println!("result.stdout {}", result.stdout);
println!("result.stderr = {}", result.stderr);
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
assert!(result.success);
assert!(!result.stdout.is_empty());
assert!(!result.stdout_str().is_empty());
}

View file

@ -17,14 +17,14 @@ macro_rules! test_digest {
fn test_single_file() {
let ts = TestScenario::new("hashsum");
assert_eq!(ts.fixtures.read(EXPECTED_FILE),
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).arg("input.txt").succeeds().no_stderr().stdout));
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).arg("input.txt").succeeds().no_stderr().stdout_str()));
}
#[test]
fn test_stdin() {
let ts = TestScenario::new("hashsum");
assert_eq!(ts.fixtures.read(EXPECTED_FILE),
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).pipe_in_fixture("input.txt").succeeds().no_stderr().stdout));
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).pipe_in_fixture("input.txt").succeeds().no_stderr().stdout_str()));
}
}
)*)

View file

@ -9,5 +9,5 @@ fn test_normal() {
assert!(result.success);
let re = Regex::new(r"^[0-9a-f]{8}").unwrap();
assert!(re.is_match(&result.stdout.trim()));
assert!(re.is_match(&result.stdout_str()));
}

View file

@ -6,8 +6,8 @@ fn test_hostname() {
let ls_short_res = new_ucmd!().arg("-s").succeeds();
let ls_domain_res = new_ucmd!().arg("-d").succeeds();
assert!(ls_default_res.stdout.len() >= ls_short_res.stdout.len());
assert!(ls_default_res.stdout.len() >= ls_domain_res.stdout.len());
assert!(ls_default_res.stdout().len() >= ls_short_res.stdout().len());
assert!(ls_default_res.stdout().len() >= ls_domain_res.stdout().len());
}
// FixME: fails for "MacOS"
@ -17,14 +17,14 @@ fn test_hostname_ip() {
let result = new_ucmd!().arg("-i").run();
println!("{:#?}", result);
assert!(result.success);
assert!(!result.stdout.trim().is_empty());
assert!(!result.stdout_str().trim().is_empty());
}
#[test]
fn test_hostname_full() {
let result = new_ucmd!().arg("-f").succeeds();
assert!(!result.stdout.trim().is_empty());
let ls_short_res = new_ucmd!().arg("-s").succeeds();
assert!(result.stdout.trim().contains(ls_short_res.stdout.trim()));
assert!(!ls_short_res.stdout_str().trim().is_empty());
new_ucmd!().arg("-f").succeeds()
.stdout_contains(ls_short_res.stdout_str().trim());
}

View file

@ -9,33 +9,29 @@ fn return_whoami_username() -> String {
return String::from("");
}
result.stdout.trim().to_string()
result.stdout_str().trim().to_string()
}
#[test]
fn test_id() {
let scene = TestScenario::new(util_name!());
let mut result = scene.ucmd().arg("-u").run();
let result = new_ucmd!().arg("-u").run();
if result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
let uid = String::from(result.stdout.trim());
result = scene.ucmd().run();
let uid = result.success().stdout_str().trim();
let result = new_ucmd!().run();
if is_ci() && result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return;
}
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
if !result.stderr.contains("Could not find uid") {
if !result.stderr_str().contains("Could not find uid") {
// Verify that the id found by --user/-u exists in the list
assert!(result.stdout.contains(&uid));
result.success().stdout_contains(&uid);
}
}
@ -47,88 +43,64 @@ fn test_id_from_name() {
return;
}
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg(&username).succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
let uid = String::from(result.stdout.trim());
let result = scene.ucmd().succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
let result = new_ucmd!().arg(&username).succeeds();
let uid = result.stdout_str().trim();
new_ucmd!().succeeds()
// Verify that the id found by --user/-u exists in the list
assert!(result.stdout.contains(&uid));
.stdout_contains(uid)
// Verify that the username found by whoami exists in the list
assert!(result.stdout.contains(&username));
.stdout_contains(username);
}
#[test]
fn test_id_name_from_id() {
let mut scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-u").run();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
let uid = String::from(result.stdout.trim());
let result = new_ucmd!().arg("-u").succeeds();
let uid = result.stdout_str().trim();
scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-nu").arg(uid).run();
let result = new_ucmd!().arg("-nu").arg(uid).run();
if is_ci() && result.stderr.contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return;
}
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
let username_id = String::from(result.stdout.trim());
let username_id = result
.success()
.stdout_str()
.trim();
scene = TestScenario::new("whoami");
let result = scene.cmd("whoami").run();
let scene = TestScenario::new("whoami");
let result = scene.cmd("whoami").succeeds();
let username_whoami = result.stdout.trim();
let username_whoami = result.stdout_str().trim();
assert_eq!(username_id, username_whoami);
}
#[test]
fn test_id_group() {
let scene = TestScenario::new(util_name!());
let mut result = scene.ucmd().arg("-g").succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
let s1 = String::from(result.stdout.trim());
let mut result = new_ucmd!().arg("-g").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
result = scene.ucmd().arg("--group").succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
let s1 = String::from(result.stdout.trim());
result = new_ucmd!().arg("--group").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
}
#[test]
fn test_id_groups() {
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-G").succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
let result = new_ucmd!().arg("-G").succeeds();
assert!(result.success);
let groups = result.stdout.trim().split_whitespace();
let groups = result.stdout_str().trim().split_whitespace();
for s in groups {
assert!(s.parse::<f64>().is_ok());
}
let result = scene.ucmd().arg("--groups").succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
let result = new_ucmd!().arg("--groups").succeeds();
assert!(result.success);
let groups = result.stdout.trim().split_whitespace();
let groups = result.stdout_str().trim().split_whitespace();
for s in groups {
assert!(s.parse::<f64>().is_ok());
}
@ -136,15 +108,12 @@ fn test_id_groups() {
#[test]
fn test_id_user() {
let scene = TestScenario::new(util_name!());
let mut result = scene.ucmd().arg("-u").succeeds();
assert!(result.success);
let s1 = String::from(result.stdout.trim());
let mut result = new_ucmd!().arg("-u").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
result = scene.ucmd().arg("--user").succeeds();
assert!(result.success);
let s1 = String::from(result.stdout.trim());
result = new_ucmd!().arg("--user").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
}
@ -156,17 +125,13 @@ fn test_id_pretty_print() {
return;
}
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-p").run();
if result.stdout.trim() == "" {
let result = new_ucmd!().arg("-p").run();
if result.stdout_str().trim() == "" {
// Sometimes, the CI is failing here with
// old rust versions on Linux
return;
}
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
assert!(result.stdout.contains(&username));
result.success().stdout_contains(username);
}
#[test]
@ -176,12 +141,7 @@ fn test_id_password_style() {
// Sometimes, the CI is failing here
return;
}
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-P").succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
assert!(result.stdout.starts_with(&username));
let result = new_ucmd!().arg("-P").succeeds();
assert!(result.stdout_str().starts_with(&username));
}

View file

@ -195,12 +195,8 @@ fn test_install_mode_numeric() {
let mode_arg = "-m 0333";
at.mkdir(dir2);
let result = scene.ucmd().arg(mode_arg).arg(file).arg(dir2).run();
scene.ucmd().arg(mode_arg).arg(file).arg(dir2).succeeds();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
assert!(result.success);
let dest_file = &format!("{}/{}", dir2, file);
assert!(at.file_exists(file));
assert!(at.file_exists(dest_file));
@ -313,16 +309,13 @@ fn test_install_target_new_file_with_group() {
.arg(format!("{}/{}", dir, file))
.run();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
if is_ci() && result.stderr.contains("error: no such group:") {
if is_ci() && result.stderr_str().contains("error: no such group:") {
// In the CI, some server are failing to return the group.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
result.success();
assert!(at.file_exists(file));
assert!(at.file_exists(&format!("{}/{}", dir, file)));
}
@ -343,16 +336,13 @@ fn test_install_target_new_file_with_owner() {
.arg(format!("{}/{}", dir, file))
.run();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
if is_ci() && result.stderr.contains("error: no such user:") {
// In the CI, some server are failing to return the user id.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
result.success();
assert!(at.file_exists(file));
assert!(at.file_exists(&format!("{}/{}", dir, file)));
}
@ -366,13 +356,10 @@ fn test_install_target_new_file_failing_nonexistent_parent() {
at.touch(file1);
let err = ucmd
.arg(file1)
ucmd.arg(file1)
.arg(format!("{}/{}", dir, file2))
.fails()
.stderr;
assert!(err.contains("not a directory"))
.stderr_contains(&"not a directory");
}
#[test]
@ -417,18 +404,12 @@ fn test_install_copy_file() {
#[test]
#[cfg(target_os = "linux")]
fn test_install_target_file_dev_null() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "/dev/null";
let file2 = "target_file";
let result = scene.ucmd().arg(file1).arg(file2).run();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
assert!(result.success);
ucmd.arg(file1).arg(file2).succeeds();
assert!(at.file_exists(file2));
}

View file

@ -520,10 +520,7 @@ fn test_symlink_no_deref_dir() {
scene.ucmd().args(&["-sn", dir1, link]).fails();
// Try with the no-deref
let result = scene.ucmd().args(&["-sfn", dir1, link]).run();
println!("stdout {}", result.stdout);
println!("stderr {}", result.stderr);
assert!(result.success);
scene.ucmd().args(&["-sfn", dir1, link]).succeeds();
assert!(at.dir_exists(dir1));
assert!(at.dir_exists(dir2));
assert!(at.is_symlink(link));
@ -566,10 +563,7 @@ fn test_symlink_no_deref_file() {
scene.ucmd().args(&["-sn", file1, link]).fails();
// Try with the no-deref
let result = scene.ucmd().args(&["-sfn", file1, link]).run();
println!("stdout {}", result.stdout);
println!("stderr {}", result.stderr);
assert!(result.success);
scene.ucmd().args(&["-sfn", file1, link]).succeeds();
assert!(at.file_exists(file1));
assert!(at.file_exists(file2));
assert!(at.is_symlink(link));

View file

@ -3,23 +3,19 @@ use std::env;
#[test]
fn test_normal() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
let result = new_ucmd!().run();
println!("env::var(CI).is_ok() = {}", env::var("CI").is_ok());
for (key, value) in env::vars() {
println!("{}: {}", key, value);
}
if (is_ci() || is_wsl()) && result.stderr.contains("error: no login name") {
if (is_ci() || is_wsl()) && result.stderr_str().contains("error: no login name") {
// ToDO: investigate WSL failure
// In the CI, some server are failing to return logname.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
assert!(!result.stdout.trim().is_empty());
result.success();
assert!(!result.stdout_str().trim().is_empty());
}

View file

@ -8,6 +8,25 @@ fn test_helper(file_name: &str, args: &str) {
.stdout_is_fixture(format!("{}.expected", file_name));
}
#[test]
fn test_months_whitespace() {
test_helper("months-whitespace", "-M");
}
#[test]
fn test_version_empty_lines() {
new_ucmd!()
.arg("-V")
.arg("version-empty-lines.txt")
.succeeds()
.stdout_is("\n\n\n\n\n\n\n1.2.3-alpha\n1.2.3-alpha2\n\t\t\t1.12.4\n11.2.3\n");
}
#[test]
fn test_human_numeric_whitespace() {
test_helper("human-numeric-whitespace", "-h");
}
#[test]
fn test_multiple_decimals_general() {
new_ucmd!()

View file

@ -25,11 +25,7 @@ fn test_stdbuf_line_buffered_stdout() {
#[cfg(not(target_os = "windows"))]
#[test]
fn test_stdbuf_no_buffer_option_fails() {
new_ucmd!()
.args(&["head"])
.pipe_in("The quick brown fox jumps over the lazy dog.")
.fails()
.stderr_is(
new_ucmd!().args(&["head"]).fails().stderr_is(
"error: The following required arguments were not provided:\n \
--error <MODE>\n \
--input <MODE>\n \
@ -55,7 +51,6 @@ fn test_stdbuf_trailing_var_arg() {
fn test_stdbuf_line_buffering_stdin_fails() {
new_ucmd!()
.args(&["-i", "L", "head"])
.pipe_in("The quick brown fox jumps over the lazy dog.")
.fails()
.stderr_is("stdbuf: error: line buffering stdin is meaningless\nTry 'stdbuf --help' for more information.");
}
@ -65,7 +60,6 @@ fn test_stdbuf_line_buffering_stdin_fails() {
fn test_stdbuf_invalid_mode_fails() {
new_ucmd!()
.args(&["-i", "1024R", "head"])
.pipe_in("The quick brown fox jumps over the lazy dog.")
.fails()
.stderr_is("stdbuf: error: invalid mode 1024R\nTry 'stdbuf --help' for more information.");
}

View file

@ -29,6 +29,7 @@ fn set_file_times(at: &AtPath, path: &str, atime: FileTime, mtime: FileTime) {
fn str_to_filetime(format: &str, s: &str) -> FileTime {
let mut tm = time::strptime(s, format).unwrap();
tm.tm_utcoff = time::now().tm_utcoff;
tm.tm_isdst = -1; // Unknown flag DST
let ts = tm.to_timespec();
FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32)
}
@ -352,3 +353,21 @@ fn test_touch_set_date() {
assert_eq!(atime, start_of_year);
assert_eq!(mtime, start_of_year);
}
#[test]
fn test_touch_mtime_dst_succeeds() {
let (at, mut ucmd) = at_and_ucmd!();
let file = "test_touch_set_mtime_dst_succeeds";
ucmd.args(&["-m", "-t", "202103140300", file])
.succeeds()
.no_stderr();
assert!(at.file_exists(file));
let target_time = str_to_filetime("%Y%m%d%H%M", "202103140300");
let (_, mtime) = get_file_times(&at, file);
eprintln!("target_time: {:?}", target_time);
eprintln!("mtime: {:?}", mtime);
assert!(target_time == mtime);
}

View file

@ -33,6 +33,8 @@ static ALREADY_RUN: &str = " you have already run this UCommand, if you want to
testing();";
static MULTIPLE_STDIN_MEANINGLESS: &str = "Ucommand is designed around a typical use case of: provide args and input stream -> spawn process -> block until completion -> return output streams. For verifying that a particular section of the input stream is what causes a particular behavior, use the Command type directly.";
static NO_STDIN_MEANINGLESS: &str = "Setting this flag has no effect if there is no stdin";
/// Test if the program is running under CI
pub fn is_ci() -> bool {
std::env::var("CI")
@ -688,6 +690,7 @@ pub struct UCommand {
tmpd: Option<Rc<TempDir>>,
has_run: bool,
stdin: Option<Vec<u8>>,
ignore_stdin_write_error: bool,
}
impl UCommand {
@ -717,6 +720,7 @@ impl UCommand {
},
comm_string: String::from(arg.as_ref().to_str().unwrap()),
stdin: None,
ignore_stdin_write_error: false,
}
}
@ -769,6 +773,17 @@ impl UCommand {
self.pipe_in(contents)
}
/// Ignores error caused by feeding stdin to the command.
/// This is typically useful to test non-standard workflows
/// like feeding something to a command that does not read it
pub fn ignore_stdin_write_error(&mut self) -> &mut UCommand {
if self.stdin.is_none() {
panic!("{}", NO_STDIN_MEANINGLESS);
}
self.ignore_stdin_write_error = true;
self
}
pub fn env<K, V>(&mut self, key: K, val: V) -> &mut UCommand
where
K: AsRef<OsStr>,
@ -789,7 +804,7 @@ impl UCommand {
}
self.has_run = true;
log_info("run", &self.comm_string);
let mut result = self
let mut child = self
.raw
.stdin(Stdio::piped())
.stdout(Stdio::piped())
@ -798,15 +813,19 @@ impl UCommand {
.unwrap();
if let Some(ref input) = self.stdin {
result
let write_result = child
.stdin
.take()
.unwrap_or_else(|| panic!("Could not take child process stdin"))
.write_all(input)
.unwrap_or_else(|e| panic!("{}", e));
.write_all(input);
if !self.ignore_stdin_write_error {
if let Err(e) = write_result {
panic!("failed to write to stdin of child: {}", e)
}
}
}
result
child
}
/// Spawns the command, feeds the stdin if any, waits for the result

View file

@ -0,0 +1,11 @@
456K
4568K
456M
6.2G

View file

@ -0,0 +1,11 @@
456K
456M
4568K
6.2G

View file

@ -0,0 +1,8 @@
JAN
FEb
apr
apr
JUNNNN
AUG

View file

@ -0,0 +1,8 @@
JAN
JUNNNN
AUG
apr
apr
FEb

View file

@ -0,0 +1,11 @@
1.2.3-alpha
1.2.3-alpha2
11.2.3
1.12.4

View file

@ -0,0 +1,11 @@
11.2.3
1.2.3-alpha2
1.2.3-alpha
1.12.4