Merge pull request #2339 from sylvestre/gnu-compat

Improve the gnu compat and use it for "touch"
This commit is contained in:
Sylvestre Ledru 2021-06-03 10:53:47 +02:00 committed by GitHub
commit 24032498ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 5 deletions

View file

@ -18,6 +18,7 @@ search the issues to make sure no one else is working on it.
## Best practices
1. Follow what GNU is doing in term of options and behavior.
1. If possible, look at the GNU test suite execution in the CI and make the test work if failing.
1. Use clap for argument management.
1. Make sure that the code coverage is covering all of the cases, including errors.
1. The code must be clippy-warning-free and rustfmt-compliant.

View file

@ -327,8 +327,12 @@ To run locally:
```bash
$ bash util/build-gnu.sh
$ bash util/run-gnu-test.sh
# To run a single test:
$ bash util/run-gnu-test.sh tests/touch/not-owner.sh # for example
```
Note that it relies on individual utilities (not the multicall binary).
## Contribute
To contribute to uutils, please see [CONTRIBUTING](CONTRIBUTING.md).

View file

@ -155,6 +155,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
(now, now)
};
let mut error_code = 0;
for filename in &files {
let path = &filename[..];
@ -166,6 +168,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if let Err(e) = File::create(path) {
show_warning!("cannot touch '{}': {}", path, e);
error_code = 1;
continue;
};
@ -202,14 +205,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if matches.is_present(options::NO_DEREF) {
if let Err(e) = set_symlink_file_times(path, atime, mtime) {
show_warning!("cannot touch '{}': {}", path, e);
// we found an error, it should fail in any case
error_code = 1;
if e.kind() == std::io::ErrorKind::PermissionDenied {
// GNU compatibility (not-owner.sh)
show_error!("setting times of '{}': {}", path, "Permission denied");
} else {
show_error!("setting times of '{}': {}", path, e);
}
}
} else if let Err(e) = filetime::set_file_times(path, atime, mtime) {
show_warning!("cannot touch '{}': {}", path, e);
// we found an error, it should fail in any case
error_code = 1;
if e.kind() == std::io::ErrorKind::PermissionDenied {
// GNU compatibility (not-owner.sh)
show_error!("setting times of '{}': {}", path, "Permission denied");
} else {
show_error!("setting times of '{}': {}", path, e);
}
}
}
0
error_code
}
fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {

View file

@ -449,3 +449,20 @@ fn test_touch_mtime_dst_fails() {
ucmd.args(&["-m", "-t", &s, file]).fails();
}
}
#[test]
#[cfg(unix)]
fn test_touch_system_fails() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "/";
ucmd.args(&[file])
.fails()
.stderr_contains("setting times of '/'");
}
#[test]
fn test_touch_trailing_slash() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "no-file/";
ucmd.args(&[file]).fails();
}

View file

@ -5,4 +5,11 @@ BUILDDIR="${PWD}/uutils/target/release"
GNULIB_DIR="${PWD}/gnulib"
pushd gnu
timeout -sKILL 2h make -j "$(nproc)" check SUBDIRS=. RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes VERBOSE=no || : # Kill after 4 hours in case something gets stuck in make
export RUST_BACKTRACE=1
if test -n "$1"; then
# if set, run only the test passed
export RUN_TEST="TESTS=$1"
fi
timeout -sKILL 2h make -j "$(nproc)" check $RUN_TEST SUBDIRS=. RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes VERBOSE=no || : # Kill after 4 hours in case something gets stuck in make