1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge branch 'master' into issue2147

This commit is contained in:
Jan Scheer 2021-05-01 18:52:35 +02:00
commit 83eb704415
14 changed files with 249 additions and 126 deletions

51
Cargo.lock generated
View file

@ -12,11 +12,11 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "0.7.15"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr 2.3.4",
"memchr 2.4.0",
]
[[package]]
@ -106,12 +106,12 @@ dependencies = [
[[package]]
name = "bstr"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
dependencies = [
"lazy_static",
"memchr 2.3.4",
"memchr 2.4.0",
"regex-automata",
"serde",
]
@ -495,9 +495,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
@ -508,9 +508,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
@ -536,7 +536,7 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr 2.3.4",
"memchr 2.4.0",
]
[[package]]
@ -868,9 +868,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.3.4"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "memoffset"
@ -1089,7 +1089,7 @@ version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid 0.2.1",
"unicode-xid 0.2.2",
]
[[package]]
@ -1277,12 +1277,12 @@ dependencies = [
[[package]]
name = "regex"
version = "1.4.6"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
checksum = "1efb2352a0f4d4b128f734b5c44c79ff80117351138733f12f982fe3e2b13343"
dependencies = [
"aho-corasick",
"memchr 2.3.4",
"memchr 2.4.0",
"regex-syntax",
]
@ -1297,9 +1297,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.23"
version = "0.6.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
checksum = "00efb87459ba4f6fb2169d20f68565555688e1250ee6825cdf6254f8b48fafb2"
[[package]]
name = "remove_dir_all"
@ -1489,7 +1489,7 @@ checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"unicode-xid 0.2.1",
"unicode-xid 0.2.2",
]
[[package]]
@ -1636,9 +1636,9 @@ checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
[[package]]
name = "unicode-xid"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "unindent"
@ -1806,7 +1806,7 @@ version = "0.0.6"
dependencies = [
"bstr",
"clap",
"memchr 2.3.4",
"memchr 2.4.0",
"uucore",
"uucore_procs",
]
@ -2175,7 +2175,7 @@ dependencies = [
"aho-corasick",
"clap",
"libc",
"memchr 2.3.4",
"memchr 2.4.0",
"regex",
"regex-syntax",
"uucore",
@ -2247,6 +2247,7 @@ dependencies = [
name = "uu_pinky"
version = "0.0.6"
dependencies = [
"clap",
"uucore",
"uucore_procs",
]
@ -2276,7 +2277,7 @@ dependencies = [
"aho-corasick",
"clap",
"libc",
"memchr 2.3.4",
"memchr 2.4.0",
"regex",
"regex-syntax",
"uucore",

View file

@ -12,37 +12,42 @@ use clap::{App, Arg};
use std::path::Path;
use uucore::InvalidEncodingHandling;
static NAME: &str = "dirname";
static SYNTAX: &str = "[OPTION] NAME...";
static SUMMARY: &str = "strip last component from file name";
static ABOUT: &str = "strip last component from file name";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static LONG_HELP: &str = "
Output each NAME with its last non-slash component and trailing slashes
removed; if NAME contains no /'s, output '.' (meaning the current
directory).
";
mod options {
pub const ZERO: &str = "zero";
pub const DIR: &str = "dir";
}
fn get_usage() -> String {
format!("{0} [OPTION] NAME...", executable!())
}
fn get_long_usage() -> String {
String::from(
"Output each NAME with its last non-slash component and trailing slashes
removed; if NAME contains no /'s, output '.' (meaning the current directory).",
)
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let usage = get_usage();
let after_help = get_long_usage();
let matches = App::new(executable!())
.name(NAME)
.usage(SYNTAX)
.about(SUMMARY)
.after_help(LONG_HELP)
.about(ABOUT)
.usage(&usage[..])
.after_help(&after_help[..])
.version(VERSION)
.arg(
Arg::with_name(options::ZERO)
.short(options::ZERO)
.long(options::ZERO)
.short("z")
.takes_value(false)
.help("separate output with NUL rather than newline"),
)
.arg(Arg::with_name(options::DIR).hidden(true).multiple(true))

View file

@ -125,7 +125,7 @@ fn _factor<A: Arithmetic + miller_rabin::Basis>(num: u64, f: Factors) -> Factors
let n = A::new(num);
let divisor = match miller_rabin::test::<A>(n) {
Prime => {
#[cfg(feature="coz")]
#[cfg(feature = "coz")]
coz::progress!("factor found");
let mut r = f;
r.push(num);
@ -141,7 +141,7 @@ fn _factor<A: Arithmetic + miller_rabin::Basis>(num: u64, f: Factors) -> Factors
}
pub fn factor(mut n: u64) -> Factors {
#[cfg(feature="coz")]
#[cfg(feature = "coz")]
coz::begin!("factorization");
let mut factors = Factors::one();
@ -156,7 +156,7 @@ pub fn factor(mut n: u64) -> Factors {
}
if n == 1 {
#[cfg(feature="coz")]
#[cfg(feature = "coz")]
coz::end!("factorization");
return factors;
}
@ -169,7 +169,7 @@ pub fn factor(mut n: u64) -> Factors {
_factor::<Montgomery<u64>>(n, factors)
};
#[cfg(feature="coz")]
#[cfg(feature = "coz")]
coz::end!("factorization");
return r;

View file

@ -33,7 +33,7 @@ pub(crate) fn factor(mut num: u64, mut factors: Factors) -> (Factors, u64) {
if x <= ceil {
num = x;
k += 1;
#[cfg(feature="coz")]
#[cfg(feature = "coz")]
coz::progress!("factor found");
} else {
if k > 0 {

View file

@ -17,6 +17,7 @@ path = "src/pinky.rs"
[dependencies]
uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["utmpx", "entries"] }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
clap = "2.33.3"
[[bin]]
name = "pinky"

View file

@ -19,67 +19,110 @@ use std::io::BufReader;
use std::fs::File;
use std::os::unix::fs::MetadataExt;
use clap::{App, Arg};
use std::path::PathBuf;
use uucore::InvalidEncodingHandling;
static SYNTAX: &str = "[OPTION]... [USER]...";
static SUMMARY: &str = "A lightweight 'finger' program; print user information.";
const BUFSIZE: usize = 1024;
static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "pinky - lightweight finger";
mod options {
pub const LONG_FORMAT: &str = "long_format";
pub const OMIT_HOME_DIR: &str = "omit_home_dir";
pub const OMIT_PROJECT_FILE: &str = "omit_project_file";
pub const OMIT_PLAN_FILE: &str = "omit_plan_file";
pub const SHORT_FORMAT: &str = "short_format";
pub const OMIT_HEADINGS: &str = "omit_headings";
pub const OMIT_NAME: &str = "omit_name";
pub const OMIT_NAME_HOST: &str = "omit_name_host";
pub const OMIT_NAME_HOST_TIME: &str = "omit_name_host_time";
pub const USER: &str = "user";
}
fn get_usage() -> String {
format!("{0} [OPTION]... [USER]...", executable!())
}
fn get_long_usage() -> String {
format!(
"A lightweight 'finger' program; print user information.\n\
The utmp file will be {}.",
utmpx::DEFAULT_FILE
)
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let long_help = &format!(
"
-l produce long format output for the specified USERs
-b omit the user's home directory and shell in long format
-h omit the user's project file in long format
-p omit the user's plan file in long format
-s do short format output, this is the default
-f omit the line of column headings in short format
-w omit the user's full name in short format
-i omit the user's full name and remote host in short format
-q omit the user's full name, remote host and idle time
in short format
--help display this help and exit
--version output version information and exit
let usage = get_usage();
let after_help = get_long_usage();
The utmp file will be {}",
utmpx::DEFAULT_FILE
);
let mut opts = app!(SYNTAX, SUMMARY, &long_help);
opts.optflag(
"l",
"",
"produce long format output for the specified USERs",
);
opts.optflag(
"b",
"",
"omit the user's home directory and shell in long format",
);
opts.optflag("h", "", "omit the user's project file in long format");
opts.optflag("p", "", "omit the user's plan file in long format");
opts.optflag("s", "", "do short format output, this is the default");
opts.optflag("f", "", "omit the line of column headings in short format");
opts.optflag("w", "", "omit the user's full name in short format");
opts.optflag(
"i",
"",
"omit the user's full name and remote host in short format",
);
opts.optflag(
"q",
"",
"omit the user's full name, remote host and idle time in short format",
);
opts.optflag("", "help", "display this help and exit");
opts.optflag("", "version", "output version information and exit");
let matches = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.after_help(&after_help[..])
.arg(
Arg::with_name(options::LONG_FORMAT)
.short("l")
.requires(options::USER)
.help("produce long format output for the specified USERs"),
)
.arg(
Arg::with_name(options::OMIT_HOME_DIR)
.short("b")
.help("omit the user's home directory and shell in long format"),
)
.arg(
Arg::with_name(options::OMIT_PROJECT_FILE)
.short("h")
.help("omit the user's project file in long format"),
)
.arg(
Arg::with_name(options::OMIT_PLAN_FILE)
.short("p")
.help("omit the user's plan file in long format"),
)
.arg(
Arg::with_name(options::SHORT_FORMAT)
.short("s")
.help("do short format output, this is the default"),
)
.arg(
Arg::with_name(options::OMIT_HEADINGS)
.short("f")
.help("omit the line of column headings in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME)
.short("w")
.help("omit the user's full name in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME_HOST)
.short("i")
.help("omit the user's full name and remote host in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME_HOST_TIME)
.short("q")
.help("omit the user's full name, remote host and idle time in short format"),
)
.arg(
Arg::with_name(options::USER)
.takes_value(true)
.multiple(true),
)
.get_matches_from(args);
let matches = opts.parse(args);
let users: Vec<String> = matches
.values_of(options::USER)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
// If true, display the hours:minutes since each user has touched
// the keyboard, or blank if within the last minute, or days followed
@ -87,45 +130,40 @@ The utmp file will be {}",
let mut include_idle = true;
// If true, display a line at the top describing each field.
let include_heading = !matches.opt_present("f");
let include_heading = !matches.is_present(options::OMIT_HEADINGS);
// if true, display the user's full name from pw_gecos.
let mut include_fullname = true;
// if true, display the user's ~/.project file when doing long format.
let include_project = !matches.opt_present("h");
let include_project = !matches.is_present(options::OMIT_PROJECT_FILE);
// if true, display the user's ~/.plan file when doing long format.
let include_plan = !matches.opt_present("p");
let include_plan = !matches.is_present(options::OMIT_PLAN_FILE);
// if true, display the user's home directory and shell
// when doing long format.
let include_home_and_shell = !matches.opt_present("b");
let include_home_and_shell = !matches.is_present(options::OMIT_HOME_DIR);
// if true, use the "short" output format.
let do_short_format = !matches.opt_present("l");
let do_short_format = !matches.is_present(options::LONG_FORMAT);
/* if true, display the ut_host field. */
let mut include_where = true;
if matches.opt_present("w") {
if matches.is_present(options::OMIT_NAME) {
include_fullname = false;
}
if matches.opt_present("i") {
if matches.is_present(options::OMIT_NAME_HOST) {
include_fullname = false;
include_where = false;
}
if matches.opt_present("q") {
if matches.is_present(options::OMIT_NAME_HOST_TIME) {
include_fullname = false;
include_idle = false;
include_where = false;
}
if !do_short_format && matches.free.is_empty() {
show_usage_error!("no username specified; at least one must be specified when using -l");
return 1;
}
let pk = Pinky {
include_idle,
include_heading,
@ -134,7 +172,7 @@ The utmp file will be {}",
include_plan,
include_home_and_shell,
include_where,
names: matches.free,
names: users,
};
if do_short_format {

View file

@ -158,7 +158,6 @@ pub fn base_conv_float(src: &[u8], radix_src: u8, _radix_dest: u8) -> f64 {
// to implement this for arbitrary string input.
// until then, the below operates as an outline
// of how it would work.
let result: Vec<u8> = vec![0];
let mut factor: f64 = 1_f64;
let radix_src_float: f64 = f64::from(radix_src);
let mut r: f64 = 0_f64;

View file

@ -23,11 +23,9 @@ use std::io::{stdin, stdout, BufRead, BufWriter, Write};
use crate::expand::ExpandSet;
use uucore::InvalidEncodingHandling;
static NAME: &str = "tr";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "translate or delete characters";
static LONG_HELP: &str = "Translate, squeeze, and/or delete characters from standard input,
writing to standard output.";
const BUFFER_LEN: usize = 1024;
mod options {
@ -205,24 +203,38 @@ fn get_usage() -> String {
format!("{} [OPTION]... SET1 [SET2]", executable!())
}
fn get_long_usage() -> String {
String::from(
"Translate, squeeze, and/or delete characters from standard input,
writing to standard output.",
)
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let args = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let usage = get_usage();
let after_help = get_long_usage();
let matches = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.after_help(&after_help[..])
.arg(
Arg::with_name(options::COMPLEMENT)
.short("C")
// .visible_short_alias('C') // TODO: requires clap "3.0.0-beta.2"
.short("c")
.long(options::COMPLEMENT)
.help("use the complement of SET1"),
)
.arg(
Arg::with_name("C") // work around for `Arg::visible_short_alias`
.short("C")
.help("same as -c"),
)
.arg(
Arg::with_name(options::DELETE)
.short("d")
@ -235,8 +247,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.short("s")
.help(
"replace each sequence of a repeated character that is
listed in the last specified SET, with a single occurrence
of that character",
listed in the last specified SET, with a single occurrence
of that character",
),
)
.arg(
@ -249,7 +261,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.get_matches_from(args);
let delete_flag = matches.is_present(options::DELETE);
let complement_flag = matches.is_present(options::COMPLEMENT);
let complement_flag = matches.is_present(options::COMPLEMENT) || matches.is_present("C");
let squeeze_flag = matches.is_present(options::SQUEEZE);
let truncate_flag = matches.is_present(options::TRUNCATE);
@ -261,7 +273,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if sets.is_empty() {
show_error!(
"missing operand\nTry `{} --help` for more information.",
NAME
executable!()
);
return 1;
}
@ -270,7 +282,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
show_error!(
"missing operand after {}\nTry `{} --help` for more information.",
sets[0],
NAME
executable!()
);
return 1;
}

View file

@ -16,6 +16,21 @@ fn test_path_without_trailing_slashes() {
.stdout_is("/root/alpha/beta/gamma/delta/epsilon\n");
}
#[test]
fn test_path_without_trailing_slashes_and_zero() {
new_ucmd!()
.arg("-z")
.arg("/root/alpha/beta/gamma/delta/epsilon/omega")
.succeeds()
.stdout_is("/root/alpha/beta/gamma/delta/epsilon\u{0}");
new_ucmd!()
.arg("--zero")
.arg("/root/alpha/beta/gamma/delta/epsilon/omega")
.succeeds()
.stdout_is("/root/alpha/beta/gamma/delta/epsilon\u{0}");
}
#[test]
fn test_root() {
new_ucmd!().arg("/").run().stdout_is("/\n");

View file

@ -559,6 +559,7 @@ fn test_ls_long_ctime() {
}
#[test]
#[ignore]
fn test_ls_order_birthtime() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
@ -583,6 +584,7 @@ fn test_ls_order_birthtime() {
}
#[test]
#[ignore]
fn test_ls_styles() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;

View file

@ -34,6 +34,36 @@ fn test_long_format() {
));
}
#[cfg(target_os = "linux")]
#[test]
fn test_long_format_multiple_users() {
let scene = TestScenario::new(util_name!());
let expected = scene
.cmd_keepenv(util_name!())
.env("LANGUAGE", "C")
.arg("-l")
.arg("root")
.arg("root")
.arg("root")
.succeeds();
scene
.ucmd()
.arg("-l")
.arg("root")
.arg("root")
.arg("root")
.succeeds()
.stdout_is(expected.stdout_str());
}
#[test]
fn test_long_format_wo_user() {
// "no username specified; at least one must be specified when using -l"
new_ucmd!().arg("-l").fails().code_is(1);
}
#[cfg(target_os = "linux")]
#[test]
fn test_short_format_i() {

View file

@ -16,15 +16,15 @@ fn test_helper(file_name: &str, args: &str) {
}
// FYI, the initialization size of our Line struct is 96 bytes.
//
// At very small buffer sizes, with that overhead we are certainly going
// to overrun our buffer way, way, way too quickly because of these excess
//
// At very small buffer sizes, with that overhead we are certainly going
// to overrun our buffer way, way, way too quickly because of these excess
// bytes for the struct.
//
// For instance, seq 0..20000 > ...text = 108894 bytes
// But overhead is 1920000 + 108894 = 2028894 bytes
//
// Or kjvbible-random.txt = 4332506 bytes, but minimum size of its
// Or kjvbible-random.txt = 4332506 bytes, but minimum size of its
// 99817 lines in memory * 96 bytes = 9582432 bytes
//
// Here, we test 108894 bytes with a 50K buffer
@ -59,7 +59,7 @@ fn test_human_numeric_whitespace() {
test_helper("human-numeric-whitespace", "-h");
}
// This tests where serde often fails when reading back JSON
// This tests where serde often fails when reading back JSON
// if it finds a null value
#[test]
fn test_extsort_as64_bailout() {

View file

@ -45,6 +45,20 @@ fn test_delete_complement() {
.stdout_is("ac");
}
#[test]
fn test_delete_complement_2() {
new_ucmd!()
.args(&["-d", "-C", "0-9"])
.pipe_in("Phone: 01234 567890")
.succeeds()
.stdout_is("01234567890");
new_ucmd!()
.args(&["-d", "--complement", "0-9"])
.pipe_in("Phone: 01234 567890")
.succeeds()
.stdout_is("01234567890");
}
#[test]
fn test_complement1() {
new_ucmd!()

View file

@ -224,8 +224,14 @@ fn test_size_and_reference() {
let mut file1 = at.make_file(TFILE1);
let mut file2 = at.make_file(TFILE2);
file1.write_all(b"1234567890").unwrap();
ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2]).succeeds();
ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2])
.succeeds();
file2.seek(SeekFrom::End(0)).unwrap();
let actual = file2.seek(SeekFrom::Current(0)).unwrap();
assert!(expected == actual, "expected '{}' got '{}'", expected, actual);
assert!(
expected == actual,
"expected '{}' got '{}'",
expected,
actual
);
}