mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Merge branch 'master' into hostname-uresult
This commit is contained in:
commit
e253fb89db
20 changed files with 910 additions and 177 deletions
|
@ -6,6 +6,7 @@
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
|
use clap::Arg;
|
||||||
use clap::Shell;
|
use clap::Shell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::hash_map::HashMap;
|
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
|
/// Prints completions for the utility in the first parameter for the shell in the second parameter to stdout
|
||||||
fn gen_completions<T: uucore::Args>(
|
fn gen_completions<T: uucore::Args>(
|
||||||
mut args: impl Iterator<Item = OsString>,
|
args: impl Iterator<Item = OsString>,
|
||||||
util_map: UtilityMap<T>,
|
util_map: UtilityMap<T>,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
let utility = args
|
let all_utilities: Vec<_> = std::iter::once("coreutils")
|
||||||
.next()
|
.chain(util_map.keys().copied())
|
||||||
.expect("expected utility as the first parameter")
|
.collect();
|
||||||
.to_str()
|
|
||||||
.expect("utility name was not valid utf-8")
|
let matches = App::new("completion")
|
||||||
.to_owned();
|
.about("Prints completions to stdout")
|
||||||
let shell = args
|
.arg(
|
||||||
.next()
|
Arg::with_name("utility")
|
||||||
.expect("expected shell as the second parameter")
|
.possible_values(&all_utilities)
|
||||||
.to_str()
|
.required(true),
|
||||||
.expect("shell name was not valid utf-8")
|
)
|
||||||
.to_owned();
|
.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" {
|
let mut app = if utility == "coreutils" {
|
||||||
gen_coreutils_app(util_map)
|
gen_coreutils_app(util_map)
|
||||||
} else if let Some((_, app)) = util_map.get(utility.as_str()) {
|
|
||||||
app()
|
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{} is not a valid utility", utility);
|
util_map.get(utility).unwrap().1()
|
||||||
process::exit(1)
|
|
||||||
};
|
};
|
||||||
let shell: Shell = shell.parse().unwrap();
|
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());
|
app.gen_completions_to(bin_name, shell, &mut io::stdout());
|
||||||
io::stdout().flush().unwrap();
|
io::stdout().flush().unwrap();
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// 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]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) nonprint nonblank nonprinting
|
// 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)]
|
#[cfg(unix)]
|
||||||
extern crate unix_socket;
|
extern crate unix_socket;
|
||||||
#[macro_use]
|
#[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 std::io;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern crate uucore;
|
||||||
|
|
||||||
use chrono::prelude::DateTime;
|
use chrono::prelude::DateTime;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
|
use clap::ArgMatches;
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -63,6 +64,7 @@ mod options {
|
||||||
pub const TIME_STYLE: &str = "time-style";
|
pub const TIME_STYLE: &str = "time-style";
|
||||||
pub const ONE_FILE_SYSTEM: &str = "one-file-system";
|
pub const ONE_FILE_SYSTEM: &str = "one-file-system";
|
||||||
pub const DEREFERENCE: &str = "dereference";
|
pub const DEREFERENCE: &str = "dereference";
|
||||||
|
pub const INODES: &str = "inodes";
|
||||||
pub const FILE: &str = "FILE";
|
pub const FILE: &str = "FILE";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +91,7 @@ struct Options {
|
||||||
separate_dirs: bool,
|
separate_dirs: bool,
|
||||||
one_file_system: bool,
|
one_file_system: bool,
|
||||||
dereference: bool,
|
dereference: bool,
|
||||||
|
inodes: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
@ -102,6 +105,7 @@ struct Stat {
|
||||||
is_dir: bool,
|
is_dir: bool,
|
||||||
size: u64,
|
size: u64,
|
||||||
blocks: u64,
|
blocks: u64,
|
||||||
|
inodes: u64,
|
||||||
inode: Option<FileInfo>,
|
inode: Option<FileInfo>,
|
||||||
created: Option<u64>,
|
created: Option<u64>,
|
||||||
accessed: u64,
|
accessed: u64,
|
||||||
|
@ -127,6 +131,7 @@ impl Stat {
|
||||||
is_dir: metadata.is_dir(),
|
is_dir: metadata.is_dir(),
|
||||||
size: metadata.len(),
|
size: metadata.len(),
|
||||||
blocks: metadata.blocks() as u64,
|
blocks: metadata.blocks() as u64,
|
||||||
|
inodes: 1,
|
||||||
inode: Some(file_info),
|
inode: Some(file_info),
|
||||||
created: birth_u64(&metadata),
|
created: birth_u64(&metadata),
|
||||||
accessed: metadata.atime() as u64,
|
accessed: metadata.atime() as u64,
|
||||||
|
@ -144,6 +149,7 @@ impl Stat {
|
||||||
size: metadata.len(),
|
size: metadata.len(),
|
||||||
blocks: size_on_disk / 1024 * 2,
|
blocks: size_on_disk / 1024 * 2,
|
||||||
inode: file_info,
|
inode: file_info,
|
||||||
|
inodes: 1,
|
||||||
created: windows_creation_time_to_unix_time(metadata.creation_time()),
|
created: windows_creation_time_to_unix_time(metadata.creation_time()),
|
||||||
accessed: windows_time_to_unix_time(metadata.last_access_time()),
|
accessed: windows_time_to_unix_time(metadata.last_access_time()),
|
||||||
modified: windows_time_to_unix_time(metadata.last_write_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.
|
// 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
|
// XXX: this should use the impl Trait return type when it is stabilized
|
||||||
fn du(
|
fn du(
|
||||||
|
@ -307,6 +325,7 @@ fn du(
|
||||||
} else {
|
} else {
|
||||||
my_stat.size += this_stat.size;
|
my_stat.size += this_stat.size;
|
||||||
my_stat.blocks += this_stat.blocks;
|
my_stat.blocks += this_stat.blocks;
|
||||||
|
my_stat.inodes += 1;
|
||||||
if options.all {
|
if options.all {
|
||||||
stats.push(this_stat);
|
stats.push(this_stat);
|
||||||
}
|
}
|
||||||
|
@ -330,6 +349,7 @@ fn du(
|
||||||
if !options.separate_dirs && stat.path.parent().unwrap() == my_stat.path {
|
if !options.separate_dirs && stat.path.parent().unwrap() == my_stat.path {
|
||||||
my_stat.size += stat.size;
|
my_stat.size += stat.size;
|
||||||
my_stat.blocks += stat.blocks;
|
my_stat.blocks += stat.blocks;
|
||||||
|
my_stat.inodes += stat.inodes;
|
||||||
}
|
}
|
||||||
options
|
options
|
||||||
.max_depth
|
.max_depth
|
||||||
|
@ -413,6 +433,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
separate_dirs: matches.is_present(options::SEPARATE_DIRS),
|
separate_dirs: matches.is_present(options::SEPARATE_DIRS),
|
||||||
one_file_system: matches.is_present(options::ONE_FILE_SYSTEM),
|
one_file_system: matches.is_present(options::ONE_FILE_SYSTEM),
|
||||||
dereference: matches.is_present(options::DEREFERENCE),
|
dereference: matches.is_present(options::DEREFERENCE),
|
||||||
|
inodes: matches.is_present(options::INODES),
|
||||||
};
|
};
|
||||||
|
|
||||||
let files = match matches.value_of(options::FILE) {
|
let files = match matches.value_of(options::FILE) {
|
||||||
|
@ -420,6 +441,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
None => vec!["."],
|
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 block_size = u64::try_from(read_block_size(matches.value_of(options::BLOCK_SIZE))).unwrap();
|
||||||
|
|
||||||
let threshold = matches.value_of(options::THRESHOLD).map(|s| {
|
let threshold = matches.value_of(options::THRESHOLD).map(|s| {
|
||||||
|
@ -445,7 +472,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
convert_size_other
|
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") {
|
let time_format_str = match matches.value_of("time-style") {
|
||||||
Some(s) => match s {
|
Some(s) => match s {
|
||||||
|
@ -488,15 +521,7 @@ Try '{} --help' for more information.",
|
||||||
let (_, len) = iter.size_hint();
|
let (_, len) = iter.size_hint();
|
||||||
let len = len.unwrap();
|
let len = len.unwrap();
|
||||||
for (index, stat) in iter.enumerate() {
|
for (index, stat) in iter.enumerate() {
|
||||||
let size = if matches.is_present(options::APPARENT_SIZE)
|
let size = choose_size(&matches, &stat);
|
||||||
|| 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
|
|
||||||
};
|
|
||||||
|
|
||||||
if threshold.map_or(false, |threshold| threshold.should_exclude(size)) {
|
if threshold.map_or(false, |threshold| threshold.should_exclude(size)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -629,8 +654,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.help("print sizes in human readable format (e.g., 1K 234M 2G)")
|
.help("print sizes in human readable format (e.g., 1K 234M 2G)")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("inodes")
|
Arg::with_name(options::INODES)
|
||||||
.long("inodes")
|
.long(options::INODES)
|
||||||
.help(
|
.help(
|
||||||
"list inode usage information instead of block usage like --block-size=1K"
|
"list inode usage information instead of block usage like --block-size=1K"
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,6 +15,7 @@ extern crate uucore;
|
||||||
use clap::{crate_version, App, Arg, ArgMatches};
|
use clap::{crate_version, App, Arg, ArgMatches};
|
||||||
use file_diff::diff;
|
use file_diff::diff;
|
||||||
use filetime::{set_file_times, FileTime};
|
use filetime::{set_file_times, FileTime};
|
||||||
|
use uucore::backup_control::{self, BackupMode};
|
||||||
use uucore::entries::{grp2gid, usr2uid};
|
use uucore::entries::{grp2gid, usr2uid};
|
||||||
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
|
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ const DEFAULT_STRIP_PROGRAM: &str = "strip";
|
||||||
pub struct Behavior {
|
pub struct Behavior {
|
||||||
main_function: MainFunction,
|
main_function: MainFunction,
|
||||||
specified_mode: Option<u32>,
|
specified_mode: Option<u32>,
|
||||||
|
backup_mode: BackupMode,
|
||||||
suffix: String,
|
suffix: String,
|
||||||
owner: String,
|
owner: String,
|
||||||
group: 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_COMPARE: &str = "compare";
|
||||||
static OPT_BACKUP: &str = "backup";
|
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_DIRECTORY: &str = "directory";
|
||||||
static OPT_IGNORED: &str = "ignored";
|
static OPT_IGNORED: &str = "ignored";
|
||||||
static OPT_CREATE_LEADING: &str = "create-leading";
|
static OPT_CREATE_LEADING: &str = "create-leading";
|
||||||
|
@ -130,14 +132,17 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(OPT_BACKUP)
|
Arg::with_name(OPT_BACKUP)
|
||||||
.long(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")
|
.value_name("CONTROL")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
// TODO implement flag
|
// TODO implement flag
|
||||||
Arg::with_name(OPT_BACKUP_2)
|
Arg::with_name(OPT_BACKUP_NO_ARG)
|
||||||
.short("b")
|
.short("b")
|
||||||
.help("(unimplemented) like --backup but does not accept an argument")
|
.help("like --backup but does not accept an argument")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(OPT_IGNORED)
|
Arg::with_name(OPT_IGNORED)
|
||||||
|
@ -210,7 +215,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
Arg::with_name(OPT_SUFFIX)
|
Arg::with_name(OPT_SUFFIX)
|
||||||
.short("S")
|
.short("S")
|
||||||
.long(OPT_SUFFIX)
|
.long(OPT_SUFFIX)
|
||||||
.help("(unimplemented) override the usual backup suffix")
|
.help("override the usual backup suffix")
|
||||||
.value_name("SUFFIX")
|
.value_name("SUFFIX")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.min_values(1)
|
.min_values(1)
|
||||||
|
@ -265,13 +270,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
|
fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
|
||||||
if matches.is_present(OPT_BACKUP) {
|
if matches.is_present(OPT_NO_TARGET_DIRECTORY) {
|
||||||
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) {
|
|
||||||
Err("--no-target-directory, -T")
|
Err("--no-target-directory, -T")
|
||||||
} else if matches.is_present(OPT_PRESERVE_CONTEXT) {
|
} else if matches.is_present(OPT_PRESERVE_CONTEXT) {
|
||||||
Err("--preserve-context, -P")
|
Err("--preserve-context, -P")
|
||||||
|
@ -309,18 +308,16 @@ fn behavior(matches: &ArgMatches) -> Result<Behavior, i32> {
|
||||||
None
|
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());
|
let target_dir = matches.value_of(OPT_TARGET_DIRECTORY).map(|d| d.to_owned());
|
||||||
|
|
||||||
Ok(Behavior {
|
Ok(Behavior {
|
||||||
main_function,
|
main_function,
|
||||||
specified_mode,
|
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(),
|
owner: matches.value_of(OPT_OWNER).unwrap_or("").to_string(),
|
||||||
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
|
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
|
||||||
verbose: matches.is_present(OPT_VERBOSE),
|
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) {
|
if b.compare && !need_copy(from, to, b) {
|
||||||
return Ok(());
|
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" {
|
if from.to_string_lossy() == "/dev/null" {
|
||||||
/* workaround a limitation of fs::copy
|
/* workaround a limitation of fs::copy
|
||||||
|
@ -624,7 +643,11 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> Result<(), ()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.verbose {
|
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(())
|
Ok(())
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) cpio svgz webm somegroup nlink rmvb xspf
|
// spell-checker:ignore (ToDO) cpio svgz webm somegroup nlink rmvb xspf
|
||||||
|
|
||||||
|
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||||
|
#![allow(clippy::nonstandard_macro_braces)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -46,19 +49,12 @@ use unicode_width::UnicodeWidthStr;
|
||||||
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
||||||
use uucore::{fs::display_permissions, version_cmp::version_cmp};
|
use uucore::{fs::display_permissions, version_cmp::version_cmp};
|
||||||
|
|
||||||
static ABOUT: &str = "
|
|
||||||
By default, ls will list the files and contents of any directories on
|
|
||||||
the command line, expect that it will ignore files and directories
|
|
||||||
whose names start with '.'
|
|
||||||
";
|
|
||||||
static AFTER_HELP: &str = "The TIME_STYLE argument can be full-iso, long-iso, iso.
|
|
||||||
Also the TIME_STYLE environment variable sets the default style to use.";
|
|
||||||
|
|
||||||
fn get_usage() -> String {
|
fn get_usage() -> String {
|
||||||
format!("{0} [OPTION]... [FILE]...", executable!())
|
format!("{0} [OPTION]... [FILE]...", executable!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod options {
|
pub mod options {
|
||||||
|
|
||||||
pub mod format {
|
pub mod format {
|
||||||
pub static ONE_LINE: &str = "1";
|
pub static ONE_LINE: &str = "1";
|
||||||
pub static LONG: &str = "long";
|
pub static LONG: &str = "long";
|
||||||
|
@ -69,10 +65,12 @@ pub mod options {
|
||||||
pub static LONG_NO_GROUP: &str = "o";
|
pub static LONG_NO_GROUP: &str = "o";
|
||||||
pub static LONG_NUMERIC_UID_GID: &str = "numeric-uid-gid";
|
pub static LONG_NUMERIC_UID_GID: &str = "numeric-uid-gid";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod files {
|
pub mod files {
|
||||||
pub static ALL: &str = "all";
|
pub static ALL: &str = "all";
|
||||||
pub static ALMOST_ALL: &str = "almost-all";
|
pub static ALMOST_ALL: &str = "almost-all";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod sort {
|
pub mod sort {
|
||||||
pub static SIZE: &str = "S";
|
pub static SIZE: &str = "S";
|
||||||
pub static TIME: &str = "t";
|
pub static TIME: &str = "t";
|
||||||
|
@ -80,30 +78,36 @@ pub mod options {
|
||||||
pub static VERSION: &str = "v";
|
pub static VERSION: &str = "v";
|
||||||
pub static EXTENSION: &str = "X";
|
pub static EXTENSION: &str = "X";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod time {
|
pub mod time {
|
||||||
pub static ACCESS: &str = "u";
|
pub static ACCESS: &str = "u";
|
||||||
pub static CHANGE: &str = "c";
|
pub static CHANGE: &str = "c";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod size {
|
pub mod size {
|
||||||
pub static HUMAN_READABLE: &str = "human-readable";
|
pub static HUMAN_READABLE: &str = "human-readable";
|
||||||
pub static SI: &str = "si";
|
pub static SI: &str = "si";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod quoting {
|
pub mod quoting {
|
||||||
pub static ESCAPE: &str = "escape";
|
pub static ESCAPE: &str = "escape";
|
||||||
pub static LITERAL: &str = "literal";
|
pub static LITERAL: &str = "literal";
|
||||||
pub static C: &str = "quote-name";
|
pub static C: &str = "quote-name";
|
||||||
}
|
}
|
||||||
pub static QUOTING_STYLE: &str = "quoting-style";
|
|
||||||
pub mod indicator_style {
|
pub mod indicator_style {
|
||||||
pub static SLASH: &str = "p";
|
pub static SLASH: &str = "p";
|
||||||
pub static FILE_TYPE: &str = "file-type";
|
pub static FILE_TYPE: &str = "file-type";
|
||||||
pub static CLASSIFY: &str = "classify";
|
pub static CLASSIFY: &str = "classify";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod dereference {
|
pub mod dereference {
|
||||||
pub static ALL: &str = "dereference";
|
pub static ALL: &str = "dereference";
|
||||||
pub static ARGS: &str = "dereference-command-line";
|
pub static ARGS: &str = "dereference-command-line";
|
||||||
pub static DIR_ARGS: &str = "dereference-command-line-symlink-to-dir";
|
pub static DIR_ARGS: &str = "dereference-command-line-symlink-to-dir";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static QUOTING_STYLE: &str = "quoting-style";
|
||||||
pub static HIDE_CONTROL_CHARS: &str = "hide-control-chars";
|
pub static HIDE_CONTROL_CHARS: &str = "hide-control-chars";
|
||||||
pub static SHOW_CONTROL_CHARS: &str = "show-control-chars";
|
pub static SHOW_CONTROL_CHARS: &str = "show-control-chars";
|
||||||
pub static WIDTH: &str = "width";
|
pub static WIDTH: &str = "width";
|
||||||
|
@ -599,15 +603,27 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
App::new(executable!())
|
App::new(executable!())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.about(ABOUT)
|
.about(
|
||||||
|
"By default, ls will list the files and contents of any directories on \
|
||||||
|
the command line, expect that it will ignore files and directories \
|
||||||
|
whose names start with '.'.",
|
||||||
|
)
|
||||||
// Format arguments
|
// Format arguments
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::FORMAT)
|
Arg::with_name(options::FORMAT)
|
||||||
.long(options::FORMAT)
|
.long(options::FORMAT)
|
||||||
.help("Set the display format.")
|
.help("Set the display format.")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.possible_values(&["long", "verbose", "single-column", "columns", "vertical", "across", "horizontal", "commas"])
|
.possible_values(&[
|
||||||
|
"long",
|
||||||
|
"verbose",
|
||||||
|
"single-column",
|
||||||
|
"columns",
|
||||||
|
"vertical",
|
||||||
|
"across",
|
||||||
|
"horizontal",
|
||||||
|
"commas",
|
||||||
|
])
|
||||||
.hide_possible_values(true)
|
.hide_possible_values(true)
|
||||||
.require_equals(true)
|
.require_equals(true)
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
|
@ -677,41 +693,51 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
Arg::with_name(options::format::ONE_LINE)
|
Arg::with_name(options::format::ONE_LINE)
|
||||||
.short(options::format::ONE_LINE)
|
.short(options::format::ONE_LINE)
|
||||||
.help("List one file per line.")
|
.help("List one file per line.")
|
||||||
.multiple(true)
|
.multiple(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::format::LONG_NO_GROUP)
|
Arg::with_name(options::format::LONG_NO_GROUP)
|
||||||
.short(options::format::LONG_NO_GROUP)
|
.short(options::format::LONG_NO_GROUP)
|
||||||
.help("Long format without group information. Identical to --format=long with --no-group.")
|
.help(
|
||||||
.multiple(true)
|
"Long format without group information. \
|
||||||
|
Identical to --format=long with --no-group.",
|
||||||
|
)
|
||||||
|
.multiple(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::format::LONG_NO_OWNER)
|
Arg::with_name(options::format::LONG_NO_OWNER)
|
||||||
.short(options::format::LONG_NO_OWNER)
|
.short(options::format::LONG_NO_OWNER)
|
||||||
.help("Long format without owner information.")
|
.help("Long format without owner information.")
|
||||||
.multiple(true)
|
.multiple(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::format::LONG_NUMERIC_UID_GID)
|
Arg::with_name(options::format::LONG_NUMERIC_UID_GID)
|
||||||
.short("n")
|
.short("n")
|
||||||
.long(options::format::LONG_NUMERIC_UID_GID)
|
.long(options::format::LONG_NUMERIC_UID_GID)
|
||||||
.help("-l with numeric UIDs and GIDs.")
|
.help("-l with numeric UIDs and GIDs.")
|
||||||
.multiple(true)
|
.multiple(true),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Quoting style
|
// Quoting style
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::QUOTING_STYLE)
|
Arg::with_name(options::QUOTING_STYLE)
|
||||||
.long(options::QUOTING_STYLE)
|
.long(options::QUOTING_STYLE)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Set quoting style.")
|
.help("Set quoting style.")
|
||||||
.possible_values(&["literal", "shell", "shell-always", "shell-escape", "shell-escape-always", "c", "escape"])
|
.possible_values(&[
|
||||||
|
"literal",
|
||||||
|
"shell",
|
||||||
|
"shell-always",
|
||||||
|
"shell-escape",
|
||||||
|
"shell-escape-always",
|
||||||
|
"c",
|
||||||
|
"escape",
|
||||||
|
])
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
options::QUOTING_STYLE,
|
options::QUOTING_STYLE,
|
||||||
options::quoting::LITERAL,
|
options::quoting::LITERAL,
|
||||||
options::quoting::ESCAPE,
|
options::quoting::ESCAPE,
|
||||||
options::quoting::C,
|
options::quoting::C,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::quoting::LITERAL)
|
Arg::with_name(options::quoting::LITERAL)
|
||||||
|
@ -723,7 +749,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::quoting::LITERAL,
|
options::quoting::LITERAL,
|
||||||
options::quoting::ESCAPE,
|
options::quoting::ESCAPE,
|
||||||
options::quoting::C,
|
options::quoting::C,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::quoting::ESCAPE)
|
Arg::with_name(options::quoting::ESCAPE)
|
||||||
|
@ -735,7 +761,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::quoting::LITERAL,
|
options::quoting::LITERAL,
|
||||||
options::quoting::ESCAPE,
|
options::quoting::ESCAPE,
|
||||||
options::quoting::C,
|
options::quoting::C,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::quoting::C)
|
Arg::with_name(options::quoting::C)
|
||||||
|
@ -747,76 +773,63 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::quoting::LITERAL,
|
options::quoting::LITERAL,
|
||||||
options::quoting::ESCAPE,
|
options::quoting::ESCAPE,
|
||||||
options::quoting::C,
|
options::quoting::C,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Control characters
|
// Control characters
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::HIDE_CONTROL_CHARS)
|
Arg::with_name(options::HIDE_CONTROL_CHARS)
|
||||||
.short("q")
|
.short("q")
|
||||||
.long(options::HIDE_CONTROL_CHARS)
|
.long(options::HIDE_CONTROL_CHARS)
|
||||||
.help("Replace control characters with '?' if they are not escaped.")
|
.help("Replace control characters with '?' if they are not escaped.")
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[options::HIDE_CONTROL_CHARS, options::SHOW_CONTROL_CHARS]),
|
||||||
options::HIDE_CONTROL_CHARS,
|
|
||||||
options::SHOW_CONTROL_CHARS,
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::SHOW_CONTROL_CHARS)
|
Arg::with_name(options::SHOW_CONTROL_CHARS)
|
||||||
.long(options::SHOW_CONTROL_CHARS)
|
.long(options::SHOW_CONTROL_CHARS)
|
||||||
.help("Show control characters 'as is' if they are not escaped.")
|
.help("Show control characters 'as is' if they are not escaped.")
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[options::HIDE_CONTROL_CHARS, options::SHOW_CONTROL_CHARS]),
|
||||||
options::HIDE_CONTROL_CHARS,
|
|
||||||
options::SHOW_CONTROL_CHARS,
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Time arguments
|
// Time arguments
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::TIME)
|
Arg::with_name(options::TIME)
|
||||||
.long(options::TIME)
|
.long(options::TIME)
|
||||||
.help("Show time in <field>:\n\
|
.help(
|
||||||
|
"Show time in <field>:\n\
|
||||||
\taccess time (-u): atime, access, use;\n\
|
\taccess time (-u): atime, access, use;\n\
|
||||||
\tchange time (-t): ctime, status.\n\
|
\tchange time (-t): ctime, status.\n\
|
||||||
\tbirth time: birth, creation;")
|
\tbirth time: birth, creation;",
|
||||||
|
)
|
||||||
.value_name("field")
|
.value_name("field")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.possible_values(&["atime", "access", "use", "ctime", "status", "birth", "creation"])
|
.possible_values(&[
|
||||||
|
"atime", "access", "use", "ctime", "status", "birth", "creation",
|
||||||
|
])
|
||||||
.hide_possible_values(true)
|
.hide_possible_values(true)
|
||||||
.require_equals(true)
|
.require_equals(true)
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE]),
|
||||||
options::TIME,
|
|
||||||
options::time::ACCESS,
|
|
||||||
options::time::CHANGE,
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::time::CHANGE)
|
Arg::with_name(options::time::CHANGE)
|
||||||
.short(options::time::CHANGE)
|
.short(options::time::CHANGE)
|
||||||
.help("If the long listing format (e.g., -l, -o) is being used, print the status \
|
.help(
|
||||||
|
"If the long listing format (e.g., -l, -o) is being used, print the status \
|
||||||
change time (the 'ctime' in the inode) instead of the modification time. When \
|
change time (the 'ctime' in the inode) instead of the modification time. When \
|
||||||
explicitly sorting by time (--sort=time or -t) or when not using a long listing \
|
explicitly sorting by time (--sort=time or -t) or when not using a long listing \
|
||||||
format, sort according to the status change time.")
|
format, sort according to the status change time.",
|
||||||
.overrides_with_all(&[
|
)
|
||||||
options::TIME,
|
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE]),
|
||||||
options::time::ACCESS,
|
|
||||||
options::time::CHANGE,
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::time::ACCESS)
|
Arg::with_name(options::time::ACCESS)
|
||||||
.short(options::time::ACCESS)
|
.short(options::time::ACCESS)
|
||||||
.help("If the long listing format (e.g., -l, -o) is being used, print the status \
|
.help(
|
||||||
|
"If the long listing format (e.g., -l, -o) is being used, print the status \
|
||||||
access time instead of the modification time. When explicitly sorting by time \
|
access time instead of the modification time. When explicitly sorting by time \
|
||||||
(--sort=time or -t) or when not using a long listing format, sort according to the \
|
(--sort=time or -t) or when not using a long listing format, sort according to the \
|
||||||
access time.")
|
access time.",
|
||||||
.overrides_with_all(&[
|
)
|
||||||
options::TIME,
|
.overrides_with_all(&[options::TIME, options::time::ACCESS, options::time::CHANGE]),
|
||||||
options::time::ACCESS,
|
|
||||||
options::time::CHANGE,
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hide and ignore
|
// Hide and ignore
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::HIDE)
|
Arg::with_name(options::HIDE)
|
||||||
|
@ -824,7 +837,9 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.value_name("PATTERN")
|
.value_name("PATTERN")
|
||||||
.help("do not list implied entries matching shell PATTERN (overridden by -a or -A)")
|
.help(
|
||||||
|
"do not list implied entries matching shell PATTERN (overridden by -a or -A)",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::IGNORE)
|
Arg::with_name(options::IGNORE)
|
||||||
|
@ -833,7 +848,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.value_name("PATTERN")
|
.value_name("PATTERN")
|
||||||
.help("do not list implied entries matching shell PATTERN")
|
.help("do not list implied entries matching shell PATTERN"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::IGNORE_BACKUPS)
|
Arg::with_name(options::IGNORE_BACKUPS)
|
||||||
|
@ -841,7 +856,6 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.long(options::IGNORE_BACKUPS)
|
.long(options::IGNORE_BACKUPS)
|
||||||
.help("Ignore entries which end with ~."),
|
.help("Ignore entries which end with ~."),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sort arguments
|
// Sort arguments
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::SORT)
|
Arg::with_name(options::SORT)
|
||||||
|
@ -858,7 +872,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::sort::NONE,
|
options::sort::NONE,
|
||||||
options::sort::VERSION,
|
options::sort::VERSION,
|
||||||
options::sort::EXTENSION,
|
options::sort::EXTENSION,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::sort::SIZE)
|
Arg::with_name(options::sort::SIZE)
|
||||||
|
@ -871,7 +885,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::sort::NONE,
|
options::sort::NONE,
|
||||||
options::sort::VERSION,
|
options::sort::VERSION,
|
||||||
options::sort::EXTENSION,
|
options::sort::EXTENSION,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::sort::TIME)
|
Arg::with_name(options::sort::TIME)
|
||||||
|
@ -884,7 +898,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::sort::NONE,
|
options::sort::NONE,
|
||||||
options::sort::VERSION,
|
options::sort::VERSION,
|
||||||
options::sort::EXTENSION,
|
options::sort::EXTENSION,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::sort::VERSION)
|
Arg::with_name(options::sort::VERSION)
|
||||||
|
@ -897,7 +911,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::sort::NONE,
|
options::sort::NONE,
|
||||||
options::sort::VERSION,
|
options::sort::VERSION,
|
||||||
options::sort::EXTENSION,
|
options::sort::EXTENSION,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::sort::EXTENSION)
|
Arg::with_name(options::sort::EXTENSION)
|
||||||
|
@ -910,14 +924,16 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::sort::NONE,
|
options::sort::NONE,
|
||||||
options::sort::VERSION,
|
options::sort::VERSION,
|
||||||
options::sort::EXTENSION,
|
options::sort::EXTENSION,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::sort::NONE)
|
Arg::with_name(options::sort::NONE)
|
||||||
.short(options::sort::NONE)
|
.short(options::sort::NONE)
|
||||||
.help("Do not sort; list the files in whatever order they are stored in the \
|
.help(
|
||||||
directory. This is especially useful when listing very large directories, \
|
"Do not sort; list the files in whatever order they are stored in the \
|
||||||
since not doing any sorting can be noticeably faster.")
|
directory. This is especially useful when listing very large directories, \
|
||||||
|
since not doing any sorting can be noticeably faster.",
|
||||||
|
)
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
options::SORT,
|
options::SORT,
|
||||||
options::sort::SIZE,
|
options::sort::SIZE,
|
||||||
|
@ -925,9 +941,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::sort::NONE,
|
options::sort::NONE,
|
||||||
options::sort::VERSION,
|
options::sort::VERSION,
|
||||||
options::sort::EXTENSION,
|
options::sort::EXTENSION,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dereferencing
|
// Dereferencing
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::dereference::ALL)
|
Arg::with_name(options::dereference::ALL)
|
||||||
|
@ -941,48 +956,43 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::dereference::ALL,
|
options::dereference::ALL,
|
||||||
options::dereference::DIR_ARGS,
|
options::dereference::DIR_ARGS,
|
||||||
options::dereference::ARGS,
|
options::dereference::ARGS,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::dereference::DIR_ARGS)
|
Arg::with_name(options::dereference::DIR_ARGS)
|
||||||
.long(options::dereference::DIR_ARGS)
|
.long(options::dereference::DIR_ARGS)
|
||||||
.help(
|
.help(
|
||||||
"Do not dereference symlinks except when they link to directories and are \
|
"Do not dereference symlinks except when they link to directories and are \
|
||||||
given as command line arguments.",
|
given as command line arguments.",
|
||||||
)
|
)
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
options::dereference::ALL,
|
options::dereference::ALL,
|
||||||
options::dereference::DIR_ARGS,
|
options::dereference::DIR_ARGS,
|
||||||
options::dereference::ARGS,
|
options::dereference::ARGS,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::dereference::ARGS)
|
Arg::with_name(options::dereference::ARGS)
|
||||||
.short("H")
|
.short("H")
|
||||||
.long(options::dereference::ARGS)
|
.long(options::dereference::ARGS)
|
||||||
.help(
|
.help("Do not dereference symlinks except when given as command line arguments.")
|
||||||
"Do not dereference symlinks except when given as command line arguments.",
|
|
||||||
)
|
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
options::dereference::ALL,
|
options::dereference::ALL,
|
||||||
options::dereference::DIR_ARGS,
|
options::dereference::DIR_ARGS,
|
||||||
options::dereference::ARGS,
|
options::dereference::ARGS,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Long format options
|
// Long format options
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::NO_GROUP)
|
Arg::with_name(options::NO_GROUP)
|
||||||
.long(options::NO_GROUP)
|
.long(options::NO_GROUP)
|
||||||
.short("-G")
|
.short("-G")
|
||||||
.help("Do not show group in long format.")
|
.help("Do not show group in long format."),
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name(options::AUTHOR)
|
|
||||||
.long(options::AUTHOR)
|
|
||||||
.help("Show author in long format. On the supported platforms, the author \
|
|
||||||
always matches the file owner.")
|
|
||||||
)
|
)
|
||||||
|
.arg(Arg::with_name(options::AUTHOR).long(options::AUTHOR).help(
|
||||||
|
"Show author in long format. \
|
||||||
|
On the supported platforms, the author always matches the file owner.",
|
||||||
|
))
|
||||||
// Other Flags
|
// Other Flags
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::files::ALL)
|
Arg::with_name(options::files::ALL)
|
||||||
|
@ -995,9 +1005,9 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.short("A")
|
.short("A")
|
||||||
.long(options::files::ALMOST_ALL)
|
.long(options::files::ALMOST_ALL)
|
||||||
.help(
|
.help(
|
||||||
"In a directory, do not ignore all file names that start with '.', only ignore \
|
"In a directory, do not ignore all file names that start with '.', \
|
||||||
'.' and '..'.",
|
only ignore '.' and '..'.",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::DIRECTORY)
|
Arg::with_name(options::DIRECTORY)
|
||||||
|
@ -1020,7 +1030,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::size::SI)
|
Arg::with_name(options::size::SI)
|
||||||
.long(options::size::SI)
|
.long(options::size::SI)
|
||||||
.help("Print human readable file sizes using powers of 1000 instead of 1024.")
|
.help("Print human readable file sizes using powers of 1000 instead of 1024."),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::INODE)
|
Arg::with_name(options::INODE)
|
||||||
|
@ -1032,9 +1042,11 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
Arg::with_name(options::REVERSE)
|
Arg::with_name(options::REVERSE)
|
||||||
.short("r")
|
.short("r")
|
||||||
.long(options::REVERSE)
|
.long(options::REVERSE)
|
||||||
.help("Reverse whatever the sorting method is--e.g., list files in reverse \
|
.help(
|
||||||
|
"Reverse whatever the sorting method is e.g., list files in reverse \
|
||||||
alphabetical order, youngest first, smallest first, or whatever.",
|
alphabetical order, youngest first, smallest first, or whatever.",
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::RECURSIVE)
|
Arg::with_name(options::RECURSIVE)
|
||||||
.short("R")
|
.short("R")
|
||||||
|
@ -1047,7 +1059,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.short("w")
|
.short("w")
|
||||||
.help("Assume that the terminal is COLS columns wide.")
|
.help("Assume that the terminal is COLS columns wide.")
|
||||||
.value_name("COLS")
|
.value_name("COLS")
|
||||||
.takes_value(true)
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::COLOR)
|
Arg::with_name(options::COLOR)
|
||||||
|
@ -1060,8 +1072,10 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::INDICATOR_STYLE)
|
Arg::with_name(options::INDICATOR_STYLE)
|
||||||
.long(options::INDICATOR_STYLE)
|
.long(options::INDICATOR_STYLE)
|
||||||
.help(" append indicator with style WORD to entry names: none (default), slash\
|
.help(
|
||||||
(-p), file-type (--file-type), classify (-F)")
|
"Append indicator with style WORD to entry names: \
|
||||||
|
none (default), slash (-p), file-type (--file-type), classify (-F)",
|
||||||
|
)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.possible_values(&["none", "slash", "file-type", "classify"])
|
.possible_values(&["none", "slash", "file-type", "classify"])
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
|
@ -1069,21 +1083,24 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::indicator_style::SLASH,
|
options::indicator_style::SLASH,
|
||||||
options::indicator_style::CLASSIFY,
|
options::indicator_style::CLASSIFY,
|
||||||
options::INDICATOR_STYLE,
|
options::INDICATOR_STYLE,
|
||||||
]))
|
]),
|
||||||
.arg(
|
)
|
||||||
|
.arg(
|
||||||
Arg::with_name(options::indicator_style::CLASSIFY)
|
Arg::with_name(options::indicator_style::CLASSIFY)
|
||||||
.short("F")
|
.short("F")
|
||||||
.long(options::indicator_style::CLASSIFY)
|
.long(options::indicator_style::CLASSIFY)
|
||||||
.help("Append a character to each file name indicating the file type. Also, for \
|
.help(
|
||||||
regular files that are executable, append '*'. The file type indicators are \
|
"Append a character to each file name indicating the file type. Also, for \
|
||||||
'/' for directories, '@' for symbolic links, '|' for FIFOs, '=' for sockets, \
|
regular files that are executable, append '*'. The file type indicators are \
|
||||||
'>' for doors, and nothing for regular files.")
|
'/' for directories, '@' for symbolic links, '|' for FIFOs, '=' for sockets, \
|
||||||
|
'>' for doors, and nothing for regular files.",
|
||||||
|
)
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
options::indicator_style::FILE_TYPE,
|
options::indicator_style::FILE_TYPE,
|
||||||
options::indicator_style::SLASH,
|
options::indicator_style::SLASH,
|
||||||
options::indicator_style::CLASSIFY,
|
options::indicator_style::CLASSIFY,
|
||||||
options::INDICATOR_STYLE,
|
options::INDICATOR_STYLE,
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::indicator_style::FILE_TYPE)
|
Arg::with_name(options::indicator_style::FILE_TYPE)
|
||||||
|
@ -1094,18 +1111,19 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
options::indicator_style::SLASH,
|
options::indicator_style::SLASH,
|
||||||
options::indicator_style::CLASSIFY,
|
options::indicator_style::CLASSIFY,
|
||||||
options::INDICATOR_STYLE,
|
options::INDICATOR_STYLE,
|
||||||
]))
|
]),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::indicator_style::SLASH)
|
Arg::with_name(options::indicator_style::SLASH)
|
||||||
.short(options::indicator_style::SLASH)
|
.short(options::indicator_style::SLASH)
|
||||||
.help("Append / indicator to directories."
|
.help("Append / indicator to directories.")
|
||||||
)
|
|
||||||
.overrides_with_all(&[
|
.overrides_with_all(&[
|
||||||
options::indicator_style::FILE_TYPE,
|
options::indicator_style::FILE_TYPE,
|
||||||
options::indicator_style::SLASH,
|
options::indicator_style::SLASH,
|
||||||
options::indicator_style::CLASSIFY,
|
options::indicator_style::CLASSIFY,
|
||||||
options::INDICATOR_STYLE,
|
options::INDICATOR_STYLE,
|
||||||
]))
|
]),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
//This still needs support for posix-*, +FORMAT
|
//This still needs support for posix-*, +FORMAT
|
||||||
Arg::with_name(options::TIME_STYLE)
|
Arg::with_name(options::TIME_STYLE)
|
||||||
|
@ -1113,27 +1131,25 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.help("time/date format with -l; see TIME_STYLE below")
|
.help("time/date format with -l; see TIME_STYLE below")
|
||||||
.value_name("TIME_STYLE")
|
.value_name("TIME_STYLE")
|
||||||
.env("TIME_STYLE")
|
.env("TIME_STYLE")
|
||||||
.possible_values(&[
|
.possible_values(&["full-iso", "long-iso", "iso", "locale"])
|
||||||
"full-iso",
|
.overrides_with_all(&[options::TIME_STYLE]),
|
||||||
"long-iso",
|
|
||||||
"iso",
|
|
||||||
"locale",
|
|
||||||
])
|
|
||||||
.overrides_with_all(&[
|
|
||||||
options::TIME_STYLE
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::FULL_TIME)
|
Arg::with_name(options::FULL_TIME)
|
||||||
.long(options::FULL_TIME)
|
.long(options::FULL_TIME)
|
||||||
.overrides_with(options::FULL_TIME)
|
.overrides_with(options::FULL_TIME)
|
||||||
.help("like -l --time-style=full-iso")
|
.help("like -l --time-style=full-iso"),
|
||||||
|
)
|
||||||
|
// Positional arguments
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::PATHS)
|
||||||
|
.multiple(true)
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.after_help(
|
||||||
|
"The TIME_STYLE argument can be full-iso, long-iso, iso. \
|
||||||
|
Also the TIME_STYLE environment variable sets the default style to use.",
|
||||||
)
|
)
|
||||||
|
|
||||||
// Positional arguments
|
|
||||||
.arg(Arg::with_name(options::PATHS).multiple(true).takes_value(true))
|
|
||||||
|
|
||||||
.after_help(AFTER_HELP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a Path along with it's associated data
|
/// Represents a Path along with it's associated data
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * 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]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
// spell-checker:ignore (paths) GPGHome
|
// spell-checker:ignore (paths) GPGHome
|
||||||
|
|
||||||
|
// clippy bug https://github.com/rust-lang/rust-clippy/issues/7422
|
||||||
|
#![allow(clippy::nonstandard_macro_braces)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
|
|
|
@ -349,12 +349,10 @@ impl<'a> Pager<'a> {
|
||||||
let status = format!("--More--({})", status_inner);
|
let status = format!("--More--({})", status_inner);
|
||||||
|
|
||||||
let banner = match (self.silent, wrong_key) {
|
let banner = match (self.silent, wrong_key) {
|
||||||
(true, Some(key)) => {
|
(true, Some(key)) => format!(
|
||||||
format!(
|
"{} [Unknown key: '{}'. Press 'h' for instructions. (unimplemented)]",
|
||||||
"{} [Unknown key: '{}'. Press 'h' for instructions. (unimplemented)]",
|
status, key
|
||||||
status, key
|
),
|
||||||
)
|
|
||||||
}
|
|
||||||
(true, None) => format!("{}[Press space to continue, 'q' to quit.]", status),
|
(true, None) => format!("{}[Press space to continue, 'q' to quit.]", status),
|
||||||
(false, Some(_)) => format!("{}{}", status, BELL),
|
(false, Some(_)) => format!("{}{}", status, BELL),
|
||||||
(false, None) => status,
|
(false, None) => status,
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm
|
// 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;
|
pub extern crate filetime;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
// *
|
// *
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * 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]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
// spell-checker:ignore (strings) ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
// 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;
|
extern crate data_encoding;
|
||||||
|
|
||||||
use self::data_encoding::{DecodeError, BASE32, BASE64};
|
use self::data_encoding::{DecodeError, BASE32, BASE64};
|
||||||
|
|
|
@ -27,6 +27,9 @@ macro_rules! show(
|
||||||
let e = $err;
|
let e = $err;
|
||||||
uucore::error::set_exit_code(e.code());
|
uucore::error::set_exit_code(e.code());
|
||||||
eprintln!("{}: {}", executable!(), e);
|
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 {
|
pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>) -> BackupMode {
|
||||||
if backup_opt_exists {
|
if backup_opt_exists {
|
||||||
match backup_opt.map(String::from) {
|
match backup_opt.map(String::from) {
|
||||||
|
|
|
@ -144,6 +144,13 @@ impl UError {
|
||||||
UError::Custom(e) => e.code(),
|
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 {
|
impl From<UCommonError> for UError {
|
||||||
|
@ -220,6 +227,10 @@ pub trait UCustomError: Error {
|
||||||
fn code(&self) -> i32 {
|
fn code(&self) -> i32 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Box<dyn UCustomError>> for i32 {
|
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`].
|
/// Wrapper type around [`std::io::Error`].
|
||||||
///
|
///
|
||||||
/// The messages displayed by [`UIoError`] should match the error messages displayed by GNU
|
/// The messages displayed by [`UIoError`] should match the error messages displayed by GNU
|
||||||
|
@ -331,6 +373,10 @@ impl UIoError {
|
||||||
pub fn code(&self) -> i32 {
|
pub fn code(&self) -> i32 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn usage(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for UIoError {}
|
impl Error for UIoError {}
|
||||||
|
@ -427,6 +473,10 @@ impl UCommonError {
|
||||||
pub fn code(&self) -> i32 {
|
pub fn code(&self) -> i32 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn usage(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<UCommonError> for i32 {
|
impl From<UCommonError> for i32 {
|
||||||
|
|
|
@ -103,6 +103,9 @@ pub fn gen_uumain(_args: TokenStream, stream: TokenStream) -> TokenStream {
|
||||||
if s != "" {
|
if s != "" {
|
||||||
show_error!("{}", s);
|
show_error!("{}", s);
|
||||||
}
|
}
|
||||||
|
if e.usage() {
|
||||||
|
eprintln!("Try '{} --help' for more information.", executable!());
|
||||||
|
}
|
||||||
e.code()
|
e.code()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,6 +292,77 @@ fn _du_dereference(s: &str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_du_inodes_basic() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let result = scene.ucmd().arg("--inodes").succeeds();
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let result_reference = scene.cmd("du").arg("--inodes").run();
|
||||||
|
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
_du_inodes_basic(result.stdout_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn _du_inodes_basic(s: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
"2\t.\\subdir\\deeper\\deeper_dir
|
||||||
|
4\t.\\subdir\\deeper
|
||||||
|
3\t.\\subdir\\links
|
||||||
|
8\t.\\subdir
|
||||||
|
11\t.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn _du_inodes_basic(s: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
"2\t./subdir/deeper/deeper_dir
|
||||||
|
4\t./subdir/deeper
|
||||||
|
3\t./subdir/links
|
||||||
|
8\t./subdir
|
||||||
|
11\t.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_du_inodes() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--summarize")
|
||||||
|
.arg("--inodes")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("11\t.\n");
|
||||||
|
|
||||||
|
let result = scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--separate-dirs")
|
||||||
|
.arg("--inodes")
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
result.stdout_contains("3\t.\\subdir\\links\n");
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
result.stdout_contains("3\t./subdir/links\n");
|
||||||
|
result.stdout_contains("3\t.\n");
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let result_reference = scene.cmd("du").arg("--separate-dirs").arg("--inodes").run();
|
||||||
|
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_du_h_flag_empty_file() {
|
fn test_du_h_flag_empty_file() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
@ -419,3 +490,96 @@ fn test_du_threshold() {
|
||||||
.stdout_does_not_contain("links")
|
.stdout_does_not_contain("links")
|
||||||
.stdout_contains("deeper_dir");
|
.stdout_contains("deeper_dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_du_apparent_size() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let result = scene.ucmd().arg("--apparent-size").succeeds();
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let result_reference = scene.cmd("du").arg("--apparent-size").run();
|
||||||
|
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
_du_apparent_size(result.stdout_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn _du_apparent_size(s: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
"1\t.\\subdir\\deeper\\deeper_dir
|
||||||
|
1\t.\\subdir\\deeper
|
||||||
|
6\t.\\subdir\\links
|
||||||
|
6\t.\\subdir
|
||||||
|
6\t.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[cfg(target_vendor = "apple")]
|
||||||
|
fn _du_apparent_size(s: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
"1\t./subdir/deeper/deeper_dir
|
||||||
|
1\t./subdir/deeper
|
||||||
|
6\t./subdir/links
|
||||||
|
6\t./subdir
|
||||||
|
6\t.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "freebsd")]
|
||||||
|
fn _du_apparent_size(s: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
"1\t./subdir/deeper/deeper_dir
|
||||||
|
2\t./subdir/deeper
|
||||||
|
6\t./subdir/links
|
||||||
|
8\t./subdir
|
||||||
|
8\t.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[cfg(all(
|
||||||
|
not(target_vendor = "apple"),
|
||||||
|
not(target_os = "windows"),
|
||||||
|
not(target_os = "freebsd")
|
||||||
|
))]
|
||||||
|
fn _du_apparent_size(s: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
"5\t./subdir/deeper/deeper_dir
|
||||||
|
9\t./subdir/deeper
|
||||||
|
10\t./subdir/links
|
||||||
|
22\t./subdir
|
||||||
|
26\t.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_du_bytes() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let result = scene.ucmd().arg("--bytes").succeeds();
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let result_reference = scene.cmd("du").arg("--bytes").run();
|
||||||
|
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
result.stdout_contains("5145\t.\\subdir\n");
|
||||||
|
#[cfg(target_vendor = "apple")]
|
||||||
|
result.stdout_contains("5625\t./subdir\n");
|
||||||
|
#[cfg(target_os = "freebsd")]
|
||||||
|
result.stdout_contains("7193\t./subdir\n");
|
||||||
|
#[cfg(all(
|
||||||
|
not(target_vendor = "apple"),
|
||||||
|
not(target_os = "windows"),
|
||||||
|
not(target_os = "freebsd")
|
||||||
|
))]
|
||||||
|
result.stdout_contains("21529\t./subdir\n");
|
||||||
|
}
|
||||||
|
|
|
@ -250,6 +250,28 @@ hello
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bad_utf8() {
|
||||||
|
let bytes: &[u8] = b"\xfc\x80\x80\x80\x80\xaf";
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-c", "6"])
|
||||||
|
.pipe_in(bytes)
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_bytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bad_utf8_lines() {
|
||||||
|
let input: &[u8] =
|
||||||
|
b"\xfc\x80\x80\x80\x80\xaf\nb\xfc\x80\x80\x80\x80\xaf\nb\xfc\x80\x80\x80\x80\xaf";
|
||||||
|
let output = b"\xfc\x80\x80\x80\x80\xaf\nb\xfc\x80\x80\x80\x80\xaf\n";
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-n", "2"])
|
||||||
|
.pipe_in(input)
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_bytes(output);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_head_invalid_num() {
|
fn test_head_invalid_num() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
|
|
@ -696,3 +696,388 @@ fn test_install_dir() {
|
||||||
assert!(at.file_exists(&format!("{}/{}", dir, file1)));
|
assert!(at.file_exists(&format!("{}/{}", dir, file1)));
|
||||||
assert!(at.file_exists(&format!("{}/{}", dir, file2)));
|
assert!(at.file_exists(&format!("{}/{}", dir, file2)));
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// test backup functionality
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_short_no_args_files() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_simple_backup_file_a";
|
||||||
|
let file_b = "test_install_simple_backup_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-b")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_short_no_args_file_to_dir() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file = "test_install_simple_backup_file_a";
|
||||||
|
let dest_dir = "test_install_dest/";
|
||||||
|
let expect = format!("{}{}", dest_dir, file);
|
||||||
|
|
||||||
|
at.touch(file);
|
||||||
|
at.mkdir(dest_dir);
|
||||||
|
at.touch(&expect);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-b")
|
||||||
|
.arg(file)
|
||||||
|
.arg(dest_dir)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file));
|
||||||
|
assert!(at.file_exists(&expect));
|
||||||
|
assert!(at.file_exists(&format!("{}~", expect)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Long --backup option is tested separately as it requires a slightly different
|
||||||
|
// handling than '-b' does.
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_long_no_args_files() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_simple_backup_file_a";
|
||||||
|
let file_b = "test_install_simple_backup_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_long_no_args_file_to_dir() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file = "test_install_simple_backup_file_a";
|
||||||
|
let dest_dir = "test_install_dest/";
|
||||||
|
let expect = format!("{}{}", dest_dir, file);
|
||||||
|
|
||||||
|
at.touch(file);
|
||||||
|
at.mkdir(dest_dir);
|
||||||
|
at.touch(&expect);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup")
|
||||||
|
.arg(file)
|
||||||
|
.arg(dest_dir)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file));
|
||||||
|
assert!(at.file_exists(&expect));
|
||||||
|
assert!(at.file_exists(&format!("{}~", expect)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_short_custom_suffix() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_custom_suffix_file_a";
|
||||||
|
let file_b = "test_install_backup_custom_suffix_file_b";
|
||||||
|
let suffix = "super-suffix-of-the-century";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-b")
|
||||||
|
.arg(format!("--suffix={}", suffix))
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}{}", file_b, suffix)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_custom_suffix_via_env() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_custom_suffix_file_a";
|
||||||
|
let file_b = "test_install_backup_custom_suffix_file_b";
|
||||||
|
let suffix = "super-suffix-of-the-century";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("-b")
|
||||||
|
.env("SIMPLE_BACKUP_SUFFIX", suffix)
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}{}", file_b, suffix)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_numbered_with_t() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=t")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}.~1~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_numbered_with_numbered() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=numbered")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}.~1~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_existing() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=existing")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_nil() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=nil")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_numbered_if_existing_backup_existing() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
let file_b_backup = "test_install_backup_numbering_file_b.~1~";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
at.touch(file_b_backup);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=existing")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(file_b_backup));
|
||||||
|
assert!(at.file_exists(&*format!("{}.~2~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_numbered_if_existing_backup_nil() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
let file_b_backup = "test_install_backup_numbering_file_b.~1~";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
at.touch(file_b_backup);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=nil")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(file_b_backup));
|
||||||
|
assert!(at.file_exists(&*format!("{}.~2~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_simple() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=simple")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_never() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=never")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_none() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=none")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(!at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_backup_off() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file_a = "test_install_backup_numbering_file_a";
|
||||||
|
let file_b = "test_install_backup_numbering_file_b";
|
||||||
|
|
||||||
|
at.touch(file_a);
|
||||||
|
at.touch(file_b);
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg("--backup=off")
|
||||||
|
.arg(file_a)
|
||||||
|
.arg(file_b)
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
assert!(at.file_exists(file_a));
|
||||||
|
assert!(at.file_exists(file_b));
|
||||||
|
assert!(!at.file_exists(&format!("{}~", file_b)));
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue