mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
install: split/doc copy into smaller functions
This commit is contained in:
parent
fb72738db4
commit
2c1aa229a0
1 changed files with 153 additions and 74 deletions
|
@ -682,36 +682,23 @@ fn chown_optional_user_group(path: &Path, b: &Behavior) -> UResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy one file to a new location, changing metadata.
|
/// Perform backup before overwriting.
|
||||||
///
|
|
||||||
/// Returns a Result type with the Err variant containing the error message.
|
|
||||||
///
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
///
|
///
|
||||||
/// _from_ must exist as a non-directory.
|
/// * `to` - The destination file path.
|
||||||
/// _to_ must be a non-existent file, whose parent directory exists.
|
/// * `b` - The behavior configuration.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// If the copy system call fails, we print a verbose error and return an empty error value.
|
/// Returns an Option containing the backup path, or None if backup is not needed.
|
||||||
///
|
///
|
||||||
#[allow(clippy::cognitive_complexity)]
|
fn perform_backup(to: &Path, b: &Behavior) -> UResult<Option<PathBuf>> {
|
||||||
fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
|
||||||
if b.compare && !need_copy(from, to, b)? {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
// Declare the path here as we may need it for the verbose output below.
|
|
||||||
let mut backup_path = None;
|
|
||||||
|
|
||||||
// Perform backup, if any, before overwriting 'to'
|
|
||||||
//
|
|
||||||
// The codes actually making use of the backup process don't seem to agree
|
|
||||||
// on how best to approach the issue. (mv and ln, for example)
|
|
||||||
if to.exists() {
|
if to.exists() {
|
||||||
if b.verbose {
|
if b.verbose {
|
||||||
println!("removed {}", to.quote());
|
println!("removed {}", to.quote());
|
||||||
}
|
}
|
||||||
backup_path = backup_control::get_backup_path(b.backup_mode, to, &b.suffix);
|
let backup_path = backup_control::get_backup_path(b.backup_mode, to, &b.suffix);
|
||||||
if let Some(ref backup_path) = backup_path {
|
if let Some(ref backup_path) = backup_path {
|
||||||
// TODO!!
|
// TODO!!
|
||||||
if let Err(err) = fs::rename(to, backup_path) {
|
if let Err(err) = fs::rename(to, backup_path) {
|
||||||
|
@ -723,8 +710,24 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(backup_path)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy a file from one path to another.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `from` - The source file path.
|
||||||
|
/// * `to` - The destination file path.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns an empty Result or an error in case of failure.
|
||||||
|
///
|
||||||
|
fn copy_file(from: &Path, to: &Path) -> UResult<()> {
|
||||||
if from.as_os_str() == "/dev/null" {
|
if from.as_os_str() == "/dev/null" {
|
||||||
/* workaround a limitation of fs::copy
|
/* workaround a limitation of fs::copy
|
||||||
* https://github.com/rust-lang/rust/issues/79390
|
* https://github.com/rust-lang/rust/issues/79390
|
||||||
|
@ -737,8 +740,21 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
} else if let Err(err) = fs::copy(from, to) {
|
} else if let Err(err) = fs::copy(from, to) {
|
||||||
return Err(InstallError::InstallFailed(from.to_path_buf(), to.to_path_buf(), err).into());
|
return Err(InstallError::InstallFailed(from.to_path_buf(), to.to_path_buf(), err).into());
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
if b.strip && cfg!(not(windows)) {
|
/// Strip a file using an external program.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `to` - The destination file path.
|
||||||
|
/// * `b` - The behavior configuration.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns an empty Result or an error in case of failure.
|
||||||
|
///
|
||||||
|
fn strip_file(to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
match process::Command::new(&b.strip_program).arg(to).output() {
|
match process::Command::new(&b.strip_program).arg(to).output() {
|
||||||
Ok(o) => {
|
Ok(o) => {
|
||||||
if !o.status.success() {
|
if !o.status.success() {
|
||||||
|
@ -756,8 +772,21 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
return Err(InstallError::StripProgramFailed(e.to_string()).into());
|
return Err(InstallError::StripProgramFailed(e.to_string()).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set ownership and permissions on the destination file.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `to` - The destination file path.
|
||||||
|
/// * `b` - The behavior configuration.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns an empty Result or an error in case of failure.
|
||||||
|
///
|
||||||
|
fn set_ownership_and_permissions(to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
// Silent the warning as we want to the error message
|
// Silent the warning as we want to the error message
|
||||||
#[allow(clippy::question_mark)]
|
#[allow(clippy::question_mark)]
|
||||||
if mode::chmod(to, b.mode()).is_err() {
|
if mode::chmod(to, b.mode()).is_err() {
|
||||||
|
@ -766,7 +795,21 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
|
|
||||||
chown_optional_user_group(to, b)?;
|
chown_optional_user_group(to, b)?;
|
||||||
|
|
||||||
if b.preserve_timestamps {
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Preserve timestamps on the destination file.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `from` - The source file path.
|
||||||
|
/// * `to` - The destination file path.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns an empty Result or an error in case of failure.
|
||||||
|
///
|
||||||
|
fn preserve_timestamps(from: &Path, to: &Path) -> UResult<()> {
|
||||||
let meta = match fs::metadata(from) {
|
let meta = match fs::metadata(from) {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
||||||
|
@ -776,10 +819,46 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
let accessed_time = FileTime::from_last_access_time(&meta);
|
let accessed_time = FileTime::from_last_access_time(&meta);
|
||||||
|
|
||||||
match set_file_times(to, accessed_time, modified_time) {
|
match set_file_times(to, accessed_time, modified_time) {
|
||||||
Ok(_) => {}
|
Ok(_) => Ok(()),
|
||||||
Err(e) => show_error!("{}", e),
|
Err(e) => {
|
||||||
|
show_error!("{}", e);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy one file to a new location, changing metadata.
|
||||||
|
///
|
||||||
|
/// Returns a Result type with the Err variant containing the error message.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// _from_ must exist as a non-directory.
|
||||||
|
/// _to_ must be a non-existent file, whose parent directory exists.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If the copy system call fails, we print a verbose error and return an empty error value.
|
||||||
|
///
|
||||||
|
fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
|
if b.compare && !need_copy(from, to, b)? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// Declare the path here as we may need it for the verbose output below.
|
||||||
|
let backup_path = perform_backup(to, b)?;
|
||||||
|
|
||||||
|
copy_file(from, to)?;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
if b.strip {
|
||||||
|
strip_file(to, b)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_ownership_and_permissions(to, b)?;
|
||||||
|
|
||||||
|
if b.preserve_timestamps {
|
||||||
|
preserve_timestamps(from, to)?;
|
||||||
|
}
|
||||||
|
|
||||||
if b.verbose {
|
if b.verbose {
|
||||||
print!("{} -> {}", from.quote(), to.quote());
|
print!("{} -> {}", from.quote(), to.quote());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue