mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 23:02:38 +00:00
Implement skeleton install utility
Add install utility skeleton source, based on mv, including the getopts setup mirroring GNU's `man install` documentation. Also add a single test and build system code.
This commit is contained in:
parent
61cf4e4fba
commit
e72ec4a5bb
8 changed files with 174 additions and 0 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
@ -8,6 +8,7 @@ dependencies = [
|
||||||
"basename 0.0.1",
|
"basename 0.0.1",
|
||||||
"cat 0.0.1",
|
"cat 0.0.1",
|
||||||
"chmod 0.0.1",
|
"chmod 0.0.1",
|
||||||
|
"chown 0.0.1",
|
||||||
"chroot 0.0.1",
|
"chroot 0.0.1",
|
||||||
"cksum 0.0.1",
|
"cksum 0.0.1",
|
||||||
"comm 0.0.1",
|
"comm 0.0.1",
|
||||||
|
@ -31,6 +32,7 @@ dependencies = [
|
||||||
"hostid 0.0.1",
|
"hostid 0.0.1",
|
||||||
"hostname 0.0.1",
|
"hostname 0.0.1",
|
||||||
"id 0.0.1",
|
"id 0.0.1",
|
||||||
|
"install 0.0.1",
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"kill 0.0.1",
|
"kill 0.0.1",
|
||||||
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -177,6 +179,17 @@ dependencies = [
|
||||||
"walker 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walker 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chown"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"uucore 0.0.1",
|
||||||
|
"walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chroot"
|
name = "chroot"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -408,6 +421,15 @@ dependencies = [
|
||||||
"uucore 0.0.1",
|
"uucore 0.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "install"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"uucore 0.0.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.4.15"
|
version = "0.4.15"
|
||||||
|
@ -1204,6 +1226,15 @@ name = "vec_map"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walker"
|
name = "walker"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
|
@ -15,6 +15,7 @@ unix = [
|
||||||
"hostid",
|
"hostid",
|
||||||
"hostname",
|
"hostname",
|
||||||
"id",
|
"id",
|
||||||
|
"install",
|
||||||
"kill",
|
"kill",
|
||||||
"logname",
|
"logname",
|
||||||
"mkfifo",
|
"mkfifo",
|
||||||
|
@ -126,6 +127,7 @@ head = { optional=true, path="src/head" }
|
||||||
hostid = { optional=true, path="src/hostid" }
|
hostid = { optional=true, path="src/hostid" }
|
||||||
hostname = { optional=true, path="src/hostname" }
|
hostname = { optional=true, path="src/hostname" }
|
||||||
id = { optional=true, path="src/id" }
|
id = { optional=true, path="src/id" }
|
||||||
|
install = { optional=true, path="src/install" }
|
||||||
kill = { optional=true, path="src/kill" }
|
kill = { optional=true, path="src/kill" }
|
||||||
link = { optional=true, path="src/link" }
|
link = { optional=true, path="src/link" }
|
||||||
ln = { optional=true, path="src/ln" }
|
ln = { optional=true, path="src/ln" }
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -107,6 +107,7 @@ UNIX_PROGS := \
|
||||||
hostid \
|
hostid \
|
||||||
hostname \
|
hostname \
|
||||||
id \
|
id \
|
||||||
|
install \
|
||||||
kill \
|
kill \
|
||||||
logname \
|
logname \
|
||||||
mkfifo \
|
mkfifo \
|
||||||
|
@ -152,6 +153,7 @@ TEST_PROGS := \
|
||||||
fold \
|
fold \
|
||||||
hashsum \
|
hashsum \
|
||||||
head \
|
head \
|
||||||
|
install \
|
||||||
link \
|
link \
|
||||||
ln \
|
ln \
|
||||||
ls \
|
ls \
|
||||||
|
|
20
src/install/Cargo.toml
Normal file
20
src/install/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "install"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Ben Eills <ben@beneills.com>"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "uu_install"
|
||||||
|
path = "install.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
getopts = "*"
|
||||||
|
libc = "*"
|
||||||
|
uucore = { path="../uucore" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
time = "*"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "install"
|
||||||
|
path = "main.rs"
|
92
src/install/install.rs
Normal file
92
src/install/install.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#![crate_name = "uu_install"]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the uutils coreutils package.
|
||||||
|
*
|
||||||
|
* (c) Ben Eills <ben@beneills.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE file
|
||||||
|
* that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern crate getopts;
|
||||||
|
extern crate libc;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate uucore;
|
||||||
|
|
||||||
|
use std::io::{Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
static NAME: &'static str = "install";
|
||||||
|
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
|
let mut opts = getopts::Options::new();
|
||||||
|
|
||||||
|
opts.optflagopt("", "backup", "make a backup of each existing destination file", "CONTROL");
|
||||||
|
opts.optflag("b", "", "like --backup but does not accept an argument");
|
||||||
|
opts.optflag("C", "compare", "compare each pair of source and destination files, and in\n \
|
||||||
|
some cases, do not modify the destination at all");
|
||||||
|
opts.optflag("d", "directory", "treat all arguments as directory names; create all\n \
|
||||||
|
components of the specified directories");
|
||||||
|
|
||||||
|
opts.optflag("D", "", "create all leading components of DEST except the last, then copy\n \
|
||||||
|
SOURCE to DEST");
|
||||||
|
opts.optflagopt("g", "group", "set group ownership, instead of process' current group",
|
||||||
|
"GROUP");
|
||||||
|
opts.optflagopt("m", "mode", "set permission mode (as in chmod), instead of rwxr-xr-x",
|
||||||
|
"MODE");
|
||||||
|
opts.optflagopt("o", "owner", "set ownership (super-user only)",
|
||||||
|
"OWNER");
|
||||||
|
opts.optflag("p", "preserve-timestamps", "apply access/modification times of SOURCE files\n \
|
||||||
|
to corresponding destination files");
|
||||||
|
opts.optflag("s", "strip", "strip symbol tables");
|
||||||
|
opts.optflagopt("", "strip-program", "program used to strip binaries", "PROGRAM");
|
||||||
|
opts.optopt("S", "suffix", "override the usual backup suffix", "SUFFIX");
|
||||||
|
opts.optopt("t", "target-directory", "move all SOURCE arguments into DIRECTORY", "DIRECTORY");
|
||||||
|
opts.optflag("T", "no-target-directory", "treat DEST as a normal file");
|
||||||
|
opts.optflag("v", "verbose", "explain what is being done");
|
||||||
|
opts.optflag("P", "preserve-context", "preserve security context");
|
||||||
|
opts.optflagopt("Z", "context", "set security context of files and directories", "CONTEXT");
|
||||||
|
opts.optflag("h", "help", "display this help and exit");
|
||||||
|
opts.optflag("V", "version", "output version information and exit");
|
||||||
|
|
||||||
|
let matches = match opts.parse(&args[1..]) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(f) => {
|
||||||
|
show_error!("Invalid options\n{}", f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let usage = opts.usage("Copy SOURCE to DEST or multiple SOURCE(s) to the existing\n \
|
||||||
|
DIRECTORY, while setting permission modes and owner/group");
|
||||||
|
|
||||||
|
let paths: Vec<PathBuf> = {
|
||||||
|
fn string_to_path<'a>(s: &'a String) -> &'a Path {
|
||||||
|
Path::new(s)
|
||||||
|
};
|
||||||
|
let to_owned = |p: &Path| p.to_owned();
|
||||||
|
let arguments = matches.free.iter().map(string_to_path);
|
||||||
|
|
||||||
|
arguments.map(to_owned).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
if matches.opt_present("version") {
|
||||||
|
println!("{} {}", NAME, VERSION);
|
||||||
|
0
|
||||||
|
} else if matches.opt_present("help") {
|
||||||
|
help(&usage);
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
println!("Not implemented.");
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn help(usage: &str) {
|
||||||
|
println!("{0} {1}\n\n\
|
||||||
|
Usage: {0} SOURCE DEST\n \
|
||||||
|
or: {0} SOURCE... DIRECTORY\n\n\
|
||||||
|
{2}", NAME, VERSION, usage);
|
||||||
|
}
|
5
src/install/main.rs
Normal file
5
src/install/main.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
extern crate uu_install;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
std::process::exit(uu_install::uumain(std::env::args().collect()));
|
||||||
|
}
|
21
tests/test_install.rs
Normal file
21
tests/test_install.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
extern crate libc;
|
||||||
|
extern crate time;
|
||||||
|
extern crate kernel32;
|
||||||
|
extern crate winapi;
|
||||||
|
extern crate filetime;
|
||||||
|
|
||||||
|
use self::filetime::*;
|
||||||
|
use common::util::*;
|
||||||
|
|
||||||
|
static UTIL_NAME: &'static str = "install";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_install_help() {
|
||||||
|
let (at, mut ucmd) = testing(UTIL_NAME);
|
||||||
|
|
||||||
|
let result = ucmd.arg("--help").run();
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
// assert!(result.stdout.contains("Usage:"));
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ macro_rules! unix_only {
|
||||||
unix_only! {
|
unix_only! {
|
||||||
"chmod", test_chmod;
|
"chmod", test_chmod;
|
||||||
"chown", test_chown;
|
"chown", test_chown;
|
||||||
|
"install", test_install;
|
||||||
"mv", test_mv;
|
"mv", test_mv;
|
||||||
"pathchk", test_pathchk;
|
"pathchk", test_pathchk;
|
||||||
"stdbuf", test_stdbuf;
|
"stdbuf", test_stdbuf;
|
||||||
|
|
Loading…
Reference in a new issue