mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
Merge branch 'uutils:master' into master
This commit is contained in:
+26
-18
@@ -6,6 +6,7 @@
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use clap::App;
|
||||
use clap::Arg;
|
||||
use clap::Shell;
|
||||
use std::cmp;
|
||||
use std::collections::hash_map::HashMap;
|
||||
@@ -122,31 +123,38 @@ fn main() {
|
||||
|
||||
/// Prints completions for the utility in the first parameter for the shell in the second parameter to stdout
|
||||
fn gen_completions<T: uucore::Args>(
|
||||
mut args: impl Iterator<Item = OsString>,
|
||||
args: impl Iterator<Item = OsString>,
|
||||
util_map: UtilityMap<T>,
|
||||
) -> ! {
|
||||
let utility = args
|
||||
.next()
|
||||
.expect("expected utility as the first parameter")
|
||||
.to_str()
|
||||
.expect("utility name was not valid utf-8")
|
||||
.to_owned();
|
||||
let shell = args
|
||||
.next()
|
||||
.expect("expected shell as the second parameter")
|
||||
.to_str()
|
||||
.expect("shell name was not valid utf-8")
|
||||
.to_owned();
|
||||
let all_utilities: Vec<_> = std::iter::once("coreutils")
|
||||
.chain(util_map.keys().copied())
|
||||
.collect();
|
||||
|
||||
let matches = App::new("completion")
|
||||
.about("Prints completions to stdout")
|
||||
.arg(
|
||||
Arg::with_name("utility")
|
||||
.possible_values(&all_utilities)
|
||||
.required(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("shell")
|
||||
.possible_values(&Shell::variants())
|
||||
.required(true),
|
||||
)
|
||||
.get_matches_from(std::iter::once(OsString::from("completion")).chain(args));
|
||||
|
||||
let utility = matches.value_of("utility").unwrap();
|
||||
let shell = matches.value_of("shell").unwrap();
|
||||
|
||||
let mut app = if utility == "coreutils" {
|
||||
gen_coreutils_app(util_map)
|
||||
} else if let Some((_, app)) = util_map.get(utility.as_str()) {
|
||||
app()
|
||||
} else {
|
||||
eprintln!("{} is not a valid utility", utility);
|
||||
process::exit(1)
|
||||
util_map.get(utility).unwrap().1()
|
||||
};
|
||||
let shell: Shell = shell.parse().unwrap();
|
||||
let bin_name = std::env::var("PROG_PREFIX").unwrap_or_default() + &utility;
|
||||
let bin_name = std::env::var("PROG_PREFIX").unwrap_or_default() + utility;
|
||||
|
||||
app.gen_completions_to(bin_name, shell, &mut io::stdout());
|
||||
io::stdout().flush().unwrap();
|
||||
process::exit(0);
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
// spell-checker:ignore (ToDO) nonprint nonblank nonprinting
|
||||
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[cfg(unix)]
|
||||
extern crate unix_socket;
|
||||
#[macro_use]
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use std::path::Path;
|
||||
use uucore::error::{UResult, UUsageError};
|
||||
use uucore::InvalidEncodingHandling;
|
||||
|
||||
static ABOUT: &str = "strip last component from file name";
|
||||
@@ -30,7 +34,8 @@ fn get_long_usage() -> String {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
#[uucore_procs::gen_uumain]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args
|
||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||
.accept_any();
|
||||
@@ -77,11 +82,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
print!("{}", separator);
|
||||
}
|
||||
} else {
|
||||
show_usage_error!("missing operand");
|
||||
return 1;
|
||||
return Err(UUsageError::new(1, "missing operand".to_string()));
|
||||
}
|
||||
|
||||
0
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn uu_app() -> App<'static, 'static> {
|
||||
|
||||
+37
-12
@@ -10,6 +10,7 @@ extern crate uucore;
|
||||
|
||||
use chrono::prelude::DateTime;
|
||||
use chrono::Local;
|
||||
use clap::ArgMatches;
|
||||
use clap::{crate_version, App, Arg};
|
||||
use std::collections::HashSet;
|
||||
use std::convert::TryFrom;
|
||||
@@ -63,6 +64,7 @@ mod options {
|
||||
pub const TIME_STYLE: &str = "time-style";
|
||||
pub const ONE_FILE_SYSTEM: &str = "one-file-system";
|
||||
pub const DEREFERENCE: &str = "dereference";
|
||||
pub const INODES: &str = "inodes";
|
||||
pub const FILE: &str = "FILE";
|
||||
}
|
||||
|
||||
@@ -89,6 +91,7 @@ struct Options {
|
||||
separate_dirs: bool,
|
||||
one_file_system: bool,
|
||||
dereference: bool,
|
||||
inodes: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||
@@ -102,6 +105,7 @@ struct Stat {
|
||||
is_dir: bool,
|
||||
size: u64,
|
||||
blocks: u64,
|
||||
inodes: u64,
|
||||
inode: Option<FileInfo>,
|
||||
created: Option<u64>,
|
||||
accessed: u64,
|
||||
@@ -127,6 +131,7 @@ impl Stat {
|
||||
is_dir: metadata.is_dir(),
|
||||
size: metadata.len(),
|
||||
blocks: metadata.blocks() as u64,
|
||||
inodes: 1,
|
||||
inode: Some(file_info),
|
||||
created: birth_u64(&metadata),
|
||||
accessed: metadata.atime() as u64,
|
||||
@@ -144,6 +149,7 @@ impl Stat {
|
||||
size: metadata.len(),
|
||||
blocks: size_on_disk / 1024 * 2,
|
||||
inode: file_info,
|
||||
inodes: 1,
|
||||
created: windows_creation_time_to_unix_time(metadata.creation_time()),
|
||||
accessed: windows_time_to_unix_time(metadata.last_access_time()),
|
||||
modified: windows_time_to_unix_time(metadata.last_write_time()),
|
||||
@@ -257,6 +263,18 @@ fn read_block_size(s: Option<&str>) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_size(matches: &ArgMatches, stat: &Stat) -> u64 {
|
||||
if matches.is_present(options::INODES) {
|
||||
stat.inodes
|
||||
} else if matches.is_present(options::APPARENT_SIZE) || matches.is_present(options::BYTES) {
|
||||
stat.size
|
||||
} else {
|
||||
// The st_blocks field indicates the number of blocks allocated to the file, 512-byte units.
|
||||
// See: http://linux.die.net/man/2/stat
|
||||
stat.blocks * 512
|
||||
}
|
||||
}
|
||||
|
||||
// this takes `my_stat` to avoid having to stat files multiple times.
|
||||
// XXX: this should use the impl Trait return type when it is stabilized
|
||||
fn du(
|
||||
@@ -307,6 +325,7 @@ fn du(
|
||||
} else {
|
||||
my_stat.size += this_stat.size;
|
||||
my_stat.blocks += this_stat.blocks;
|
||||
my_stat.inodes += 1;
|
||||
if options.all {
|
||||
stats.push(this_stat);
|
||||
}
|
||||
@@ -330,6 +349,7 @@ fn du(
|
||||
if !options.separate_dirs && stat.path.parent().unwrap() == my_stat.path {
|
||||
my_stat.size += stat.size;
|
||||
my_stat.blocks += stat.blocks;
|
||||
my_stat.inodes += stat.inodes;
|
||||
}
|
||||
options
|
||||
.max_depth
|
||||
@@ -413,6 +433,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
separate_dirs: matches.is_present(options::SEPARATE_DIRS),
|
||||
one_file_system: matches.is_present(options::ONE_FILE_SYSTEM),
|
||||
dereference: matches.is_present(options::DEREFERENCE),
|
||||
inodes: matches.is_present(options::INODES),
|
||||
};
|
||||
|
||||
let files = match matches.value_of(options::FILE) {
|
||||
@@ -420,6 +441,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
None => vec!["."],
|
||||
};
|
||||
|
||||
if options.inodes
|
||||
&& (matches.is_present(options::APPARENT_SIZE) || matches.is_present(options::BYTES))
|
||||
{
|
||||
show_warning!("options --apparent-size and -b are ineffective with --inodes")
|
||||
}
|
||||
|
||||
let block_size = u64::try_from(read_block_size(matches.value_of(options::BLOCK_SIZE))).unwrap();
|
||||
|
||||
let threshold = matches.value_of(options::THRESHOLD).map(|s| {
|
||||
@@ -445,7 +472,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
convert_size_other
|
||||
}
|
||||
};
|
||||
let convert_size = |size| convert_size_fn(size, multiplier, block_size);
|
||||
let convert_size = |size: u64| {
|
||||
if options.inodes {
|
||||
size.to_string()
|
||||
} else {
|
||||
convert_size_fn(size, multiplier, block_size)
|
||||
}
|
||||
};
|
||||
|
||||
let time_format_str = match matches.value_of("time-style") {
|
||||
Some(s) => match s {
|
||||
@@ -488,15 +521,7 @@ Try '{} --help' for more information.",
|
||||
let (_, len) = iter.size_hint();
|
||||
let len = len.unwrap();
|
||||
for (index, stat) in iter.enumerate() {
|
||||
let size = if matches.is_present(options::APPARENT_SIZE)
|
||||
|| matches.is_present(options::BYTES)
|
||||
{
|
||||
stat.size
|
||||
} else {
|
||||
// C's stat is such that each block is assume to be 512 bytes
|
||||
// See: http://linux.die.net/man/2/stat
|
||||
stat.blocks * 512
|
||||
};
|
||||
let size = choose_size(&matches, &stat);
|
||||
|
||||
if threshold.map_or(false, |threshold| threshold.should_exclude(size)) {
|
||||
continue;
|
||||
@@ -629,8 +654,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||
.help("print sizes in human readable format (e.g., 1K 234M 2G)")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("inodes")
|
||||
.long("inodes")
|
||||
Arg::with_name(options::INODES)
|
||||
.long(options::INODES)
|
||||
.help(
|
||||
"list inode usage information instead of block usage like --block-size=1K"
|
||||
)
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
|
||||
// spell-checker:ignore (ToDO) gethostid
|
||||
|
||||
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App};
|
||||
use libc::c_long;
|
||||
use uucore::error::UResult;
|
||||
|
||||
static SYNTAX: &str = "[options]";
|
||||
|
||||
@@ -20,10 +24,11 @@ extern "C" {
|
||||
pub fn gethostid() -> c_long;
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
#[uucore_procs::gen_uumain]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
uu_app().get_matches_from(args);
|
||||
hostid();
|
||||
0
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn uu_app() -> App<'static, 'static> {
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
|
||||
|
||||
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
@@ -14,6 +17,9 @@ use clap::{crate_version, App, Arg, ArgMatches};
|
||||
use std::collections::hash_set::HashSet;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::str;
|
||||
#[cfg(windows)]
|
||||
use uucore::error::UUsageError;
|
||||
use uucore::error::{UResult, USimpleError};
|
||||
|
||||
#[cfg(windows)]
|
||||
use winapi::shared::minwindef::MAKEWORD;
|
||||
@@ -28,15 +34,18 @@ static OPT_FQDN: &str = "fqdn";
|
||||
static OPT_SHORT: &str = "short";
|
||||
static OPT_HOST: &str = "host";
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
#[uucore_procs::gen_uumain]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
#![allow(clippy::let_and_return)]
|
||||
#[cfg(windows)]
|
||||
unsafe {
|
||||
#[allow(deprecated)]
|
||||
let mut data = std::mem::uninitialized();
|
||||
if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 {
|
||||
eprintln!("Failed to start Winsock 2.2");
|
||||
return 1;
|
||||
return Err(UUsageError::new(
|
||||
1,
|
||||
"Failed to start Winsock 2.2".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let result = execute(args);
|
||||
@@ -50,7 +59,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
fn get_usage() -> String {
|
||||
format!("{0} [OPTION]... [HOSTNAME]", executable!())
|
||||
}
|
||||
fn execute(args: impl uucore::Args) -> i32 {
|
||||
fn execute(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = get_usage();
|
||||
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
|
||||
|
||||
@@ -58,10 +67,9 @@ fn execute(args: impl uucore::Args) -> i32 {
|
||||
None => display_hostname(&matches),
|
||||
Some(host) => {
|
||||
if let Err(err) = hostname::set(host) {
|
||||
show_error!("{}", err);
|
||||
1
|
||||
return Err(USimpleError::new(1, format!("{}", err)));
|
||||
} else {
|
||||
0
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +105,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||
.arg(Arg::with_name(OPT_HOST))
|
||||
}
|
||||
|
||||
fn display_hostname(matches: &ArgMatches) -> i32 {
|
||||
fn display_hostname(matches: &ArgMatches) -> UResult<()> {
|
||||
let hostname = hostname::get().unwrap().into_string().unwrap();
|
||||
|
||||
if matches.is_present(OPT_IP_ADDRESS) {
|
||||
@@ -127,12 +135,10 @@ fn display_hostname(matches: &ArgMatches) -> i32 {
|
||||
println!("{}", &output[0..len - 1]);
|
||||
}
|
||||
|
||||
0
|
||||
Ok(())
|
||||
}
|
||||
Err(f) => {
|
||||
show_error!("{}", f);
|
||||
|
||||
1
|
||||
return Err(USimpleError::new(1, format!("{}", f)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -144,12 +150,12 @@ fn display_hostname(matches: &ArgMatches) -> i32 {
|
||||
} else {
|
||||
println!("{}", &hostname[ci.0 + 1..]);
|
||||
}
|
||||
return 0;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", hostname);
|
||||
|
||||
0
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ extern crate uucore;
|
||||
use clap::{crate_version, App, Arg, ArgMatches};
|
||||
use file_diff::diff;
|
||||
use filetime::{set_file_times, FileTime};
|
||||
use uucore::backup_control::{self, BackupMode};
|
||||
use uucore::entries::{grp2gid, usr2uid};
|
||||
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
|
||||
|
||||
@@ -33,6 +34,7 @@ const DEFAULT_STRIP_PROGRAM: &str = "strip";
|
||||
pub struct Behavior {
|
||||
main_function: MainFunction,
|
||||
specified_mode: Option<u32>,
|
||||
backup_mode: BackupMode,
|
||||
suffix: String,
|
||||
owner: String,
|
||||
group: String,
|
||||
@@ -68,7 +70,7 @@ static ABOUT: &str = "Copy SOURCE to DEST or multiple SOURCE(s) to the existing
|
||||
|
||||
static OPT_COMPARE: &str = "compare";
|
||||
static OPT_BACKUP: &str = "backup";
|
||||
static OPT_BACKUP_2: &str = "backup2";
|
||||
static OPT_BACKUP_NO_ARG: &str = "backup2";
|
||||
static OPT_DIRECTORY: &str = "directory";
|
||||
static OPT_IGNORED: &str = "ignored";
|
||||
static OPT_CREATE_LEADING: &str = "create-leading";
|
||||
@@ -130,14 +132,17 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||
.arg(
|
||||
Arg::with_name(OPT_BACKUP)
|
||||
.long(OPT_BACKUP)
|
||||
.help("(unimplemented) make a backup of each existing destination file")
|
||||
.help("make a backup of each existing destination file")
|
||||
.takes_value(true)
|
||||
.require_equals(true)
|
||||
.min_values(0)
|
||||
.value_name("CONTROL")
|
||||
)
|
||||
.arg(
|
||||
// TODO implement flag
|
||||
Arg::with_name(OPT_BACKUP_2)
|
||||
Arg::with_name(OPT_BACKUP_NO_ARG)
|
||||
.short("b")
|
||||
.help("(unimplemented) like --backup but does not accept an argument")
|
||||
.help("like --backup but does not accept an argument")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_IGNORED)
|
||||
@@ -210,7 +215,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||
Arg::with_name(OPT_SUFFIX)
|
||||
.short("S")
|
||||
.long(OPT_SUFFIX)
|
||||
.help("(unimplemented) override the usual backup suffix")
|
||||
.help("override the usual backup suffix")
|
||||
.value_name("SUFFIX")
|
||||
.takes_value(true)
|
||||
.min_values(1)
|
||||
@@ -265,13 +270,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||
///
|
||||
///
|
||||
fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
|
||||
if matches.is_present(OPT_BACKUP) {
|
||||
Err("--backup")
|
||||
} else if matches.is_present(OPT_BACKUP_2) {
|
||||
Err("-b")
|
||||
} else if matches.is_present(OPT_SUFFIX) {
|
||||
Err("--suffix, -S")
|
||||
} else if matches.is_present(OPT_NO_TARGET_DIRECTORY) {
|
||||
if matches.is_present(OPT_NO_TARGET_DIRECTORY) {
|
||||
Err("--no-target-directory, -T")
|
||||
} else if matches.is_present(OPT_PRESERVE_CONTEXT) {
|
||||
Err("--preserve-context, -P")
|
||||
@@ -309,18 +308,16 @@ fn behavior(matches: &ArgMatches) -> Result<Behavior, i32> {
|
||||
None
|
||||
};
|
||||
|
||||
let backup_suffix = if matches.is_present(OPT_SUFFIX) {
|
||||
matches.value_of(OPT_SUFFIX).ok_or(1)?
|
||||
} else {
|
||||
"~"
|
||||
};
|
||||
|
||||
let target_dir = matches.value_of(OPT_TARGET_DIRECTORY).map(|d| d.to_owned());
|
||||
|
||||
Ok(Behavior {
|
||||
main_function,
|
||||
specified_mode,
|
||||
suffix: backup_suffix.to_string(),
|
||||
backup_mode: backup_control::determine_backup_mode(
|
||||
matches.is_present(OPT_BACKUP_NO_ARG) || matches.is_present(OPT_BACKUP),
|
||||
matches.value_of(OPT_BACKUP),
|
||||
),
|
||||
suffix: backup_control::determine_backup_suffix(matches.value_of(OPT_SUFFIX)),
|
||||
owner: matches.value_of(OPT_OWNER).unwrap_or("").to_string(),
|
||||
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
|
||||
verbose: matches.is_present(OPT_VERBOSE),
|
||||
@@ -517,6 +514,28 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> Result<(), ()> {
|
||||
if b.compare && !need_copy(from, to, b) {
|
||||
return Ok(());
|
||||
}
|
||||
// Declare the path here as we may need it for the verbose output below.
|
||||
let mut backup_path = None;
|
||||
|
||||
// Perform backup, if any, before overwriting 'to'
|
||||
//
|
||||
// The codes actually making use of the backup process don't seem to agree
|
||||
// on how best to approach the issue. (mv and ln, for example)
|
||||
if to.exists() {
|
||||
backup_path = backup_control::get_backup_path(b.backup_mode, to, &b.suffix);
|
||||
if let Some(ref backup_path) = backup_path {
|
||||
// TODO!!
|
||||
if let Err(err) = fs::rename(to, backup_path) {
|
||||
show_error!(
|
||||
"install: cannot backup file '{}' to '{}': {}",
|
||||
to.display(),
|
||||
backup_path.display(),
|
||||
err
|
||||
);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if from.to_string_lossy() == "/dev/null" {
|
||||
/* workaround a limitation of fs::copy
|
||||
@@ -624,7 +643,11 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> Result<(), ()> {
|
||||
}
|
||||
|
||||
if b.verbose {
|
||||
show_error!("'{}' -> '{}'", from.display(), to.display());
|
||||
print!("'{}' -> '{}'", from.display(), to.display());
|
||||
match backup_path {
|
||||
Some(path) => println!(" (backup: '{}')", path.display()),
|
||||
None => println!(),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+137
-121
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,9 @@
|
||||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
// spell-checker:ignore (paths) GPGHome
|
||||
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
|
||||
@@ -349,12 +349,10 @@ impl<'a> Pager<'a> {
|
||||
let status = format!("--More--({})", status_inner);
|
||||
|
||||
let banner = match (self.silent, wrong_key) {
|
||||
(true, Some(key)) => {
|
||||
format!(
|
||||
"{} [Unknown key: '{}'. Press 'h' for instructions. (unimplemented)]",
|
||||
status, key
|
||||
)
|
||||
}
|
||||
(true, Some(key)) => format!(
|
||||
"{} [Unknown key: '{}'. Press 'h' for instructions. (unimplemented)]",
|
||||
status, key
|
||||
),
|
||||
(true, None) => format!("{}[Press space to continue, 'q' to quit.]", status),
|
||||
(false, Some(_)) => format!("{}{}", status, BELL),
|
||||
(false, None) => status,
|
||||
|
||||
@@ -1267,6 +1267,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||
.help("sort by a key")
|
||||
.long_help(LONG_HELP_KEYS)
|
||||
.multiple(true)
|
||||
.number_of_values(1)
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm
|
||||
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
pub extern crate filetime;
|
||||
|
||||
#[macro_use]
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// *
|
||||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
// spell-checker:ignore (strings) ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
|
||||
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
#![allow(clippy::nonstandard_macro_braces)]
|
||||
|
||||
extern crate data_encoding;
|
||||
|
||||
use self::data_encoding::{DecodeError, BASE32, BASE64};
|
||||
|
||||
@@ -27,6 +27,9 @@ macro_rules! show(
|
||||
let e = $err;
|
||||
uucore::error::set_exit_code(e.code());
|
||||
eprintln!("{}: {}", executable!(), e);
|
||||
if e.usage() {
|
||||
eprintln!("Try '{} --help' for more information.", executable!());
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -37,6 +37,19 @@ pub fn determine_backup_suffix(supplied_suffix: Option<&str>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// # TODO
|
||||
///
|
||||
/// This function currently deviates slightly from how the [manual][1] describes
|
||||
/// that it should work. In particular, the current implementation:
|
||||
///
|
||||
/// 1. Doesn't strictly respect the order in which to determine the backup type,
|
||||
/// which is (in order of precedence)
|
||||
/// 1. Take a valid value to the '--backup' option
|
||||
/// 2. Take the value of the `VERSION_CONTROL` env var
|
||||
/// 3. default to 'existing'
|
||||
/// 2. Doesn't accept abbreviations to the 'backup_option' parameter
|
||||
///
|
||||
/// [1]: https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
|
||||
pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>) -> BackupMode {
|
||||
if backup_opt_exists {
|
||||
match backup_opt.map(String::from) {
|
||||
|
||||
@@ -144,6 +144,13 @@ impl UError {
|
||||
UError::Custom(e) => e.code(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> bool {
|
||||
match self {
|
||||
UError::Common(e) => e.usage(),
|
||||
UError::Custom(e) => e.usage(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UCommonError> for UError {
|
||||
@@ -220,6 +227,10 @@ pub trait UCustomError: Error {
|
||||
fn code(&self) -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn usage(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<dyn UCustomError>> for i32 {
|
||||
@@ -291,6 +302,37 @@ impl UCustomError for USimpleError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UUsageError {
|
||||
pub code: i32,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl UUsageError {
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
pub fn new(code: i32, message: String) -> UError {
|
||||
UError::Custom(Box::new(Self { code, message }))
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for UUsageError {}
|
||||
|
||||
impl Display for UUsageError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
self.message.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl UCustomError for UUsageError {
|
||||
fn code(&self) -> i32 {
|
||||
self.code
|
||||
}
|
||||
|
||||
fn usage(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper type around [`std::io::Error`].
|
||||
///
|
||||
/// The messages displayed by [`UIoError`] should match the error messages displayed by GNU
|
||||
@@ -331,6 +373,10 @@ impl UIoError {
|
||||
pub fn code(&self) -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for UIoError {}
|
||||
@@ -427,6 +473,10 @@ impl UCommonError {
|
||||
pub fn code(&self) -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UCommonError> for i32 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user