mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
Merge branch 'master' into ls/dereference-command-line
This commit is contained in:
@@ -22,6 +22,7 @@ search the issues to make sure no one else is working on it.
|
||||
1. Make sure that the code coverage is covering all of the cases, including errors.
|
||||
1. The code must be clippy-warning-free and rustfmt-compliant.
|
||||
1. Don't hesitate to move common functions into uucore if they can be reused by other binaries.
|
||||
1. Unsafe code should be documented with Safety comments.
|
||||
|
||||
## Commit messages
|
||||
|
||||
|
||||
Generated
+15
-7
@@ -1362,6 +1362,12 @@ dependencies = [
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
@@ -1388,9 +1394,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.68"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
|
||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
@@ -1610,7 +1616,8 @@ name = "uu_cat"
|
||||
version = "0.0.6"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"quick-error",
|
||||
"nix 0.20.0",
|
||||
"thiserror",
|
||||
"unix_socket",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
@@ -1816,7 +1823,7 @@ dependencies = [
|
||||
"quickcheck",
|
||||
"rand 0.7.3",
|
||||
"rand_chacha",
|
||||
"smallvec",
|
||||
"smallvec 0.6.14",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
]
|
||||
@@ -2285,10 +2292,11 @@ version = "0.0.6"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"fnv",
|
||||
"itertools 0.8.2",
|
||||
"itertools 0.10.0",
|
||||
"rand 0.7.3",
|
||||
"rayon",
|
||||
"semver",
|
||||
"smallvec 1.6.1",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
]
|
||||
@@ -2316,7 +2324,7 @@ dependencies = [
|
||||
name = "uu_stdbuf"
|
||||
version = "0.0.6"
|
||||
dependencies = [
|
||||
"getopts",
|
||||
"clap",
|
||||
"tempfile",
|
||||
"uu_stdbuf_libstdbuf",
|
||||
"uucore",
|
||||
@@ -2500,7 +2508,7 @@ dependencies = [
|
||||
name = "uu_unlink"
|
||||
version = "0.0.6"
|
||||
dependencies = [
|
||||
"getopts",
|
||||
"clap",
|
||||
"libc",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -16,13 +16,16 @@ path = "src/cat.rs"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
quick-error = "1.2.3"
|
||||
thiserror = "1.0"
|
||||
uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
unix_socket = "0.5.0"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
||||
nix = "0.20"
|
||||
|
||||
[[bin]]
|
||||
name = "cat"
|
||||
path = "src/main.rs"
|
||||
|
||||
+246
-172
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+16
-14
@@ -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(()),
|
||||
|
||||
+31
-35
@@ -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;
|
||||
}
|
||||
@@ -487,7 +487,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
.help("filter field columns from the input source")
|
||||
.takes_value(true)
|
||||
.allow_hyphen_values(true)
|
||||
.value_name("LIST")
|
||||
.value_name("LIST")
|
||||
.display_order(4),
|
||||
)
|
||||
.arg(
|
||||
@@ -535,40 +535,36 @@ 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| {
|
||||
Mode::Bytes(
|
||||
ranges,
|
||||
Options {
|
||||
out_delim: Some(
|
||||
matches
|
||||
.value_of(options::OUTPUT_DELIMITER)
|
||||
.unwrap_or_default()
|
||||
.to_owned(),
|
||||
),
|
||||
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
(None, Some(char_ranges), None) => {
|
||||
list_to_ranges(&char_ranges[..], complement).map(|ranges| {
|
||||
Mode::Characters(
|
||||
ranges,
|
||||
Options {
|
||||
out_delim: Some(
|
||||
matches
|
||||
.value_of(options::OUTPUT_DELIMITER)
|
||||
.unwrap_or_default()
|
||||
.to_owned(),
|
||||
),
|
||||
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
(Some(byte_ranges), None, None) => list_to_ranges(byte_ranges, complement).map(|ranges| {
|
||||
Mode::Bytes(
|
||||
ranges,
|
||||
Options {
|
||||
out_delim: Some(
|
||||
matches
|
||||
.value_of(options::OUTPUT_DELIMITER)
|
||||
.unwrap_or_default()
|
||||
.to_owned(),
|
||||
),
|
||||
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
|
||||
},
|
||||
)
|
||||
}),
|
||||
(None, Some(char_ranges), None) => list_to_ranges(char_ranges, complement).map(|ranges| {
|
||||
Mode::Characters(
|
||||
ranges,
|
||||
Options {
|
||||
out_delim: Some(
|
||||
matches
|
||||
.value_of(options::OUTPUT_DELIMITER)
|
||||
.unwrap_or_default()
|
||||
.to_owned(),
|
||||
),
|
||||
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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+17
-3
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,9 +23,11 @@ use std::fs;
|
||||
use std::fs::File;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::result::Result;
|
||||
|
||||
const DEFAULT_MODE: u32 = 0o755;
|
||||
const DEFAULT_STRIP_PROGRAM: &str = "strip";
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Behavior {
|
||||
@@ -37,6 +39,8 @@ pub struct Behavior {
|
||||
verbose: bool,
|
||||
preserve_timestamps: bool,
|
||||
compare: bool,
|
||||
strip: bool,
|
||||
strip_program: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
@@ -164,17 +168,15 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
.help("apply access/modification times of SOURCE files to corresponding destination files")
|
||||
)
|
||||
.arg(
|
||||
// TODO implement flag
|
||||
Arg::with_name(OPT_STRIP)
|
||||
.short("s")
|
||||
.long(OPT_STRIP)
|
||||
.help("(unimplemented) strip symbol tables")
|
||||
.help("strip symbol tables (no action Windows)")
|
||||
)
|
||||
.arg(
|
||||
// TODO implement flag
|
||||
Arg::with_name(OPT_STRIP_PROGRAM)
|
||||
.long(OPT_STRIP_PROGRAM)
|
||||
.help("(unimplemented) program used to strip binaries")
|
||||
.help("program used to strip binaries (no action Windows)")
|
||||
.value_name("PROGRAM")
|
||||
)
|
||||
.arg(
|
||||
@@ -266,10 +268,6 @@ fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
|
||||
Err("-b")
|
||||
} else if matches.is_present(OPT_CREATED) {
|
||||
Err("-D")
|
||||
} else if matches.is_present(OPT_STRIP) {
|
||||
Err("--strip, -s")
|
||||
} else if matches.is_present(OPT_STRIP_PROGRAM) {
|
||||
Err("--strip-program")
|
||||
} else if matches.is_present(OPT_SUFFIX) {
|
||||
Err("--suffix, -S")
|
||||
} else if matches.is_present(OPT_TARGET_DIRECTORY) {
|
||||
@@ -304,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);
|
||||
@@ -339,6 +337,12 @@ fn behavior(matches: &ArgMatches) -> Result<Behavior, i32> {
|
||||
verbose: matches.is_present(OPT_VERBOSE),
|
||||
preserve_timestamps: matches.is_present(OPT_PRESERVE_TIMESTAMPS),
|
||||
compare: matches.is_present(OPT_COMPARE),
|
||||
strip: matches.is_present(OPT_STRIP),
|
||||
strip_program: String::from(
|
||||
matches
|
||||
.value_of(OPT_STRIP_PROGRAM)
|
||||
.unwrap_or(DEFAULT_STRIP_PROGRAM),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -425,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;
|
||||
@@ -449,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);
|
||||
|
||||
@@ -474,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 {
|
||||
@@ -493,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(());
|
||||
}
|
||||
@@ -521,6 +525,21 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if b.strip && cfg!(not(windows)) {
|
||||
match Command::new(&b.strip_program).arg(to).output() {
|
||||
Ok(o) => {
|
||||
if !o.status.success() {
|
||||
crash!(
|
||||
1,
|
||||
"strip program failed: {}",
|
||||
String::from_utf8(o.stderr).unwrap_or_default()
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => crash!(1, "strip program execution failed: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
if mode::chmod(&to, b.mode()).is_err() {
|
||||
return Err(());
|
||||
}
|
||||
@@ -537,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),
|
||||
@@ -563,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);
|
||||
@@ -582,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),
|
||||
}
|
||||
@@ -611,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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user