mv: implement update=[switch]

This commit is contained in:
John Shin 2023-04-27 04:48:41 -07:00
parent ecde4b6aa3
commit 0e8dd894a3

View file

@ -25,6 +25,7 @@ use std::path::{Path, PathBuf};
use uucore::backup_control::{self, BackupMode};
use uucore::display::Quotable;
use uucore::error::{set_exit_code, FromIo, UError, UResult, USimpleError, UUsageError};
use uucore::update_control::{self, UpdateMode};
use uucore::{format_usage, help_about, help_usage, prompt_yes, show};
use fs_extra::dir::{
@ -38,7 +39,7 @@ pub struct Behavior {
overwrite: OverwriteMode,
backup: BackupMode,
suffix: String,
update: bool,
update: UpdateMode,
target_dir: Option<OsString>,
no_target_dir: bool,
verbose: bool,
@ -62,14 +63,15 @@ static OPT_NO_CLOBBER: &str = "no-clobber";
static OPT_STRIP_TRAILING_SLASHES: &str = "strip-trailing-slashes";
static OPT_TARGET_DIRECTORY: &str = "target-directory";
static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory";
static OPT_UPDATE: &str = "update";
static OPT_VERBOSE: &str = "verbose";
static OPT_PROGRESS: &str = "progress";
static ARG_FILES: &str = "files";
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let mut app = uu_app().after_help(backup_control::BACKUP_CONTROL_LONG_HELP);
let mut app = uu_app()
.after_help(backup_control::BACKUP_CONTROL_LONG_HELP)
.after_help(update_control::UPDATE_CONTROL_LONG_HELP);
let matches = app.try_get_matches_from_mut(args)?;
if !matches.contains_id(OPT_TARGET_DIRECTORY)
@ -96,6 +98,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let overwrite_mode = determine_overwrite_mode(&matches);
let backup_mode = backup_control::determine_backup_mode(&matches)?;
let update_mode = update_control::determine_update_mode(&matches);
if overwrite_mode == OverwriteMode::NoClobber && backup_mode != BackupMode::NoBackup {
return Err(UUsageError::new(
@ -110,7 +113,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
overwrite: overwrite_mode,
backup: backup_mode,
suffix: backup_suffix,
update: matches.get_flag(OPT_UPDATE),
update: update_mode,
target_dir: matches
.get_one::<OsString>(OPT_TARGET_DIRECTORY)
.map(OsString::from),
@ -131,6 +134,8 @@ pub fn uu_app() -> Command {
.infer_long_args(true)
.arg(backup_control::arguments::backup())
.arg(backup_control::arguments::backup_no_args())
.arg(update_control::arguments::update())
.arg(update_control::arguments::update_no_args())
.arg(
Arg::new(OPT_FORCE)
.short('f')
@ -176,16 +181,6 @@ pub fn uu_app() -> Command {
.help("treat DEST as a normal file")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(OPT_UPDATE)
.short('u')
.long(OPT_UPDATE)
.help(
"move only when the SOURCE file is newer than the destination file \
or when the destination file is missing",
)
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(OPT_VERBOSE)
.short('v')
@ -412,7 +407,9 @@ fn rename(
let mut backup_path = None;
if to.exists() {
if b.update && b.overwrite == OverwriteMode::Interactive {
if (b.update == UpdateMode::ReplaceIfOlder || b.update == UpdateMode::ReplaceNone)
&& b.overwrite == OverwriteMode::Interactive
{
// `mv -i --update old new` when `new` exists doesn't move anything
// and exit with 0
return Ok(());
@ -433,7 +430,9 @@ fn rename(
rename_with_fallback(to, backup_path, multi_progress)?;
}
if b.update && fs::metadata(from)?.modified()? <= fs::metadata(to)?.modified()? {
if (b.update == UpdateMode::ReplaceIfOlder)
&& fs::metadata(from)?.modified()? <= fs::metadata(to)?.modified()?
{
return Ok(());
}
}