mirror of
https://github.com/uutils/coreutils
synced 2024-07-23 19:04:18 +00:00
install: allow to install a file to a file
This commit is contained in:
parent
c386d5bfaf
commit
ee34206520
227
Cargo.lock
generated
227
Cargo.lock
generated
|
@ -1,112 +1,3 @@
|
|||
[root]
|
||||
name = "uutils"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"arch 0.0.1",
|
||||
"base32 0.0.1",
|
||||
"base64 0.0.1",
|
||||
"basename 0.0.1",
|
||||
"cat 0.0.1",
|
||||
"chgrp 0.0.1",
|
||||
"chmod 0.0.1",
|
||||
"chown 0.0.1",
|
||||
"chroot 0.0.1",
|
||||
"cksum 0.0.1",
|
||||
"comm 0.0.1",
|
||||
"cp 0.0.1",
|
||||
"cut 0.0.1",
|
||||
"date 0.0.1",
|
||||
"dircolors 0.0.1",
|
||||
"dirname 0.0.1",
|
||||
"du 0.0.1",
|
||||
"echo 0.0.1",
|
||||
"env 0.0.1",
|
||||
"expand 0.0.1",
|
||||
"expr 0.0.1",
|
||||
"factor 0.0.1",
|
||||
"false 0.0.1",
|
||||
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fmt 0.0.1",
|
||||
"fold 0.0.1",
|
||||
"groups 0.0.1",
|
||||
"hashsum 0.0.1",
|
||||
"head 0.0.1",
|
||||
"hostid 0.0.1",
|
||||
"hostname 0.0.1",
|
||||
"id 0.0.1",
|
||||
"install 0.0.1",
|
||||
"join 0.0.1",
|
||||
"kill 0.0.1",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"link 0.0.1",
|
||||
"ln 0.0.1",
|
||||
"logname 0.0.1",
|
||||
"ls 0.0.1",
|
||||
"mkdir 0.0.1",
|
||||
"mkfifo 0.0.1",
|
||||
"mknod 0.0.1",
|
||||
"mktemp 0.0.1",
|
||||
"more 0.0.1",
|
||||
"mv 0.0.1",
|
||||
"nice 0.0.1",
|
||||
"nl 0.0.1",
|
||||
"nohup 0.0.1",
|
||||
"nproc 0.0.1",
|
||||
"numfmt 0.0.1",
|
||||
"od 0.0.1",
|
||||
"paste 0.0.1",
|
||||
"pathchk 0.0.1",
|
||||
"pinky 0.0.1",
|
||||
"printenv 0.0.1",
|
||||
"printf 0.0.1",
|
||||
"ptx 0.0.1",
|
||||
"pwd 0.0.1",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"readlink 0.0.1",
|
||||
"realpath 0.0.1",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"relpath 0.0.1",
|
||||
"rm 0.0.1",
|
||||
"rmdir 0.0.1",
|
||||
"seq 0.0.1",
|
||||
"shred 0.0.1",
|
||||
"shuf 0.0.1",
|
||||
"sleep 0.0.1",
|
||||
"sort 0.0.1",
|
||||
"split 0.0.1",
|
||||
"stat 0.0.1",
|
||||
"stdbuf 0.0.1",
|
||||
"sum 0.0.1",
|
||||
"sync 0.0.1",
|
||||
"tac 0.0.1",
|
||||
"tail 0.0.1",
|
||||
"tee 0.0.1",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"test 0.0.1",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"timeout 0.0.1",
|
||||
"touch 0.0.1",
|
||||
"tr 0.0.1",
|
||||
"true 0.0.1",
|
||||
"truncate 0.0.1",
|
||||
"tsort 0.0.1",
|
||||
"tty 0.0.1",
|
||||
"uname 0.0.1",
|
||||
"unexpand 0.0.1",
|
||||
"unindent 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uniq 0.0.1",
|
||||
"unix_socket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unlink 0.0.1",
|
||||
"uptime 0.0.1",
|
||||
"users 0.0.1",
|
||||
"uucore 0.0.1",
|
||||
"wc 0.0.1",
|
||||
"who 0.0.1",
|
||||
"whoami 0.0.1",
|
||||
"yes 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "advapi32-sys"
|
||||
version = "0.2.0"
|
||||
|
@ -435,6 +326,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
[[package]]
|
||||
name = "false"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"uucore 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
|
@ -593,7 +487,7 @@ dependencies = [
|
|||
name = "join"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uucore 0.0.1",
|
||||
]
|
||||
|
||||
|
@ -1170,6 +1064,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libstdbuf 0.0.1",
|
||||
"uucore 0.0.1",
|
||||
]
|
||||
|
@ -1345,6 +1240,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "true"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"uucore 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "truncate"
|
||||
|
@ -1467,6 +1365,115 @@ dependencies = [
|
|||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uutils"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"arch 0.0.1",
|
||||
"base32 0.0.1",
|
||||
"base64 0.0.1",
|
||||
"basename 0.0.1",
|
||||
"cat 0.0.1",
|
||||
"chgrp 0.0.1",
|
||||
"chmod 0.0.1",
|
||||
"chown 0.0.1",
|
||||
"chroot 0.0.1",
|
||||
"cksum 0.0.1",
|
||||
"comm 0.0.1",
|
||||
"cp 0.0.1",
|
||||
"cut 0.0.1",
|
||||
"date 0.0.1",
|
||||
"dircolors 0.0.1",
|
||||
"dirname 0.0.1",
|
||||
"du 0.0.1",
|
||||
"echo 0.0.1",
|
||||
"env 0.0.1",
|
||||
"expand 0.0.1",
|
||||
"expr 0.0.1",
|
||||
"factor 0.0.1",
|
||||
"false 0.0.1",
|
||||
"filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fmt 0.0.1",
|
||||
"fold 0.0.1",
|
||||
"groups 0.0.1",
|
||||
"hashsum 0.0.1",
|
||||
"head 0.0.1",
|
||||
"hostid 0.0.1",
|
||||
"hostname 0.0.1",
|
||||
"id 0.0.1",
|
||||
"install 0.0.1",
|
||||
"join 0.0.1",
|
||||
"kill 0.0.1",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"link 0.0.1",
|
||||
"ln 0.0.1",
|
||||
"logname 0.0.1",
|
||||
"ls 0.0.1",
|
||||
"mkdir 0.0.1",
|
||||
"mkfifo 0.0.1",
|
||||
"mknod 0.0.1",
|
||||
"mktemp 0.0.1",
|
||||
"more 0.0.1",
|
||||
"mv 0.0.1",
|
||||
"nice 0.0.1",
|
||||
"nl 0.0.1",
|
||||
"nohup 0.0.1",
|
||||
"nproc 0.0.1",
|
||||
"numfmt 0.0.1",
|
||||
"od 0.0.1",
|
||||
"paste 0.0.1",
|
||||
"pathchk 0.0.1",
|
||||
"pinky 0.0.1",
|
||||
"printenv 0.0.1",
|
||||
"printf 0.0.1",
|
||||
"ptx 0.0.1",
|
||||
"pwd 0.0.1",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"readlink 0.0.1",
|
||||
"realpath 0.0.1",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"relpath 0.0.1",
|
||||
"rm 0.0.1",
|
||||
"rmdir 0.0.1",
|
||||
"seq 0.0.1",
|
||||
"shred 0.0.1",
|
||||
"shuf 0.0.1",
|
||||
"sleep 0.0.1",
|
||||
"sort 0.0.1",
|
||||
"split 0.0.1",
|
||||
"stat 0.0.1",
|
||||
"stdbuf 0.0.1",
|
||||
"sum 0.0.1",
|
||||
"sync 0.0.1",
|
||||
"tac 0.0.1",
|
||||
"tail 0.0.1",
|
||||
"tee 0.0.1",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"test 0.0.1",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"timeout 0.0.1",
|
||||
"touch 0.0.1",
|
||||
"tr 0.0.1",
|
||||
"true 0.0.1",
|
||||
"truncate 0.0.1",
|
||||
"tsort 0.0.1",
|
||||
"tty 0.0.1",
|
||||
"uname 0.0.1",
|
||||
"unexpand 0.0.1",
|
||||
"unindent 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uniq 0.0.1",
|
||||
"unix_socket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unlink 0.0.1",
|
||||
"uptime 0.0.1",
|
||||
"users 0.0.1",
|
||||
"uucore 0.0.1",
|
||||
"wc 0.0.1",
|
||||
"who 0.0.1",
|
||||
"whoami 0.0.1",
|
||||
"yes 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.0"
|
||||
|
|
|
@ -109,7 +109,7 @@ fn parse_opts(args: Vec<String>) -> getopts::Matches {
|
|||
// TODO implement flag
|
||||
.optflag("C", "compare", "(unimplemented) compare each pair of source and destination\n \
|
||||
files, and in some cases, do not modify the destination at all")
|
||||
.optflag("d", "directory", "treat all arguments as directory names\n \
|
||||
.optflag("d", "directory", "treat all arguments as directory names.\n \
|
||||
create all components of the specified directories")
|
||||
// TODO implement flag
|
||||
.optflag("D", "", "(unimplemented) create all leading components of DEST except the\n \
|
||||
|
@ -286,6 +286,13 @@ fn directory(paths: &[PathBuf], b: Behaviour) -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Test if the path is a a new file path that can be
|
||||
/// created immediately
|
||||
fn is_new_file_path(path: &Path) -> bool {
|
||||
path.is_file() ||
|
||||
! path.exists() && path.parent().map(|p| p.is_dir()).unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Perform an install, given a list of paths and behaviour.
|
||||
///
|
||||
/// Returns an integer intended as a program return code.
|
||||
|
@ -296,9 +303,13 @@ fn standard(paths: &[PathBuf], b: Behaviour) -> i32 {
|
|||
1
|
||||
} else {
|
||||
let sources = &paths[0..paths.len() - 1];
|
||||
let target_directory = &paths[paths.len() - 1];
|
||||
let target = &paths[paths.len() - 1];
|
||||
|
||||
copy_files_into_dir(sources, target_directory, &b)
|
||||
if (target.is_file() || is_new_file_path(target)) && sources.len() == 1 {
|
||||
copy_file_to_file(&sources[0], target, &b)
|
||||
} else {
|
||||
copy_files_into_dir(sources, target, &b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,6 +349,20 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behaviour) -
|
|||
if all_successful { 0 } else { 1 }
|
||||
}
|
||||
|
||||
/// Copy a file to another file.
|
||||
///
|
||||
/// Prints verbose information and error messages.
|
||||
/// Returns an integer intended as a program return code.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// _file_ must exist as a non-directory.
|
||||
/// _target_ must be a non-directory
|
||||
///
|
||||
fn copy_file_to_file(file: &PathBuf, target: &PathBuf, b: &Behaviour) -> i32 {
|
||||
if copy(file, &target, b).is_err() { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Copy one file to a new location, changing metadata.
|
||||
///
|
||||
/// # Parameters
|
||||
|
|
|
@ -28,6 +28,20 @@ fn test_install_basic() {
|
|||
assert!(at.file_exists(&format!("{}/{}", dir, file2)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_failing_not_dir() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_dir_file_a1";
|
||||
let file2 = "test_install_target_dir_file_a2";
|
||||
let file3 = "test_install_target_dir_file_a3";
|
||||
|
||||
at.touch(file1);
|
||||
at.touch(file2);
|
||||
at.touch(file3);
|
||||
assert!(ucmd.arg(file1).arg(file2).arg(file3)
|
||||
.fails().stderr.contains("not a directory"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_unimplemented_arg() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
@ -136,3 +150,47 @@ fn test_install_mode_directories() {
|
|||
let permissions = at.metadata(component).permissions();
|
||||
assert_eq!(0o040333 as u32, PermissionsExt::mode(&permissions));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_target_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_file_file_i1";
|
||||
let file2 = "test_install_target_file_file_i2";
|
||||
|
||||
at.touch(file1);
|
||||
at.touch(file2);
|
||||
ucmd.arg(file1).arg(file2).succeeds().no_stderr();
|
||||
|
||||
assert!(at.file_exists(file1));
|
||||
assert!(at.file_exists(file2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_target_new_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file = "test_install_target_new_filer_file_j";
|
||||
let dir = "test_install_target_new_file_dir_j";
|
||||
|
||||
at.touch(file);
|
||||
at.mkdir(dir);
|
||||
ucmd.arg(file).arg(format!("{}/{}", dir, file)).succeeds().no_stderr();
|
||||
|
||||
assert!(at.file_exists(file));
|
||||
assert!(at.file_exists(&format!("{}/{}", dir, file)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_target_new_file_failing_nonexistent_parent() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_new_file_failing_file_k1";
|
||||
let file2 = "test_install_target_new_file_failing_file_k2";
|
||||
let dir = "test_install_target_new_file_failing_dir_k";
|
||||
|
||||
at.touch(file1);
|
||||
|
||||
let err = ucmd.arg(file1).arg(format!("{}/{}", dir, file2))
|
||||
.fails().stderr;
|
||||
|
||||
assert!(err.contains("not a directory"))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue