mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-31 21:17:46 +00:00
feat: expose mv externals + document for nushell
This commit is contained in:
parent
6091bafe08
commit
4a44a106a0
1 changed files with 22 additions and 37 deletions
|
@ -19,11 +19,11 @@ use std::os::unix;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use std::os::windows;
|
use std::os::windows;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use uucore::backup_control::{self, source_is_target_backup, BackupMode};
|
pub use uucore::backup_control::BackupMode;
|
||||||
|
use uucore::backup_control::{self, source_is_target_backup};
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{set_exit_code, FromIo, UError, UResult, USimpleError, UUsageError};
|
use uucore::error::{set_exit_code, FromIo, UError, UResult, USimpleError, UUsageError};
|
||||||
use uucore::fs::{are_hardlinks_or_one_way_symlink_to_same_file, are_hardlinks_to_same_file};
|
use uucore::fs::{are_hardlinks_or_one_way_symlink_to_same_file, are_hardlinks_to_same_file};
|
||||||
use uucore::libc::ENOTEMPTY;
|
|
||||||
use uucore::update_control::{self, UpdateMode};
|
use uucore::update_control::{self, UpdateMode};
|
||||||
use uucore::{format_usage, help_about, help_section, help_usage, prompt_yes, show};
|
use uucore::{format_usage, help_about, help_section, help_usage, prompt_yes, show};
|
||||||
|
|
||||||
|
@ -33,12 +33,13 @@ use fs_extra::dir::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::error::MvError;
|
use crate::error::MvError;
|
||||||
|
|
||||||
/// Options contains all the possible behaviors and flags for mv.
|
/// Options contains all the possible behaviors and flags for mv.
|
||||||
///
|
///
|
||||||
/// All options are public so that the options can be programmatically
|
/// All options are public so that the options can be programmatically
|
||||||
/// constructed by other crates, such as nushell. That means that this struct
|
/// constructed by other crates, such as nushell. That means that this struct is
|
||||||
/// is part of our public API. It should therefore not be changed without good
|
/// part of our public API. It should therefore not be changed without good reason.
|
||||||
/// reason.
|
///
|
||||||
/// The fields are documented with the arguments that determine their value.
|
/// The fields are documented with the arguments that determine their value.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
|
@ -162,7 +163,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
progress_bar: matches.get_flag(OPT_PROGRESS),
|
progress_bar: matches.get_flag(OPT_PROGRESS),
|
||||||
};
|
};
|
||||||
|
|
||||||
exec_mv(&files[..], &opts)
|
mv(&files[..], &opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> Command {
|
pub fn uu_app() -> Command {
|
||||||
|
@ -254,7 +255,7 @@ pub fn uu_app() -> Command {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn determine_overwrite_mode(matches: &ArgMatches) -> OverwriteMode {
|
fn determine_overwrite_mode(matches: &ArgMatches) -> OverwriteMode {
|
||||||
// This does not exactly match the GNU implementation:
|
// This does not exactly match the GNU implementation:
|
||||||
// The GNU mv defaults to Force, but if more than one of the
|
// The GNU mv defaults to Force, but if more than one of the
|
||||||
// overwrite options are supplied, only the last takes effect.
|
// overwrite options are supplied, only the last takes effect.
|
||||||
|
@ -358,12 +359,10 @@ fn handle_multiple_paths(paths: &[PathBuf], opts: &Options) -> UResult<()> {
|
||||||
move_files_into_dir(sources, target_dir, opts)
|
move_files_into_dir(sources, target_dir, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute mv command, moving 'source' to 'target', where
|
/// Execute the mv command. This moves 'source' to 'target', where
|
||||||
/// 'target' is a directory. If 'target' does not exist, and source is a single
|
/// 'target' is a directory. If 'target' does not exist, and source is a single
|
||||||
/// file or directory, then 'source' will be renamed to 'target'.
|
/// file or directory, then 'source' will be renamed to 'target'.
|
||||||
///
|
pub fn mv(files: &[OsString], opts: &Options) -> UResult<()> {
|
||||||
/// returns MvError | UError
|
|
||||||
pub fn exec_mv(files: &[OsString], opts: &Options) -> UResult<()> {
|
|
||||||
let paths = parse_paths(files, opts);
|
let paths = parse_paths(files, opts);
|
||||||
|
|
||||||
if let Some(ref name) = opts.target_dir {
|
if let Some(ref name) = opts.target_dir {
|
||||||
|
@ -440,31 +439,17 @@ fn move_files_into_dir(files: &[PathBuf], target_dir: &Path, opts: &Options) ->
|
||||||
match rename(sourcepath, &targetpath, opts, multi_progress.as_ref()) {
|
match rename(sourcepath, &targetpath, opts, multi_progress.as_ref()) {
|
||||||
Err(e) if e.to_string().is_empty() => set_exit_code(1),
|
Err(e) if e.to_string().is_empty() => set_exit_code(1),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e.raw_os_error() {
|
let e = e.map_err_context(|| {
|
||||||
Some(ENOTEMPTY) => {
|
format!(
|
||||||
// The error message was changed to match GNU's decision
|
"cannot move {} to {}",
|
||||||
// when an issue was filed. These will match when merged upstream.
|
sourcepath.quote(),
|
||||||
let e = e
|
targetpath.quote()
|
||||||
.map_err_context(|| format!("cannot overwrite {}", targetpath.quote()));
|
)
|
||||||
match multi_progress {
|
});
|
||||||
Some(ref pb) => pb.suspend(|| show!(e)),
|
match multi_progress {
|
||||||
None => show!(e),
|
Some(ref pb) => pb.suspend(|| show!(e)),
|
||||||
};
|
None => show!(e),
|
||||||
}
|
};
|
||||||
_ => {
|
|
||||||
let e = e.map_err_context(|| {
|
|
||||||
format!(
|
|
||||||
"cannot move {} to {}",
|
|
||||||
sourcepath.quote(),
|
|
||||||
targetpath.quote()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
match multi_progress {
|
|
||||||
Some(ref pb) => pb.suspend(|| show!(e)),
|
|
||||||
None => show!(e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
}
|
}
|
||||||
|
@ -527,7 +512,7 @@ fn rename(
|
||||||
if is_empty_dir(to) {
|
if is_empty_dir(to) {
|
||||||
fs::remove_dir(to)?;
|
fs::remove_dir(to)?;
|
||||||
} else {
|
} else {
|
||||||
return Err(io::Error::from_raw_os_error(ENOTEMPTY));
|
return Err(io::Error::new(io::ErrorKind::Other, "Directory not empty"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue