Merge pull request #1812 from konomith/feature/preserve_timestamps_#1758

install: Implement --preserve-timestamps (-p)
This commit is contained in:
Sylvestre Ledru 2021-03-17 22:02:54 +01:00 committed by GitHub
commit 44a7adc9a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 4 deletions

1
Cargo.lock generated
View file

@ -1687,6 +1687,7 @@ name = "uu_install"
version = "0.0.4"
dependencies = [
"clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.85 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"uucore 0.0.7",

View file

@ -19,6 +19,7 @@ path = "src/install.rs"
[dependencies]
clap = "2.33"
filetime = "0.2"
libc = ">= 0.2"
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["mode", "perms", "entries"] }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -13,6 +13,7 @@ mod mode;
extern crate uucore;
use clap::{App, Arg, ArgMatches};
use filetime::{set_file_times, FileTime};
use uucore::entries::{grp2gid, usr2uid};
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
@ -32,6 +33,7 @@ pub struct Behavior {
owner: String,
group: String,
verbose: bool,
preserve_timestamps: bool,
}
#[derive(Clone, Eq, PartialEq)]
@ -154,11 +156,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true)
)
.arg(
// TODO implement flag
Arg::with_name(OPT_PRESERVE_TIMESTAMPS)
.short("p")
.long(OPT_PRESERVE_TIMESTAMPS)
.help("(unimplemented) apply access/modification times of SOURCE files to corresponding destination files")
.help("apply access/modification times of SOURCE files to corresponding destination files")
)
.arg(
// TODO implement flag
@ -265,8 +266,6 @@ fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
Err("--compare, -C")
} else if matches.is_present(OPT_CREATED) {
Err("-D")
} else if matches.is_present(OPT_PRESERVE_TIMESTAMPS) {
Err("--preserve-timestamps, -p")
} else if matches.is_present(OPT_STRIP) {
Err("--strip, -s")
} else if matches.is_present(OPT_STRIP_PROGRAM) {
@ -338,6 +337,7 @@ fn behavior(matches: &ArgMatches) -> Result<Behavior, i32> {
owner: matches.value_of(OPT_OWNER).unwrap_or("").to_string(),
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
verbose: matches.is_present(OPT_VERBOSE),
preserve_timestamps: matches.is_present(OPT_PRESERVE_TIMESTAMPS),
})
}
@ -555,6 +555,21 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
}
}
if b.preserve_timestamps {
let meta = match fs::metadata(from) {
Ok(meta) => meta,
Err(f) => crash!(1, "{}", f.to_string()),
};
let modified_time = FileTime::from_last_modification_time(&meta);
let accessed_time = FileTime::from_last_access_time(&meta);
match set_file_times(to.as_path(), accessed_time, modified_time) {
Ok(_) => {}
Err(e) => show_info!("{}", e),
}
}
if b.verbose {
show_info!("'{}' -> '{}'", from.display(), to.display());
}

View file

@ -309,6 +309,31 @@ fn test_install_target_new_file_failing_nonexistent_parent() {
assert!(err.contains("not a directory"))
}
#[test]
fn test_install_preserve_timestamps() {
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let file2 = "test_install_target_dir_file_a2";
at.touch(file1);
ucmd.arg(file1).arg(file2).arg("-p").succeeds().no_stderr();
assert!(at.file_exists(file1));
assert!(at.file_exists(file2));
let file1_metadata = at.metadata(file1);
let file2_metadata = at.metadata(file2);
assert_eq!(
file1_metadata.accessed().ok(),
file2_metadata.accessed().ok()
);
assert_eq!(
file1_metadata.modified().ok(),
file2_metadata.modified().ok()
);
}
// These two tests are failing but should work
#[test]
fn test_install_copy_file() {