mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
parent
704421bd6b
commit
5d6a04ab71
21 changed files with 106 additions and 169 deletions
|
@ -576,6 +576,7 @@ semicolon_if_nothing_returned = "warn"
|
||||||
single_char_pattern = "warn"
|
single_char_pattern = "warn"
|
||||||
explicit_iter_loop = "warn"
|
explicit_iter_loop = "warn"
|
||||||
if_not_else = "warn"
|
if_not_else = "warn"
|
||||||
|
manual_if_else = "warn"
|
||||||
|
|
||||||
all = { level = "deny", priority = -1 }
|
all = { level = "deny", priority = -1 }
|
||||||
cargo = { level = "warn", priority = -1 }
|
cargo = { level = "warn", priority = -1 }
|
||||||
|
|
|
@ -125,16 +125,13 @@ fn basename(fullname: &str, suffix: &str) -> String {
|
||||||
|
|
||||||
// Convert to path buffer and get last path component
|
// Convert to path buffer and get last path component
|
||||||
let pb = PathBuf::from(path);
|
let pb = PathBuf::from(path);
|
||||||
match pb.components().last() {
|
|
||||||
Some(c) => {
|
pb.components().next_back().map_or_else(String::new, |c| {
|
||||||
let name = c.as_os_str().to_str().unwrap();
|
let name = c.as_os_str().to_str().unwrap();
|
||||||
if name == suffix {
|
if name == suffix {
|
||||||
name.to_string()
|
name.to_string()
|
||||||
} else {
|
} else {
|
||||||
name.strip_suffix(suffix).unwrap_or(name).to_string()
|
name.strip_suffix(suffix).unwrap_or(name).to_string()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
None => String::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ fn is_over_mounted(mounts: &[MountInfo], mount: &MountInfo) -> bool {
|
||||||
let last_mount_for_dir = mounts
|
let last_mount_for_dir = mounts
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| m.mount_dir == mount.mount_dir)
|
.filter(|m| m.mount_dir == mount.mount_dir)
|
||||||
.last();
|
.next_back();
|
||||||
|
|
||||||
if let Some(lmi) = last_mount_for_dir {
|
if let Some(lmi) = last_mount_for_dir {
|
||||||
lmi.dev_name != mount.dev_name
|
lmi.dev_name != mount.dev_name
|
||||||
|
|
7
src/uu/env/src/env.rs
vendored
7
src/uu/env/src/env.rs
vendored
|
@ -130,14 +130,11 @@ fn parse_signal_opt<'a>(opts: &mut Options<'a>, opt: &'a OsStr) -> UResult<()> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for sig in sig_vec {
|
for sig in sig_vec {
|
||||||
let sig_str = match sig.to_str() {
|
let Some(sig_str) = sig.to_str() else {
|
||||||
Some(s) => s,
|
|
||||||
None => {
|
|
||||||
return Err(USimpleError::new(
|
return Err(USimpleError::new(
|
||||||
1,
|
1,
|
||||||
format!("{}: invalid signal", sig.quote()),
|
format!("{}: invalid signal", sig.quote()),
|
||||||
))
|
));
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let sig_val = parse_signal_value(sig_str)?;
|
let sig_val = parse_signal_value(sig_str)?;
|
||||||
if !opts.ignore_signal.contains(&sig_val) {
|
if !opts.ignore_signal.contains(&sig_val) {
|
||||||
|
|
|
@ -255,9 +255,8 @@ impl ParagraphStream<'_> {
|
||||||
if l_slice.starts_with("From ") {
|
if l_slice.starts_with("From ") {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
let colon_posn = match l_slice.find(':') {
|
let Some(colon_posn) = l_slice.find(':') else {
|
||||||
Some(n) => n,
|
return false;
|
||||||
None => return false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// header field must be nonzero length
|
// header field must be nonzero length
|
||||||
|
@ -560,12 +559,11 @@ impl<'a> Iterator for WordSplit<'a> {
|
||||||
|
|
||||||
// find the start of the next word, and record if we find a tab character
|
// find the start of the next word, and record if we find a tab character
|
||||||
let (before_tab, after_tab, word_start) =
|
let (before_tab, after_tab, word_start) =
|
||||||
match self.analyze_tabs(&self.string[old_position..]) {
|
if let (b, a, Some(s)) = self.analyze_tabs(&self.string[old_position..]) {
|
||||||
(b, a, Some(s)) => (b, a, s + old_position),
|
(b, a, s + old_position)
|
||||||
(_, _, None) => {
|
} else {
|
||||||
self.position = self.length;
|
self.position = self.length;
|
||||||
return None;
|
return None;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// find the beginning of the next whitespace
|
// find the beginning of the next whitespace
|
||||||
|
|
|
@ -91,9 +91,8 @@ fn process_num_block(
|
||||||
}
|
}
|
||||||
if let Some(n) = multiplier {
|
if let Some(n) = multiplier {
|
||||||
options.push(OsString::from("-c"));
|
options.push(OsString::from("-c"));
|
||||||
let num = match num.checked_mul(n) {
|
let Some(num) = num.checked_mul(n) else {
|
||||||
Some(n) => n,
|
return Some(Err(ParseError::Overflow));
|
||||||
None => return Some(Err(ParseError::Overflow)),
|
|
||||||
};
|
};
|
||||||
options.push(OsString::from(format!("{num}")));
|
options.push(OsString::from(format!("{num}")));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -652,7 +652,7 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> UR
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut targetpath = target_dir.to_path_buf();
|
let mut targetpath = target_dir.to_path_buf();
|
||||||
let filename = sourcepath.components().last().unwrap();
|
let filename = sourcepath.components().next_back().unwrap();
|
||||||
targetpath.push(filename);
|
targetpath.push(filename);
|
||||||
|
|
||||||
show_if_err!(copy(sourcepath, &targetpath, b));
|
show_if_err!(copy(sourcepath, &targetpath, b));
|
||||||
|
|
|
@ -379,8 +379,8 @@ fn parse_time_style(options: &clap::ArgMatches) -> Result<TimeStyle, LsError> {
|
||||||
//If both FULL_TIME and TIME_STYLE are present
|
//If both FULL_TIME and TIME_STYLE are present
|
||||||
//The one added last is dominant
|
//The one added last is dominant
|
||||||
if options.get_flag(options::FULL_TIME)
|
if options.get_flag(options::FULL_TIME)
|
||||||
&& options.indices_of(options::FULL_TIME).unwrap().last()
|
&& options.indices_of(options::FULL_TIME).unwrap().next_back()
|
||||||
> options.indices_of(options::TIME_STYLE).unwrap().last()
|
> options.indices_of(options::TIME_STYLE).unwrap().next_back()
|
||||||
{
|
{
|
||||||
Ok(TimeStyle::FullIso)
|
Ok(TimeStyle::FullIso)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -101,8 +101,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let options = SeqOptions {
|
let options = SeqOptions {
|
||||||
separator: matches
|
separator: matches
|
||||||
.get_one::<String>(OPT_SEPARATOR)
|
.get_one::<String>(OPT_SEPARATOR)
|
||||||
.map(|s| s.as_str())
|
.map_or("\n", |s| s.as_str())
|
||||||
.unwrap_or("\n")
|
|
||||||
.to_string(),
|
.to_string(),
|
||||||
terminator: matches
|
terminator: matches
|
||||||
.get_one::<String>(OPT_TERMINATOR)
|
.get_one::<String>(OPT_TERMINATOR)
|
||||||
|
@ -150,13 +149,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
|
||||||
let precision = select_precision(first_precision, increment_precision, last_precision);
|
let precision = select_precision(first_precision, increment_precision, last_precision);
|
||||||
|
|
||||||
let format = match options.format {
|
let format = options
|
||||||
Some(f) => {
|
.format
|
||||||
let f = Format::<num_format::Float>::parse(f)?;
|
.map(Format::<num_format::Float>::parse)
|
||||||
Some(f)
|
.transpose()?;
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
let result = print_seq(
|
let result = print_seq(
|
||||||
(first.number, increment.number, last.number),
|
(first.number, increment.number, last.number),
|
||||||
precision,
|
precision,
|
||||||
|
@ -164,12 +161,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
&options.terminator,
|
&options.terminator,
|
||||||
options.equal_width,
|
options.equal_width,
|
||||||
padding,
|
padding,
|
||||||
&format,
|
format.as_ref(),
|
||||||
);
|
);
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
Err(err) if err.kind() == ErrorKind::BrokenPipe => Ok(()),
|
Err(err) if err.kind() == ErrorKind::BrokenPipe => Ok(()),
|
||||||
Err(e) => Err(e.map_err_context(|| "write error".into())),
|
Err(err) => Err(err.map_err_context(|| "write error".into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +260,7 @@ fn print_seq(
|
||||||
terminator: &str,
|
terminator: &str,
|
||||||
pad: bool,
|
pad: bool,
|
||||||
padding: usize,
|
padding: usize,
|
||||||
format: &Option<Format<num_format::Float>>,
|
format: Option<&Format<num_format::Float>>,
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
let stdout = stdout();
|
let stdout = stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
|
|
|
@ -224,11 +224,8 @@ fn read_write_loop<I: WriteableTmpFile>(
|
||||||
let mut sender_option = Some(sender);
|
let mut sender_option = Some(sender);
|
||||||
let mut tmp_files = vec![];
|
let mut tmp_files = vec![];
|
||||||
loop {
|
loop {
|
||||||
let chunk = match receiver.recv() {
|
let Ok(chunk) = receiver.recv() else {
|
||||||
Ok(it) => it,
|
|
||||||
_ => {
|
|
||||||
return Ok(ReadResult::WroteChunksToFile { tmp_files });
|
return Ok(ReadResult::WroteChunksToFile { tmp_files });
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let tmp_file = write::<I>(
|
let tmp_file = write::<I>(
|
||||||
|
|
|
@ -1408,20 +1408,17 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes = line.as_slice();
|
let bytes = line.as_slice();
|
||||||
match kth_chunk {
|
if let Some(chunk_number) = kth_chunk {
|
||||||
Some(chunk_number) => {
|
|
||||||
if (i % num_chunks) == (chunk_number - 1) as usize {
|
if (i % num_chunks) == (chunk_number - 1) as usize {
|
||||||
stdout_writer.write_all(bytes)?;
|
stdout_writer.write_all(bytes)?;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
None => {
|
|
||||||
let writer = out_files.get_writer(i % num_chunks, settings)?;
|
let writer = out_files.get_writer(i % num_chunks, settings)?;
|
||||||
let writer_stdin_open = custom_write_all(bytes, writer, settings)?;
|
let writer_stdin_open = custom_write_all(bytes, writer, settings)?;
|
||||||
if !writer_stdin_open {
|
if !writer_stdin_open {
|
||||||
closed_writers += 1;
|
closed_writers += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
i += 1;
|
i += 1;
|
||||||
if closed_writers == num_chunks {
|
if closed_writers == num_chunks {
|
||||||
// all writers are closed - stop reading
|
// all writers are closed - stop reading
|
||||||
|
|
|
@ -34,9 +34,8 @@ pub enum ParseError {
|
||||||
/// Parses obsolete syntax
|
/// Parses obsolete syntax
|
||||||
/// tail -\[NUM\]\[bcl\]\[f\] and tail +\[NUM\]\[bcl\]\[f\]
|
/// tail -\[NUM\]\[bcl\]\[f\] and tail +\[NUM\]\[bcl\]\[f\]
|
||||||
pub fn parse_obsolete(src: &OsString) -> Option<Result<ObsoleteArgs, ParseError>> {
|
pub fn parse_obsolete(src: &OsString) -> Option<Result<ObsoleteArgs, ParseError>> {
|
||||||
let mut rest = match src.to_str() {
|
let Some(mut rest) = src.to_str() else {
|
||||||
Some(src) => src,
|
return Some(Err(ParseError::InvalidEncoding));
|
||||||
None => return Some(Err(ParseError::InvalidEncoding)),
|
|
||||||
};
|
};
|
||||||
let sign = if let Some(r) = rest.strip_prefix('-') {
|
let sign = if let Some(r) = rest.strip_prefix('-') {
|
||||||
rest = r;
|
rest = r;
|
||||||
|
@ -86,9 +85,8 @@ pub fn parse_obsolete(src: &OsString) -> Option<Result<ObsoleteArgs, ParseError>
|
||||||
}
|
}
|
||||||
|
|
||||||
let multiplier = if mode == 'b' { 512 } else { 1 };
|
let multiplier = if mode == 'b' { 512 } else { 1 };
|
||||||
let num = match num.checked_mul(multiplier) {
|
let Some(num) = num.checked_mul(multiplier) else {
|
||||||
Some(n) => n,
|
return Some(Err(ParseError::Overflow));
|
||||||
None => return Some(Err(ParseError::Overflow)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Ok(ObsoleteArgs {
|
Some(Ok(ObsoleteArgs {
|
||||||
|
|
|
@ -210,13 +210,8 @@ fn integers(a: &OsStr, b: &OsStr, op: &OsStr) -> ParseResult<bool> {
|
||||||
fn files(a: &OsStr, b: &OsStr, op: &OsStr) -> ParseResult<bool> {
|
fn files(a: &OsStr, b: &OsStr, op: &OsStr) -> ParseResult<bool> {
|
||||||
// Don't manage the error. GNU doesn't show error when doing
|
// Don't manage the error. GNU doesn't show error when doing
|
||||||
// test foo -nt bar
|
// test foo -nt bar
|
||||||
let f_a = match fs::metadata(a) {
|
let (Ok(f_a), Ok(f_b)) = (fs::metadata(a), fs::metadata(b)) else {
|
||||||
Ok(f) => f,
|
return Ok(false);
|
||||||
Err(_) => return Ok(false),
|
|
||||||
};
|
|
||||||
let f_b = match fs::metadata(b) {
|
|
||||||
Ok(f) => f,
|
|
||||||
Err(_) => return Ok(false),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(match op.to_str() {
|
Ok(match op.to_str() {
|
||||||
|
@ -290,11 +285,8 @@ fn path(path: &OsStr, condition: &PathCondition) -> bool {
|
||||||
fs::metadata(path)
|
fs::metadata(path)
|
||||||
};
|
};
|
||||||
|
|
||||||
let metadata = match metadata {
|
let Ok(metadata) = metadata else {
|
||||||
Ok(metadata) => metadata,
|
|
||||||
Err(_) => {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let file_type = metadata.file_type();
|
let file_type = metadata.file_type();
|
||||||
|
|
|
@ -599,14 +599,11 @@ fn parse_timestamp(s: &str) -> UResult<FileTime> {
|
||||||
|
|
||||||
let local = NaiveDateTime::parse_from_str(&ts, format)
|
let local = NaiveDateTime::parse_from_str(&ts, format)
|
||||||
.map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?;
|
.map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?;
|
||||||
let mut local = match chrono::Local.from_local_datetime(&local) {
|
let LocalResult::Single(mut local) = chrono::Local.from_local_datetime(&local) else {
|
||||||
LocalResult::Single(dt) => dt,
|
|
||||||
_ => {
|
|
||||||
return Err(USimpleError::new(
|
return Err(USimpleError::new(
|
||||||
1,
|
1,
|
||||||
format!("invalid date ts format {}", ts.quote()),
|
format!("invalid date ts format {}", ts.quote()),
|
||||||
))
|
));
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Chrono caps seconds at 59, but 60 is valid. It might be a leap second
|
// Chrono caps seconds at 59, but 60 is valid. It might be a leap second
|
||||||
|
|
|
@ -171,12 +171,9 @@ impl Uniq {
|
||||||
|
|
||||||
// Convert the leftover bytes to UTF-8 for character-based -w
|
// Convert the leftover bytes to UTF-8 for character-based -w
|
||||||
// If invalid UTF-8, just compare them as individual bytes (fallback).
|
// If invalid UTF-8, just compare them as individual bytes (fallback).
|
||||||
let string_after_skip = match std::str::from_utf8(fields_to_check) {
|
let Ok(string_after_skip) = std::str::from_utf8(fields_to_check) else {
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => {
|
|
||||||
// Fallback: if invalid UTF-8, treat them as single-byte “chars”
|
// Fallback: if invalid UTF-8, treat them as single-byte “chars”
|
||||||
return closure(&mut fields_to_check.iter().map(|&b| b as char));
|
return closure(&mut fields_to_check.iter().map(|&b| b as char));
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let total_chars = string_after_skip.chars().count();
|
let total_chars = string_after_skip.chars().count();
|
||||||
|
|
|
@ -652,14 +652,10 @@ pub fn are_hardlinks_to_same_file(_source: &Path, _target: &Path) -> bool {
|
||||||
/// * `bool` - Returns `true` if the paths are hard links to the same file, and `false` otherwise.
|
/// * `bool` - Returns `true` if the paths are hard links to the same file, and `false` otherwise.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn are_hardlinks_to_same_file(source: &Path, target: &Path) -> bool {
|
pub fn are_hardlinks_to_same_file(source: &Path, target: &Path) -> bool {
|
||||||
let source_metadata = match fs::symlink_metadata(source) {
|
let (Ok(source_metadata), Ok(target_metadata)) =
|
||||||
Ok(metadata) => metadata,
|
(fs::symlink_metadata(source), fs::symlink_metadata(target))
|
||||||
Err(_) => return false,
|
else {
|
||||||
};
|
return false;
|
||||||
|
|
||||||
let target_metadata = match fs::symlink_metadata(target) {
|
|
||||||
Ok(metadata) => metadata,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
source_metadata.ino() == target_metadata.ino() && source_metadata.dev() == target_metadata.dev()
|
source_metadata.ino() == target_metadata.ino() && source_metadata.dev() == target_metadata.dev()
|
||||||
|
@ -682,14 +678,10 @@ pub fn are_hardlinks_or_one_way_symlink_to_same_file(_source: &Path, _target: &P
|
||||||
/// * `bool` - Returns `true` if either of above conditions are true, and `false` otherwise.
|
/// * `bool` - Returns `true` if either of above conditions are true, and `false` otherwise.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn are_hardlinks_or_one_way_symlink_to_same_file(source: &Path, target: &Path) -> bool {
|
pub fn are_hardlinks_or_one_way_symlink_to_same_file(source: &Path, target: &Path) -> bool {
|
||||||
let source_metadata = match fs::metadata(source) {
|
let (Ok(source_metadata), Ok(target_metadata)) =
|
||||||
Ok(metadata) => metadata,
|
(fs::metadata(source), fs::symlink_metadata(target))
|
||||||
Err(_) => return false,
|
else {
|
||||||
};
|
return false;
|
||||||
|
|
||||||
let target_metadata = match fs::symlink_metadata(target) {
|
|
||||||
Ok(metadata) => metadata,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
source_metadata.ino() == target_metadata.ino() && source_metadata.dev() == target_metadata.dev()
|
source_metadata.ino() == target_metadata.ino() && source_metadata.dev() == target_metadata.dev()
|
||||||
|
|
|
@ -79,13 +79,10 @@ pub fn apply_xattrs<P: AsRef<Path>>(
|
||||||
/// `true` if the file has extended attributes (indicating an ACL), `false` otherwise.
|
/// `true` if the file has extended attributes (indicating an ACL), `false` otherwise.
|
||||||
pub fn has_acl<P: AsRef<Path>>(file: P) -> bool {
|
pub fn has_acl<P: AsRef<Path>>(file: P) -> bool {
|
||||||
// don't use exacl here, it is doing more getxattr call then needed
|
// don't use exacl here, it is doing more getxattr call then needed
|
||||||
match xattr::list(file) {
|
xattr::list(file).is_ok_and(|acl| {
|
||||||
Ok(acl) => {
|
|
||||||
// if we have extra attributes, we have an acl
|
// if we have extra attributes, we have an acl
|
||||||
acl.count() > 0
|
acl.count() > 0
|
||||||
}
|
})
|
||||||
Err(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the permissions bits of a file or directory which has Access Control List (ACL) entries based on its
|
/// Returns the permissions bits of a file or directory which has Access Control List (ACL) entries based on its
|
||||||
|
@ -132,7 +129,7 @@ pub fn get_acl_perm_bits_from_xattr<P: AsRef<Path>>(source: P) -> u32 {
|
||||||
|
|
||||||
for entry in acl_entries.chunks_exact(4) {
|
for entry in acl_entries.chunks_exact(4) {
|
||||||
// Third byte and fourth byte will be the perm bits
|
// Third byte and fourth byte will be the perm bits
|
||||||
perm = (perm << 3) | entry[2] as u32 | entry[3] as u32;
|
perm = (perm << 3) | u32::from(entry[2]) | u32::from(entry[3]);
|
||||||
}
|
}
|
||||||
return perm;
|
return perm;
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,9 +273,7 @@ impl ChownExecutor {
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn traverse<P: AsRef<Path>>(&self, root: P) -> i32 {
|
fn traverse<P: AsRef<Path>>(&self, root: P) -> i32 {
|
||||||
let path = root.as_ref();
|
let path = root.as_ref();
|
||||||
let meta = match self.obtain_meta(path, self.dereference) {
|
let Some(meta) = self.obtain_meta(path, self.dereference) else {
|
||||||
Some(m) => m,
|
|
||||||
_ => {
|
|
||||||
if self.verbosity.level == VerbosityLevel::Verbose {
|
if self.verbosity.level == VerbosityLevel::Verbose {
|
||||||
println!(
|
println!(
|
||||||
"failed to change ownership of {} to {}",
|
"failed to change ownership of {} to {}",
|
||||||
|
@ -284,7 +282,6 @@ impl ChownExecutor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.recursive
|
if self.recursive
|
||||||
|
@ -370,9 +367,8 @@ impl ChownExecutor {
|
||||||
Ok(entry) => entry,
|
Ok(entry) => entry,
|
||||||
};
|
};
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
let meta = match self.obtain_meta(path, self.dereference) {
|
|
||||||
Some(m) => m,
|
let Some(meta) = self.obtain_meta(path, self.dereference) else {
|
||||||
_ => {
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
if entry.file_type().is_dir() {
|
if entry.file_type().is_dir() {
|
||||||
// Instruct walkdir to skip this directory to avoid getting another error
|
// Instruct walkdir to skip this directory to avoid getting another error
|
||||||
|
@ -380,7 +376,6 @@ impl ChownExecutor {
|
||||||
iterator.skip_current_dir();
|
iterator.skip_current_dir();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.preserve_root && is_root(path, self.traverse_symlinks == TraverseSymlinks::All)
|
if self.preserve_root && is_root(path, self.traverse_symlinks == TraverseSymlinks::All)
|
||||||
|
@ -425,24 +420,18 @@ impl ChownExecutor {
|
||||||
|
|
||||||
fn obtain_meta<P: AsRef<Path>>(&self, path: P, follow: bool) -> Option<Metadata> {
|
fn obtain_meta<P: AsRef<Path>>(&self, path: P, follow: bool) -> Option<Metadata> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
get_metadata(path, follow)
|
||||||
let meta = get_metadata(path, follow);
|
.inspect_err(|e| {
|
||||||
|
if self.verbosity.level != VerbosityLevel::Silent {
|
||||||
match meta {
|
show_error!(
|
||||||
Err(e) => {
|
|
||||||
match self.verbosity.level {
|
|
||||||
VerbosityLevel::Silent => (),
|
|
||||||
_ => show_error!(
|
|
||||||
"cannot {} {}: {}",
|
"cannot {} {}: {}",
|
||||||
if follow { "dereference" } else { "access" },
|
if follow { "dereference" } else { "access" },
|
||||||
path.quote(),
|
path.quote(),
|
||||||
strip_errno(&e)
|
strip_errno(e)
|
||||||
),
|
);
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Ok(meta) => Some(meta),
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -199,16 +199,9 @@ impl<'parser> Parser<'parser> {
|
||||||
|
|
||||||
/// Same as `parse()` but tries to return u64
|
/// Same as `parse()` but tries to return u64
|
||||||
pub fn parse_u64(&self, size: &str) -> Result<u64, ParseSizeError> {
|
pub fn parse_u64(&self, size: &str) -> Result<u64, ParseSizeError> {
|
||||||
match self.parse(size) {
|
self.parse(size).and_then(|num_u128| {
|
||||||
Ok(num_u128) => {
|
u64::try_from(num_u128).map_err(|_| ParseSizeError::size_too_big(size))
|
||||||
let num_u64 = match u64::try_from(num_u128) {
|
})
|
||||||
Ok(n) => n,
|
|
||||||
Err(_) => return Err(ParseSizeError::size_too_big(size)),
|
|
||||||
};
|
|
||||||
Ok(num_u64)
|
|
||||||
}
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `parse_u64()`, except returns `u64::MAX` on overflow
|
/// Same as `parse_u64()`, except returns `u64::MAX` on overflow
|
||||||
|
|
|
@ -49,9 +49,8 @@ pub fn from_str(string: &str) -> Result<Duration, String> {
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
return Err("empty string".to_owned());
|
return Err("empty string".to_owned());
|
||||||
}
|
}
|
||||||
let slice = match string.get(..len - 1) {
|
let Some(slice) = string.get(..len - 1) else {
|
||||||
Some(s) => s,
|
return Err(format!("invalid time interval {}", string.quote()));
|
||||||
None => return Err(format!("invalid time interval {}", string.quote())),
|
|
||||||
};
|
};
|
||||||
let (numstr, times) = match string.chars().next_back().unwrap() {
|
let (numstr, times) = match string.chars().next_back().unwrap() {
|
||||||
's' => (slice, 1),
|
's' => (slice, 1),
|
||||||
|
|
|
@ -950,7 +950,7 @@ mod tests_split_iterator {
|
||||||
| '*' | '?' | '[' | '#' | '˜' | '=' | '%' => {
|
| '*' | '?' | '[' | '#' | '˜' | '=' | '%' => {
|
||||||
special = true;
|
special = true;
|
||||||
}
|
}
|
||||||
_ => continue,
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue