Merge branch 'master' into ls_selinux

This commit is contained in:
Jan Scheer 2021-09-17 14:14:47 +02:00
commit 79d838b1c3
No known key found for this signature in database
GPG key ID: C62AD4C29E2B9828
70 changed files with 685 additions and 182 deletions

View file

@ -708,3 +708,35 @@ jobs:
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
name: codecov-umbrella
fail_ci_if_error: false
unused_deps:
name: Unused deps
runs-on: ${{ matrix.job.os }}
strategy:
fail-fast: false
matrix:
job:
- { os: ubuntu-latest , features: feat_os_unix }
- { os: macos-latest , features: feat_os_macos }
- { os: windows-latest , features: feat_os_windows }
steps:
- uses: actions/checkout@v2
- name: Install `rust` toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
default: true
profile: minimal
- name: Install `cargo-udeps`
uses: actions-rs/install@v0.1
with:
crate: cargo-udeps
version: latest
use-tool-cache: true
env:
RUSTUP_TOOLCHAIN: stable
- name: Confirms there isn't any unused deps
shell: bash
run: |
cargo +nightly udeps --all-targets &> udeps.log || cat udeps.log
grep "seem to have been used" udeps.log

View file

@ -43,6 +43,9 @@ gibi
gibibytes
glob
globbing
hardcode
hardcoded
hardcoding
hardfloat
hardlink
hardlinks
@ -114,6 +117,7 @@ toolchain
truthy
ucase
unbuffered
udeps
unescape
unintuitive
unprefixed

View file

@ -68,6 +68,7 @@ structs
substr
splitn
trunc
uninit
# * uutils
basenc
@ -277,6 +278,7 @@ ULONG
ULONGLONG
UNLEN
WCHAR
WSADATA
errhandlingapi
fileapi
handleapi

36
Cargo.lock generated
View file

@ -1004,15 +1004,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "locale"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fdbe492a9c0238da900a1165c42fc5067161ce292678a6fe80921f30fe307fd"
dependencies = [
"libc",
]
[[package]]
name = "lock_api"
version = "0.4.4"
@ -1104,19 +1095,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "nix"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b"
dependencies = [
"bitflags",
"cc",
"cfg-if 0.1.10",
"libc",
"void",
]
[[package]]
name = "nix"
version = "0.19.1"
@ -2314,7 +2292,6 @@ name = "uu_csplit"
version = "0.0.7"
dependencies = [
"clap",
"glob",
"regex",
"thiserror",
"uucore",
@ -2628,7 +2605,6 @@ dependencies = [
"clap",
"globset",
"lazy_static",
"locale",
"lscolors",
"number_prefix",
"once_cell",
@ -2713,7 +2689,7 @@ version = "0.0.7"
dependencies = [
"clap",
"libc",
"nix 0.13.1",
"nix 0.20.0",
"uucore",
"uucore_procs",
]
@ -2813,7 +2789,6 @@ dependencies = [
"itertools 0.10.1",
"quick-error 2.0.1",
"regex",
"time",
"uucore",
"uucore_procs",
]
@ -2939,10 +2914,8 @@ name = "uu_shred"
version = "0.0.7"
dependencies = [
"clap",
"filetime",
"libc",
"rand 0.7.3",
"time",
"uucore",
"uucore_procs",
]
@ -3052,6 +3025,7 @@ version = "0.0.7"
dependencies = [
"clap",
"memchr 2.4.0",
"regex",
"uucore",
"uucore_procs",
]
@ -3314,12 +3288,6 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "walkdir"
version = "2.3.2"

View file

@ -366,7 +366,6 @@ conv = "0.3"
filetime = "0.2"
glob = "0.3.0"
libc = "0.2"
nix = "0.20.0"
pretty_assertions = "0.7.2"
rand = "0.7"
regex = "1.0"
@ -378,8 +377,12 @@ uucore = { version=">=0.0.9", package="uucore", path="src/uucore", features=["en
walkdir = "2.2"
atty = "0.2"
[target.'cfg(unix)'.dev-dependencies]
[target.'cfg(target_os = "linux")'.dev-dependencies]
rlimit = "0.4.0"
[target.'cfg(unix)'.dev-dependencies]
nix = "0.20.0"
rust-users = { version="0.10", package="users" }
unix_socket = "0.5.0"

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "base32"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uu_base32 = { version=">=0.0.6", package="uu_base32", path="../base32"}
[[bin]]
name = "base64"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "basename"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uu_base32 = { version=">=0.0.6", package="uu_base32", path="../base32"}
[[bin]]
name = "basenc"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "cksum"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "comm"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -45,3 +45,7 @@ path = "src/main.rs"
[features]
feat_selinux = ["selinux"]
feat_acl = ["exacl"]
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -18,10 +18,13 @@ path = "src/csplit.rs"
clap = { version = "2.33", features = ["wrap_help"] }
thiserror = "1.0"
regex = "1.0.0"
glob = "0.3"
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "fs"] }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
[[bin]]
name = "csplit"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -25,3 +25,7 @@ atty = "0.2"
[[bin]]
name = "cut"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -29,3 +29,7 @@ winapi = { version = "0.3", features = ["minwinbase", "sysinfoapi", "minwindef"]
[[bin]]
name = "date"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -31,3 +31,7 @@ signal-hook = "0.3.9"
[[bin]]
name = "dd"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "dircolors"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "expand"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -26,3 +26,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "expr"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -34,3 +34,7 @@ path = "src/main.rs"
[lib]
path = "src/cli.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -24,3 +24,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "fmt"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "fold"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -33,3 +33,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "hashsum"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "head"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -10,18 +10,13 @@
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg, ArgMatches};
use std::collections::hash_set::HashSet;
use std::net::ToSocketAddrs;
use std::str;
#[cfg(windows)]
use uucore::error::UUsageError;
use uucore::error::{UResult, USimpleError};
#[cfg(windows)]
use winapi::shared::minwindef::MAKEWORD;
#[cfg(windows)]
use winapi::um::winsock2::{WSACleanup, WSAStartup};
use clap::{crate_version, App, Arg, ArgMatches};
use uucore::error::{FromIo, UResult};
static ABOUT: &str = "Display or set the system's host name.";
@ -31,45 +26,52 @@ static OPT_FQDN: &str = "fqdn";
static OPT_SHORT: &str = "short";
static OPT_HOST: &str = "host";
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
#![allow(clippy::let_and_return)]
#[cfg(windows)]
unsafe {
#[allow(deprecated)]
let mut data = std::mem::uninitialized();
if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 {
return Err(UUsageError::new(
1,
"Failed to start Winsock 2.2".to_string(),
));
#[cfg(windows)]
mod wsa {
use std::io;
use winapi::shared::minwindef::MAKEWORD;
use winapi::um::winsock2::{WSACleanup, WSAStartup, WSADATA};
pub(super) struct WsaHandle(());
pub(super) fn start() -> io::Result<WsaHandle> {
let err = unsafe {
let mut data = std::mem::MaybeUninit::<WSADATA>::uninit();
WSAStartup(MAKEWORD(2, 2), data.as_mut_ptr())
};
if err != 0 {
Err(io::Error::from_raw_os_error(err))
} else {
Ok(WsaHandle(()))
}
}
let result = execute(args);
#[cfg(windows)]
unsafe {
WSACleanup();
impl Drop for WsaHandle {
fn drop(&mut self) {
unsafe {
// This possibly returns an error but we can't handle it
let _err = WSACleanup();
}
}
}
result
}
fn usage() -> String {
format!("{0} [OPTION]... [HOSTNAME]", uucore::execution_phrase())
}
fn execute(args: impl uucore::Args) -> UResult<()> {
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let usage = usage();
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
match matches.value_of(OPT_HOST) {
#[cfg(windows)]
let _handle = wsa::start().map_err_context(|| "failed to start Winsock".to_owned())?;
match matches.value_of_os(OPT_HOST) {
None => display_hostname(&matches),
Some(host) => {
if let Err(err) = hostname::set(host) {
return Err(USimpleError::new(1, format!("{}", err)));
} else {
Ok(())
}
}
Some(host) => hostname::set(host).map_err_context(|| "failed to set hostname".to_owned()),
}
}
@ -81,64 +83,68 @@ pub fn uu_app() -> App<'static, 'static> {
Arg::with_name(OPT_DOMAIN)
.short("d")
.long("domain")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the name of the DNS domain if possible"),
)
.arg(
Arg::with_name(OPT_IP_ADDRESS)
.short("i")
.long("ip-address")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the network address(es) of the host"),
)
// TODO: support --long
.arg(
Arg::with_name(OPT_FQDN)
.short("f")
.long("fqdn")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the FQDN (Fully Qualified Domain Name) (default)"),
)
.arg(Arg::with_name(OPT_SHORT).short("s").long("short").help(
"Display the short hostname (the portion before the first dot) if \
possible",
))
.arg(
Arg::with_name(OPT_SHORT)
.short("s")
.long("short")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the short hostname (the portion before the first dot) if possible"),
)
.arg(Arg::with_name(OPT_HOST))
}
fn display_hostname(matches: &ArgMatches) -> UResult<()> {
let hostname = hostname::get().unwrap().into_string().unwrap();
let hostname = hostname::get()
.map_err_context(|| "failed to get hostname".to_owned())?
.to_string_lossy()
.into_owned();
if matches.is_present(OPT_IP_ADDRESS) {
// XXX: to_socket_addrs needs hostname:port so append a dummy port and remove it later.
// This was originally supposed to use std::net::lookup_host, but that seems to be
// deprecated. Perhaps we should use the dns-lookup crate?
let hostname = hostname + ":1";
match hostname.to_socket_addrs() {
Ok(addresses) => {
let mut hashset = HashSet::new();
let mut output = String::new();
for addr in addresses {
// XXX: not sure why this is necessary...
if !hashset.contains(&addr) {
let mut ip = format!("{}", addr);
if ip.ends_with(":1") {
let len = ip.len();
ip.truncate(len - 2);
}
output.push_str(&ip);
output.push(' ');
hashset.insert(addr);
}
let addresses = hostname
.to_socket_addrs()
.map_err_context(|| "failed to resolve socket addresses".to_owned())?;
let mut hashset = HashSet::new();
let mut output = String::new();
for addr in addresses {
// XXX: not sure why this is necessary...
if !hashset.contains(&addr) {
let mut ip = addr.to_string();
if ip.ends_with(":1") {
let len = ip.len();
ip.truncate(len - 2);
}
let len = output.len();
if len > 0 {
println!("{}", &output[0..len - 1]);
}
Ok(())
}
Err(f) => {
return Err(USimpleError::new(1, format!("{}", f)));
output.push_str(&ip);
output.push(' ');
hashset.insert(addr);
}
}
let len = output.len();
if len > 0 {
println!("{}", &output[0..len - 1]);
}
Ok(())
} else {
if matches.is_present(OPT_SHORT) || matches.is_present(OPT_DOMAIN) {
let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.');

View file

@ -490,11 +490,10 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> UR
return Err(InstallError::TargetDirIsntDir(target_dir.to_path_buf()).into());
}
for sourcepath in files.iter() {
if !sourcepath.exists() {
let err = UIoError::new(
std::io::ErrorKind::NotFound,
format!("cannot stat {}", sourcepath.quote()),
);
if let Err(err) = sourcepath
.metadata()
.map_err_context(|| format!("cannot stat {}", sourcepath.quote()))
{
show!(err);
continue;
}

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "join"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ clap = { version = "2.33", features = ["wrap_help"] }
[[bin]]
name = "link"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -15,7 +15,6 @@ edition = "2018"
path = "src/ls.rs"
[dependencies]
locale = "0.2.2"
chrono = "0.4.19"
clap = { version = "2.33", features = ["wrap_help"] }
unicode-width = "0.1.8"
@ -39,3 +38,7 @@ path = "src/main.rs"
[features]
feat_selinux = ["selinux"]
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -42,7 +42,7 @@ use std::{
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
use uucore::{
display::Quotable,
error::{set_exit_code, FromIo, UError, UResult},
error::{set_exit_code, UError, UResult},
};
use unicode_width::UnicodeWidthStr;
@ -1333,8 +1333,13 @@ fn list(locs: Vec<&Path>, config: Config) -> UResult<()> {
let path_data = PathData::new(p, None, None, &config, true);
if path_data.md().is_none() {
show!(std::io::ErrorKind::NotFound
.map_err_context(|| format!("cannot access {}", path_data.p_buf.quote())));
// FIXME: Would be nice to use the actual error instead of hardcoding it
// Presumably other errors can happen too?
show_error!(
"cannot access {}: No such file or directory",
path_data.p_buf.quote()
);
set_exit_code(1);
// We found an error, no need to continue the execution
continue;
}

View file

@ -33,3 +33,7 @@ nix = "0.19"
[[bin]]
name = "more"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "mv"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -17,7 +17,7 @@ path = "src/nice.rs"
[dependencies]
clap = { version = "2.33", features = ["wrap_help"] }
libc = "0.2.42"
nix = { version="<=0.13" }
nix = "0.20"
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }

View file

@ -27,3 +27,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "nl"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "numfmt"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -25,3 +25,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "od"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "paste"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -19,8 +19,6 @@ clap = { version = "2.33", features = ["wrap_help"] }
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries"] }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
getopts = "0.2.21"
time = "0.1.41"
# A higher version would cause a conflict with time
chrono = "0.4.19"
quick-error = "2.0.1"
itertools = "0.10"
@ -29,3 +27,7 @@ regex = "1.0"
[[bin]]
name = "pr"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "printenv"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -26,3 +26,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "printf"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -27,3 +27,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "ptx"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "readlink"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "realpath"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "relpath"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -18,12 +18,16 @@ path = "src/rm.rs"
clap = { version = "2.33", features = ["wrap_help"] }
walkdir = "2.2"
remove_dir_all = "0.5.1"
winapi = { version="0.3", features=[] }
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs"] }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
[target.'cfg(windows)'.dependencies]
winapi = { version="0.3", features=[] }
[[bin]]
name = "rm"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -24,3 +24,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "seq"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -12,7 +12,7 @@ use num_traits::One;
use num_traits::Zero;
use num_traits::{Num, ToPrimitive};
use std::cmp;
use std::io::{stdout, Write};
use std::io::{stdout, ErrorKind, Write};
use std::str::FromStr;
use uucore::display::Quotable;
@ -99,6 +99,7 @@ impl Number {
impl FromStr for Number {
type Err = String;
fn from_str(mut s: &str) -> Result<Self, Self::Err> {
s = s.trim_start();
if s.starts_with('+') {
s = &s[1..];
}
@ -192,7 +193,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.num_digits()
.max(increment.num_digits())
.max(last.num_digits());
match (first, last, increment) {
let result = match (first, last, increment) {
(Number::MinusZero, Number::BigInt(last), Number::BigInt(increment)) => print_seq_integers(
(BigInt::zero(), increment, last),
options.separator,
@ -219,8 +220,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
options.widths,
padding,
),
};
match result {
Ok(_) => 0,
Err(err) if err.kind() == ErrorKind::BrokenPipe => 0,
Err(_) => 1,
}
0
}
pub fn uu_app() -> App<'static, 'static> {
@ -276,30 +281,35 @@ fn print_seq(
terminator: String,
pad: bool,
padding: usize,
) {
) -> std::io::Result<()> {
let stdout = stdout();
let mut stdout = stdout.lock();
let (first, increment, last) = range;
let mut i = 0isize;
let mut value = first + i as f64 * increment;
let mut is_first_iteration = true;
while !done_printing(&value, &increment, &last) {
if !is_first_iteration {
write!(stdout, "{}", separator)?;
}
is_first_iteration = false;
let istr = format!("{:.*}", largest_dec, value);
let ilen = istr.len();
let before_dec = istr.find('.').unwrap_or(ilen);
if pad && before_dec < padding {
for _ in 0..(padding - before_dec) {
print!("0");
write!(stdout, "0")?;
}
}
print!("{}", istr);
write!(stdout, "{}", istr)?;
i += 1;
value = first + i as f64 * increment;
if !done_printing(&value, &increment, &last) {
print!("{}", separator);
}
}
if (first >= last && increment < 0f64) || (first <= last && increment > 0f64) {
print!("{}", terminator);
if !is_first_iteration {
write!(stdout, "{}", terminator)?;
}
crash_if_err!(1, stdout().flush());
stdout.flush()?;
Ok(())
}
/// Print an integer sequence.
@ -323,31 +333,34 @@ fn print_seq_integers(
pad: bool,
padding: usize,
is_first_minus_zero: bool,
) {
) -> std::io::Result<()> {
let stdout = stdout();
let mut stdout = stdout.lock();
let (first, increment, last) = range;
let mut value = first;
let mut is_first_iteration = true;
while !done_printing(&value, &increment, &last) {
if !is_first_iteration {
print!("{}", separator);
write!(stdout, "{}", separator)?;
}
let mut width = padding;
if is_first_iteration && is_first_minus_zero {
print!("-");
write!(stdout, "-")?;
width -= 1;
}
is_first_iteration = false;
if pad {
print!("{number:>0width$}", number = value, width = width);
write!(stdout, "{number:>0width$}", number = value, width = width)?;
} else {
print!("{}", value);
write!(stdout, "{}", value)?;
}
value += &increment;
}
if !is_first_iteration {
print!("{}", terminator);
write!(stdout, "{}", terminator)?;
}
Ok(())
}
#[cfg(test)]

View file

@ -16,13 +16,15 @@ path = "src/shred.rs"
[dependencies]
clap = { version = "2.33", features = ["wrap_help"] }
filetime = "0.2.1"
libc = "0.2.42"
rand = "0.7"
time = "0.1.40"
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
[[bin]]
name = "shred"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "shuf"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "split"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "sum"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -16,6 +16,7 @@ path = "src/tac.rs"
[dependencies]
memchr = "2"
regex = "1"
clap = { version = "2.33", features = ["wrap_help"] }
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
@ -23,3 +24,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "tac"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -69,7 +69,7 @@ pub fn uu_app() -> App<'static, 'static> {
Arg::with_name(options::REGEX)
.short("r")
.long(options::REGEX)
.help("interpret the sequence as a regular expression (NOT IMPLEMENTED)")
.help("interpret the sequence as a regular expression")
.takes_value(false),
)
.arg(
@ -82,6 +82,82 @@ pub fn uu_app() -> App<'static, 'static> {
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
}
/// Print lines of a buffer in reverse, with line separator given as a regex.
///
/// `data` contains the bytes of the file.
///
/// `pattern` is the regular expression given as a
/// [`regex::bytes::Regex`] (not a [`regex::Regex`], since the input is
/// given as a slice of bytes). If `before` is `true`, then each match
/// of this pattern in `data` is interpreted as the start of a line. If
/// `before` is `false`, then each match of this pattern is interpreted
/// as the end of a line.
///
/// This function writes each line in `data` to [`std::io::Stdout`] in
/// reverse.
///
/// # Errors
///
/// If there is a problem writing to `stdout`, then this function
/// returns [`std::io::Error`].
fn buffer_tac_regex(
data: &[u8],
pattern: regex::bytes::Regex,
before: bool,
) -> std::io::Result<()> {
let mut out = stdout();
// The index of the line separator for the current line.
//
// As we scan through the `data` from right to left, we update this
// variable each time we find a new line separator. We restrict our
// regular expression search to only those bytes up to the line
// separator.
let mut this_line_end = data.len();
// The index of the start of the next line in the `data`.
//
// As we scan through the `data` from right to left, we update this
// variable each time we find a new line.
//
// If `before` is `true`, then each line starts immediately before
// the line separator. Otherwise, each line starts immediately after
// the line separator.
let mut following_line_start = data.len();
// Iterate over each byte in the buffer in reverse. When we find a
// line separator, write the line to stdout.
//
// The `before` flag controls whether the line separator appears at
// the end of the line (as in "abc\ndef\n") or at the beginning of
// the line (as in "/abc/def").
for i in (0..data.len()).rev() {
// Determine if there is a match for `pattern` starting at index
// `i` in `data`. Only search up to the line ending that was
// found previously.
if let Some(match_) = pattern.find_at(&data[..this_line_end], i) {
// Record this index as the ending of the current line.
this_line_end = i;
// The length of the match (that is, the line separator), in bytes.
let slen = match_.end() - match_.start();
if before {
out.write_all(&data[i..following_line_start])?;
following_line_start = i;
} else {
out.write_all(&data[i + slen..following_line_start])?;
following_line_start = i + slen;
}
}
}
// After the loop terminates, write whatever bytes are remaining at
// the beginning of the buffer.
out.write_all(&data[0..following_line_start])?;
Ok(())
}
/// Write lines from `data` to stdout in reverse.
///
/// This function writes to [`stdout`] each line appearing in `data`,
@ -132,7 +208,7 @@ fn buffer_tac(data: &[u8], before: bool, separator: &str) -> std::io::Result<()>
Ok(())
}
fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {
fn tac(filenames: Vec<String>, before: bool, regex: bool, separator: &str) -> i32 {
let mut exit_code = 0;
for filename in &filenames {
@ -168,9 +244,13 @@ fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {
exit_code = 1;
continue;
};
buffer_tac(&data, before, separator)
.unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e));
if regex {
let pattern = crash_if_err!(1, regex::bytes::Regex::new(separator));
buffer_tac_regex(&data, pattern, before)
} else {
buffer_tac(&data, before, separator)
}
.unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e));
}
exit_code
}

View file

@ -19,6 +19,8 @@ clap = { version = "2.33", features = ["wrap_help"] }
libc = "0.2.42"
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["ringbuffer"] }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
[target.'cfg(windows)'.dependencies]
winapi = { version="0.3", features=["fileapi", "handleapi", "processthreadsapi", "synchapi", "winbase"] }
[target.'cfg(target_os = "redox")'.dependencies]
@ -31,3 +33,7 @@ libc = "0.2"
[[bin]]
name = "tail"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -24,3 +24,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "tee"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -26,3 +26,7 @@ redox_syscall = "0.2"
[[bin]]
name = "test"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -24,3 +24,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "tr"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "truncate"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -22,3 +22,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "tsort"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -23,3 +23,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "unexpand"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -24,3 +24,7 @@ uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_p
[[bin]]
name = "uniq"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -29,3 +29,7 @@ libc = "0.2"
[[bin]]
name = "wc"
path = "src/main.rs"
[package.metadata.cargo-udeps.ignore]
# Necessary for "make all"
normal = ["uucore_procs"]

View file

@ -24,13 +24,15 @@ wild = "2.0"
# * optional
thiserror = { version="1.0", optional=true }
time = { version="<= 0.1.43", optional=true }
walkdir = { version="2.3.2", optional=true }
# * "problem" dependencies (pinned)
data-encoding = { version="2.1", optional=true }
data-encoding-macro = { version="0.1.12", optional=true }
z85 = { version="3.0.3", optional=true }
libc = { version="0.2.15", optional=true }
once_cell = "1.8.0"
[target.'cfg(unix)'.dependencies]
walkdir = { version="2.3.2", optional=true }
nix = { version="0.20", optional=true }
[dev-dependencies]

View file

@ -393,34 +393,56 @@ impl Display for UIoError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
use std::io::ErrorKind::*;
let message;
let message = match self.inner.kind() {
NotFound => "No such file or directory",
PermissionDenied => "Permission denied",
ConnectionRefused => "Connection refused",
ConnectionReset => "Connection reset",
ConnectionAborted => "Connection aborted",
NotConnected => "Not connected",
AddrInUse => "Address in use",
AddrNotAvailable => "Address not available",
BrokenPipe => "Broken pipe",
AlreadyExists => "Already exists",
WouldBlock => "Would block",
InvalidInput => "Invalid input",
InvalidData => "Invalid data",
TimedOut => "Timed out",
WriteZero => "Write zero",
Interrupted => "Interrupted",
UnexpectedEof => "Unexpected end of file",
_ => {
// TODO: using `strip_errno()` causes the error message
// to not be capitalized. When the new error variants (https://github.com/rust-lang/rust/issues/86442)
// are stabilized, we should add them to the match statement.
message = strip_errno(&self.inner);
&message
let mut message;
let message = if self.inner.raw_os_error().is_some() {
// These are errors that come directly from the OS.
// We want to normalize their messages across systems,
// and we want to strip the "(os error X)" suffix.
match self.inner.kind() {
NotFound => "No such file or directory",
PermissionDenied => "Permission denied",
ConnectionRefused => "Connection refused",
ConnectionReset => "Connection reset",
ConnectionAborted => "Connection aborted",
NotConnected => "Not connected",
AddrInUse => "Address in use",
AddrNotAvailable => "Address not available",
BrokenPipe => "Broken pipe",
AlreadyExists => "Already exists",
WouldBlock => "Would block",
InvalidInput => "Invalid input",
InvalidData => "Invalid data",
TimedOut => "Timed out",
WriteZero => "Write zero",
Interrupted => "Interrupted",
UnexpectedEof => "Unexpected end of file",
_ => {
// TODO: When the new error variants
// (https://github.com/rust-lang/rust/issues/86442)
// are stabilized, we should add them to the match statement.
message = strip_errno(&self.inner);
capitalize(&mut message);
&message
}
}
} else {
// These messages don't need as much normalization, and the above
// messages wouldn't always be a good substitute.
// For example, ErrorKind::NotFound doesn't necessarily mean it was
// a file that was not found.
// There are also errors with entirely custom messages.
message = self.inner.to_string();
capitalize(&mut message);
&message
};
write!(f, "{}: {}", self.context, message,)
write!(f, "{}: {}", self.context, message)
}
}
/// Capitalize the first character of an ASCII string.
fn capitalize(text: &mut str) {
if let Some(first) = text.get_mut(..1) {
first.make_ascii_uppercase();
}
}
@ -428,7 +450,7 @@ impl Display for UIoError {
pub fn strip_errno(err: &std::io::Error) -> String {
let mut msg = err.to_string();
if let Some(pos) = msg.find(" (os error ") {
msg.drain(pos..);
msg.truncate(pos);
}
msg
}

View file

@ -1,17 +1,42 @@
//! Custom panic hooks that allow silencing certain types of errors.
//!
//! Use the [`mute_sigpipe_panic`] function to silence panics caused by
//! broken pipe errors. This can happen when a process is still
//! producing data when the consuming process terminates and closes the
//! pipe. For example,
//!
//! ```sh
//! $ seq inf | head -n 1
//! ```
//!
use std::panic;
use std::panic::PanicInfo;
//## SIGPIPE handling background/discussions ...
//* `uutils` ~ <https://github.com/uutils/coreutils/issues/374> , <https://github.com/uutils/coreutils/pull/1106>
//* rust and `rg` ~ <https://github.com/rust-lang/rust/issues/62569> , <https://github.com/BurntSushi/ripgrep/issues/200> , <https://github.com/crev-dev/cargo-crev/issues/287>
/// Decide whether a panic was caused by a broken pipe (SIGPIPE) error.
fn is_broken_pipe(info: &PanicInfo) -> bool {
if let Some(res) = info.payload().downcast_ref::<String>() {
if res.contains("BrokenPipe") || res.contains("Broken pipe") {
return true;
}
}
false
}
/// Terminate without error on panics that occur due to broken pipe errors.
///
/// For background discussions on `SIGPIPE` handling, see
///
/// * https://github.com/uutils/coreutils/issues/374
/// * https://github.com/uutils/coreutils/pull/1106
/// * https://github.com/rust-lang/rust/issues/62569
/// * https://github.com/BurntSushi/ripgrep/issues/200
/// * https://github.com/crev-dev/cargo-crev/issues/287
///
pub fn mute_sigpipe_panic() {
let hook = panic::take_hook();
panic::set_hook(Box::new(move |info| {
if let Some(res) = info.payload().downcast_ref::<String>() {
if res.contains("BrokenPipe") {
return;
}
if !is_broken_pipe(info) {
hook(info)
}
hook(info)
}));
}

View file

@ -9,7 +9,7 @@ use std::os::unix::fs;
#[cfg(unix)]
use std::os::unix::fs::symlink as symlink_file;
#[cfg(unix)]
#[cfg(all(unix, not(target_os = "freebsd")))]
use std::os::unix::fs::PermissionsExt;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;

View file

@ -373,6 +373,7 @@ fn test_ls_long_format() {
/// This test does not really test anything provided by `-l` but the file names and symlinks.
#[cfg(all(feature = "ln", feature = "mkdir", feature = "touch"))]
#[test]
#[cfg(all(feature = "ln", feature = "mkdir", feature = "touch"))]
fn test_ls_long_symlink_color() {
// If you break this test after breaking mkdir, touch, or ln, do not be alarmed!
// This test is made for ls, but it attempts to run those utils in the process.

View file

@ -1,4 +1,5 @@
use crate::common::util::*;
use std::io::Read;
#[test]
fn test_rejects_nan() {
@ -176,3 +177,50 @@ fn test_width_negative_zero() {
.stdout_is("-0\n01\n")
.no_stderr();
}
// TODO This is duplicated from `test_yes.rs`; refactor them.
/// Run `seq`, capture some of the output, close the pipe, and verify it.
fn run(args: &[&str], expected: &[u8]) {
let mut cmd = new_ucmd!();
let mut child = cmd.args(args).run_no_wait();
let mut stdout = child.stdout.take().unwrap();
let mut buf = vec![0; expected.len()];
stdout.read_exact(&mut buf).unwrap();
drop(stdout);
assert!(child.wait().unwrap().success());
assert_eq!(buf.as_slice(), expected);
}
#[test]
fn test_neg_inf() {
run(&["--", "-inf", "0"], b"-inf\n-inf\n-inf\n");
}
#[test]
fn test_inf() {
run(&["inf"], b"1\n2\n3\n");
}
#[test]
fn test_ignore_leading_whitespace() {
new_ucmd!()
.arg(" 1")
.succeeds()
.stdout_is("1\n")
.no_stderr();
}
#[test]
fn test_trailing_whitespace_error() {
// In some locales, the GNU error message has curly quotes ()
// instead of straight quotes ('). We just test the straight single
// quotes.
new_ucmd!()
.arg("1 ")
.fails()
.no_stdout()
.stderr_contains("seq: invalid floating point argument: '1 '")
// FIXME The second line of the error message is "Try 'seq
// --help' for more information."
.stderr_contains("for more information.");
}

View file

@ -1,4 +1,4 @@
// spell-checker:ignore axxbxx bxxaxx axxx axxxx xxaxx xxax xxxxa
// spell-checker:ignore axxbxx bxxaxx axxx axxxx xxaxx xxax xxxxa axyz zyax zyxa
use crate::common::util::*;
#[test]
@ -205,3 +205,67 @@ fn test_null_separator() {
.succeeds()
.stdout_is("b\0a\0");
}
#[test]
fn test_regex() {
new_ucmd!()
.args(&["-r", "-s", "[xyz]+"])
.pipe_in("axyz")
.succeeds()
.no_stderr()
.stdout_is("zyax");
new_ucmd!()
.args(&["-r", "-s", ":+"])
.pipe_in("a:b::c:::d::::")
.succeeds()
.no_stderr()
.stdout_is(":::d:::c::b:a:");
new_ucmd!()
.args(&["-r", "-s", r"[\+]+[-]+[\+]+"])
// line 0 1 2
// |--||-----||--------|
.pipe_in("a+-+b++--++c+d-e+---+")
.succeeds()
.no_stderr()
// line 2 1 0
// |--------||-----||--|
.stdout_is("c+d-e+---+b++--++a+-+");
}
#[test]
fn test_regex_before() {
new_ucmd!()
.args(&["-b", "-r", "-s", "[xyz]+"])
.pipe_in("axyz")
.succeeds()
.no_stderr()
.stdout_is("zyxa");
new_ucmd!()
.args(&["-b", "-r", "-s", ":+"])
.pipe_in(":a::b:::c::::d")
.succeeds()
.stdout_is(":d::::c:::b::a");
// Because `tac` searches for matches of the regular expression from
// right to left, the second to last line is
//
// +--++b
//
// not
//
// ++--++b
//
new_ucmd!()
.args(&["-b", "-r", "-s", r"[\+]+[-]+[\+]+"])
// line 0 1 2
// |---||----||--------|
.pipe_in("+-+a++--++b+---+c+d-e")
.succeeds()
.no_stderr()
// line 2 1 0
// |--------||----||---|
.stdout_is("+---+c+d-e+--++b+-+a+");
}

View file

@ -3,7 +3,7 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
//spell-checker: ignore (linux) rlimit prlimit Rlim coreutil
//spell-checker: ignore (linux) rlimit prlimit Rlim coreutil ggroups
#![allow(dead_code)]
@ -1081,7 +1081,14 @@ pub fn host_name_for(util_name: &str) -> Cow<str> {
// In some environments, e.g. macOS/freebsd, the GNU coreutils are prefixed with "g"
// to not interfere with the BSD counterparts already in `$PATH`.
#[cfg(not(target_os = "linux"))]
return format!("g{}", util_name).into();
{
// make call to `host_name_for` idempotent
if util_name.starts_with('g') && util_name != "groups" {
return util_name.into();
} else {
return format!("g{}", util_name).into();
}
}
#[cfg(target_os = "linux")]
return util_name.into();
}
@ -1195,8 +1202,8 @@ pub fn check_coreutil_version(
///```
#[cfg(unix)]
pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result<CmdResult, String> {
println!("{}", check_coreutil_version(&ts.util_name, VERSION_MIN)?);
let util_name = &host_name_for(&ts.util_name);
println!("{}", check_coreutil_version(util_name, VERSION_MIN)?);
let result = ts
.cmd_keepenv(util_name.as_ref())
@ -1493,4 +1500,25 @@ mod tests {
let ts = TestScenario::new("no test name");
assert!(expected_result(&ts, &[]).is_err());
}
#[test]
#[cfg(unix)]
fn test_host_name_for() {
#[cfg(target_os = "linux")]
{
std::assert_eq!(host_name_for("id"), "id");
std::assert_eq!(host_name_for("groups"), "groups");
std::assert_eq!(host_name_for("who"), "who");
}
#[cfg(not(target_os = "linux"))]
{
// spell-checker:ignore (strings) ggroups gwho
std::assert_eq!(host_name_for("id"), "gid");
std::assert_eq!(host_name_for("groups"), "ggroups");
std::assert_eq!(host_name_for("who"), "gwho");
std::assert_eq!(host_name_for("gid"), "gid");
std::assert_eq!(host_name_for("ggroups"), "ggroups");
std::assert_eq!(host_name_for("gwho"), "gwho");
}
}
}