mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
Merge pull request #1812 from konomith/feature/preserve_timestamps_#1758
install: Implement --preserve-timestamps (-p)
This commit is contained in:
commit
44a7adc9a0
4 changed files with 46 additions and 4 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1687,6 +1687,7 @@ name = "uu_install"
|
||||||
version = "0.0.4"
|
version = "0.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"uucore 0.0.7",
|
"uucore 0.0.7",
|
||||||
|
|
|
@ -19,6 +19,7 @@ path = "src/install.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.33"
|
clap = "2.33"
|
||||||
|
filetime = "0.2"
|
||||||
libc = ">= 0.2"
|
libc = ">= 0.2"
|
||||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["mode", "perms", "entries"] }
|
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" }
|
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod mode;
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
use clap::{App, Arg, ArgMatches};
|
use clap::{App, Arg, ArgMatches};
|
||||||
|
use filetime::{set_file_times, FileTime};
|
||||||
use uucore::entries::{grp2gid, usr2uid};
|
use uucore::entries::{grp2gid, usr2uid};
|
||||||
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
|
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ pub struct Behavior {
|
||||||
owner: String,
|
owner: String,
|
||||||
group: String,
|
group: String,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
preserve_timestamps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
|
@ -154,11 +156,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
// TODO implement flag
|
|
||||||
Arg::with_name(OPT_PRESERVE_TIMESTAMPS)
|
Arg::with_name(OPT_PRESERVE_TIMESTAMPS)
|
||||||
.short("p")
|
.short("p")
|
||||||
.long(OPT_PRESERVE_TIMESTAMPS)
|
.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(
|
.arg(
|
||||||
// TODO implement flag
|
// TODO implement flag
|
||||||
|
@ -265,8 +266,6 @@ fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
|
||||||
Err("--compare, -C")
|
Err("--compare, -C")
|
||||||
} else if matches.is_present(OPT_CREATED) {
|
} else if matches.is_present(OPT_CREATED) {
|
||||||
Err("-D")
|
Err("-D")
|
||||||
} else if matches.is_present(OPT_PRESERVE_TIMESTAMPS) {
|
|
||||||
Err("--preserve-timestamps, -p")
|
|
||||||
} else if matches.is_present(OPT_STRIP) {
|
} else if matches.is_present(OPT_STRIP) {
|
||||||
Err("--strip, -s")
|
Err("--strip, -s")
|
||||||
} else if matches.is_present(OPT_STRIP_PROGRAM) {
|
} 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(),
|
owner: matches.value_of(OPT_OWNER).unwrap_or("").to_string(),
|
||||||
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
|
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
|
||||||
verbose: matches.is_present(OPT_VERBOSE),
|
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 {
|
if b.verbose {
|
||||||
show_info!("'{}' -> '{}'", from.display(), to.display());
|
show_info!("'{}' -> '{}'", from.display(), to.display());
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,6 +309,31 @@ fn test_install_target_new_file_failing_nonexistent_parent() {
|
||||||
assert!(err.contains("not a directory"))
|
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
|
// These two tests are failing but should work
|
||||||
#[test]
|
#[test]
|
||||||
fn test_install_copy_file() {
|
fn test_install_copy_file() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue