mirror of
https://github.com/uutils/coreutils
synced 2025-01-05 17:59:00 +00:00
core mv cp: update help doc for 'update' functionality
This commit is contained in:
parent
9dc84e9061
commit
2f8df653c5
3 changed files with 63 additions and 21 deletions
|
@ -279,6 +279,21 @@ static PRESERVABLE_ATTRIBUTES: &[&str] = &[
|
||||||
"all",
|
"all",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static CP_UPDATE_LONG_HELP: &str =
|
||||||
|
"Do not copy a non-directory that has an existing destination with the same or newer modification timestamp;
|
||||||
|
instead, silently skip the file without failing. If timestamps are being preserved, the comparison is to the
|
||||||
|
source timestamp truncated to the resolutions of the destination file system and of the system calls used to
|
||||||
|
update timestamps; this avoids duplicate work if several ‘cp -pu’ commands are executed with the same source
|
||||||
|
and destination. This option is ignored if the -n or --no-clobber option is also specified. Also, if
|
||||||
|
--preserve=links is also specified (like with ‘cp -au’ for example), that will take precedence; consequently,
|
||||||
|
depending on the order that files are processed from the source, newer files in the destination may be
|
||||||
|
replaced, to mirror hard links in the source. which gives more control over which existing files in the
|
||||||
|
destination are replaced, and its value can be one of the following:
|
||||||
|
|
||||||
|
all This is the default operation when an --update option is not specified, and results in all existing files in the destination being replaced.
|
||||||
|
none This is similar to the --no-clobber option, in that no files in the destination are replaced, but also skipping a file does not induce a failure.
|
||||||
|
older This is the default operation when --update is specified, and results in files being replaced if they’re older than the corresponding source file.";
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
static PRESERVABLE_ATTRIBUTES: &[&str] =
|
static PRESERVABLE_ATTRIBUTES: &[&str] =
|
||||||
&["mode", "timestamps", "context", "links", "xattr", "all"];
|
&["mode", "timestamps", "context", "links", "xattr", "all"];
|
||||||
|
@ -558,6 +573,7 @@ pub fn uu_app() -> Command {
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let matches = uu_app()
|
let matches = uu_app()
|
||||||
.after_help(backup_control::BACKUP_CONTROL_LONG_HELP)
|
.after_help(backup_control::BACKUP_CONTROL_LONG_HELP)
|
||||||
|
.after_help(CP_UPDATE_LONG_HELP)
|
||||||
.try_get_matches_from(args);
|
.try_get_matches_from(args);
|
||||||
|
|
||||||
// The error is parsed here because we do not want version or help being printed to stderr.
|
// The error is parsed here because we do not want version or help being printed to stderr.
|
||||||
|
@ -1628,22 +1644,38 @@ fn copy_file(
|
||||||
}
|
}
|
||||||
CopyMode::Update => {
|
CopyMode::Update => {
|
||||||
if dest.exists() {
|
if dest.exists() {
|
||||||
let dest_metadata = fs::symlink_metadata(dest)?;
|
match options.update {
|
||||||
|
update_control::UpdateMode::ReplaceAll => {
|
||||||
|
copy_helper(
|
||||||
|
source,
|
||||||
|
dest,
|
||||||
|
options,
|
||||||
|
context,
|
||||||
|
source_is_symlink,
|
||||||
|
source_is_fifo,
|
||||||
|
symlinked_files,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
update_control::UpdateMode::ReplaceNone => return Ok(()),
|
||||||
|
update_control::UpdateMode::ReplaceIfOlder => {
|
||||||
|
let dest_metadata = fs::symlink_metadata(dest)?;
|
||||||
|
|
||||||
let src_time = source_metadata.modified()?;
|
let src_time = source_metadata.modified()?;
|
||||||
let dest_time = dest_metadata.modified()?;
|
let dest_time = dest_metadata.modified()?;
|
||||||
if src_time <= dest_time {
|
if src_time <= dest_time {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
copy_helper(
|
copy_helper(
|
||||||
source,
|
source,
|
||||||
dest,
|
dest,
|
||||||
options,
|
options,
|
||||||
context,
|
context,
|
||||||
source_is_symlink,
|
source_is_symlink,
|
||||||
source_is_fifo,
|
source_is_fifo,
|
||||||
symlinked_files,
|
symlinked_files,
|
||||||
)?;
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
copy_helper(
|
copy_helper(
|
||||||
|
|
|
@ -67,11 +67,23 @@ static OPT_VERBOSE: &str = "verbose";
|
||||||
static OPT_PROGRESS: &str = "progress";
|
static OPT_PROGRESS: &str = "progress";
|
||||||
static ARG_FILES: &str = "files";
|
static ARG_FILES: &str = "files";
|
||||||
|
|
||||||
|
static MV_UPDATE_LONG_HELP: &str =
|
||||||
|
"Do not move a non-directory that has an existing destination with the same or newer modification timestamp;
|
||||||
|
instead, silently skip the file without failing. If the move is across file system boundaries, the comparison is
|
||||||
|
to the source timestamp truncated to the resolutions of the destination file system and of the system calls used
|
||||||
|
to update timestamps; this avoids duplicate work if several ‘mv -u’ commands are executed with the same source
|
||||||
|
and destination. This option is ignored if the -n or --no-clobber option is also specified. which gives more control
|
||||||
|
over which existing files in the destination are replaced, and its value can be one of the following:
|
||||||
|
|
||||||
|
all This is the default operation when an --update option is not specified, and results in all existing files in the destination being replaced.
|
||||||
|
none This is similar to the --no-clobber option, in that no files in the destination are replaced, but also skipping a file does not induce a failure.
|
||||||
|
older This is the default operation when --update is specified, and results in files being replaced if they’re older than the corresponding source file.";
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let mut app = uu_app()
|
let mut app = uu_app()
|
||||||
.after_help(backup_control::BACKUP_CONTROL_LONG_HELP)
|
.after_help(backup_control::BACKUP_CONTROL_LONG_HELP)
|
||||||
.after_help(update_control::UPDATE_CONTROL_LONG_HELP);
|
.after_help(MV_UPDATE_LONG_HELP);
|
||||||
let matches = app.try_get_matches_from_mut(args)?;
|
let matches = app.try_get_matches_from_mut(args)?;
|
||||||
|
|
||||||
if !matches.contains_id(OPT_TARGET_DIRECTORY)
|
if !matches.contains_id(OPT_TARGET_DIRECTORY)
|
||||||
|
|
|
@ -2,8 +2,6 @@ use clap::ArgMatches;
|
||||||
|
|
||||||
pub static UPDATE_CONTROL_VALUES: &[&str] = &["all", "none", "old", ""];
|
pub static UPDATE_CONTROL_VALUES: &[&str] = &["all", "none", "old", ""];
|
||||||
|
|
||||||
pub const UPDATE_CONTROL_LONG_HELP: &str = "VERY LONG HELP";
|
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub enum UpdateMode {
|
pub enum UpdateMode {
|
||||||
ReplaceAll,
|
ReplaceAll,
|
||||||
|
@ -20,10 +18,10 @@ pub mod arguments {
|
||||||
pub fn update() -> clap::Arg {
|
pub fn update() -> clap::Arg {
|
||||||
clap::Arg::new(OPT_UPDATE)
|
clap::Arg::new(OPT_UPDATE)
|
||||||
.long("update")
|
.long("update")
|
||||||
.help("some help")
|
.help("move only when the SOURCE file is newer than the destination file or when the destination file is missing")
|
||||||
.value_parser(["", "none", "all", "older"])
|
.value_parser(["", "none", "all", "older"])
|
||||||
.num_args(0..=1)
|
.num_args(0..=1)
|
||||||
.default_missing_value("all")
|
.default_missing_value("older")
|
||||||
.require_equals(true)
|
.require_equals(true)
|
||||||
.overrides_with("update")
|
.overrides_with("update")
|
||||||
.action(clap::ArgAction::Set)
|
.action(clap::ArgAction::Set)
|
||||||
|
@ -32,7 +30,7 @@ pub mod arguments {
|
||||||
pub fn update_no_args() -> clap::Arg {
|
pub fn update_no_args() -> clap::Arg {
|
||||||
clap::Arg::new(OPT_UPDATE_NO_ARG)
|
clap::Arg::new(OPT_UPDATE_NO_ARG)
|
||||||
.short('u')
|
.short('u')
|
||||||
.help("like ")
|
.help("like --update but does not accept an argument")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue