From 448caa3d1c09272868e3dad71c8edb24c5cd432e Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Mon, 7 Jun 2021 14:51:58 +0200 Subject: [PATCH 01/33] ln: refactor argument handling --- src/uu/ln/src/ln.rs | 111 ++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/src/uu/ln/src/ln.rs b/src/uu/ln/src/ln.rs index cd5eef842..3d40b6bab 100644 --- a/src/uu/ln/src/ln.rs +++ b/src/uu/ln/src/ln.rs @@ -78,17 +78,19 @@ fn get_long_usage() -> String { static ABOUT: &str = "change file owner and group"; -static OPT_B: &str = "b"; -static OPT_BACKUP: &str = "backup"; -static OPT_FORCE: &str = "force"; -static OPT_INTERACTIVE: &str = "interactive"; -static OPT_NO_DEREFERENCE: &str = "no-dereference"; -static OPT_SYMBOLIC: &str = "symbolic"; -static OPT_SUFFIX: &str = "suffix"; -static OPT_TARGET_DIRECTORY: &str = "target-directory"; -static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory"; -static OPT_RELATIVE: &str = "relative"; -static OPT_VERBOSE: &str = "verbose"; +mod options { + pub const B: &str = "b"; + pub const BACKUP: &str = "backup"; + pub const FORCE: &str = "force"; + pub const INTERACTIVE: &str = "interactive"; + pub const NO_DEREFERENCE: &str = "no-dereference"; + pub const SYMBOLIC: &str = "symbolic"; + pub const SUFFIX: &str = "suffix"; + pub const TARGET_DIRECTORY: &str = "target-directory"; + pub const NO_TARGET_DIRECTORY: &str = "no-target-directory"; + pub const RELATIVE: &str = "relative"; + pub const VERBOSE: &str = "verbose"; +} static ARG_FILES: &str = "files"; @@ -101,47 +103,42 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .about(ABOUT) .usage(&usage[..]) .after_help(&long_usage[..]) - .arg(Arg::with_name(OPT_B).short(OPT_B).help( + .arg(Arg::with_name(options::B).short(options::B).help( "make a backup of each file that would otherwise be overwritten or \ removed", )) .arg( - Arg::with_name(OPT_BACKUP) - .long(OPT_BACKUP) + Arg::with_name(options::BACKUP) + .long(options::BACKUP) .help( "make a backup of each file that would otherwise be overwritten \ or removed", ) .takes_value(true) - .possible_value("simple") - .possible_value("never") - .possible_value("numbered") - .possible_value("t") - .possible_value("existing") - .possible_value("nil") - .possible_value("none") - .possible_value("off") + .possible_values(&[ + "simple", "never", "numbered", "t", "existing", "nil", "none", "off", + ]) .value_name("METHOD"), ) // TODO: opts.arg( // Arg::with_name(("d", "directory", "allow users with appropriate privileges to attempt \ // to make hard links to directories"); .arg( - Arg::with_name(OPT_FORCE) + Arg::with_name(options::FORCE) .short("f") - .long(OPT_FORCE) + .long(options::FORCE) .help("remove existing destination files"), ) .arg( - Arg::with_name(OPT_INTERACTIVE) + Arg::with_name(options::INTERACTIVE) .short("i") - .long(OPT_INTERACTIVE) + .long(options::INTERACTIVE) .help("prompt whether to remove existing destination files"), ) .arg( - Arg::with_name(OPT_NO_DEREFERENCE) + Arg::with_name(options::NO_DEREFERENCE) .short("n") - .long(OPT_NO_DEREFERENCE) + .long(options::NO_DEREFERENCE) .help( "treat LINK_executable!() as a normal file if it is a \ symbolic link to a directory", @@ -153,43 +150,45 @@ pub fn uumain(args: impl uucore::Args) -> i32 { // TODO: opts.arg( // Arg::with_name(("P", "physical", "make hard links directly to symbolic links"); .arg( - Arg::with_name(OPT_SYMBOLIC) + Arg::with_name(options::SYMBOLIC) .short("s") .long("symbolic") - .help("make symbolic links instead of hard links"), + .help("make symbolic links instead of hard links") + // override added for https://github.com/uutils/coreutils/issues/2359 + .overrides_with(options::SYMBOLIC), ) .arg( - Arg::with_name(OPT_SUFFIX) + Arg::with_name(options::SUFFIX) .short("S") - .long(OPT_SUFFIX) + .long(options::SUFFIX) .help("override the usual backup suffix") .value_name("SUFFIX") .takes_value(true), ) .arg( - Arg::with_name(OPT_TARGET_DIRECTORY) + Arg::with_name(options::TARGET_DIRECTORY) .short("t") - .long(OPT_TARGET_DIRECTORY) + .long(options::TARGET_DIRECTORY) .help("specify the DIRECTORY in which to create the links") .value_name("DIRECTORY") - .conflicts_with(OPT_NO_TARGET_DIRECTORY), + .conflicts_with(options::NO_TARGET_DIRECTORY), ) .arg( - Arg::with_name(OPT_NO_TARGET_DIRECTORY) + Arg::with_name(options::NO_TARGET_DIRECTORY) .short("T") - .long(OPT_NO_TARGET_DIRECTORY) + .long(options::NO_TARGET_DIRECTORY) .help("treat LINK_executable!() as a normal file always"), ) .arg( - Arg::with_name(OPT_RELATIVE) + Arg::with_name(options::RELATIVE) .short("r") - .long(OPT_RELATIVE) + .long(options::RELATIVE) .help("create symbolic links relative to link location"), ) .arg( - Arg::with_name(OPT_VERBOSE) + Arg::with_name(options::VERBOSE) .short("v") - .long(OPT_VERBOSE) + .long(options::VERBOSE) .help("print name of each linked file"), ) .arg( @@ -209,18 +208,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .map(PathBuf::from) .collect(); - let overwrite_mode = if matches.is_present(OPT_FORCE) { + let overwrite_mode = if matches.is_present(options::FORCE) { OverwriteMode::Force - } else if matches.is_present(OPT_INTERACTIVE) { + } else if matches.is_present(options::INTERACTIVE) { OverwriteMode::Interactive } else { OverwriteMode::NoClobber }; - let backup_mode = if matches.is_present(OPT_B) { + let backup_mode = if matches.is_present(options::B) { BackupMode::ExistingBackup - } else if matches.is_present(OPT_BACKUP) { - match matches.value_of(OPT_BACKUP) { + } else if matches.is_present(options::BACKUP) { + match matches.value_of(options::BACKUP) { None => BackupMode::ExistingBackup, Some(mode) => match mode { "simple" | "never" => BackupMode::SimpleBackup, @@ -234,8 +233,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 { BackupMode::NoBackup }; - let backup_suffix = if matches.is_present(OPT_SUFFIX) { - matches.value_of(OPT_SUFFIX).unwrap() + let backup_suffix = if matches.is_present(options::SUFFIX) { + matches.value_of(options::SUFFIX).unwrap() } else { "~" }; @@ -243,14 +242,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let settings = Settings { overwrite: overwrite_mode, backup: backup_mode, - force: matches.is_present(OPT_FORCE), + force: matches.is_present(options::FORCE), suffix: backup_suffix.to_string(), - symbolic: matches.is_present(OPT_SYMBOLIC), - relative: matches.is_present(OPT_RELATIVE), - target_dir: matches.value_of(OPT_TARGET_DIRECTORY).map(String::from), - no_target_dir: matches.is_present(OPT_NO_TARGET_DIRECTORY), - no_dereference: matches.is_present(OPT_NO_DEREFERENCE), - verbose: matches.is_present(OPT_VERBOSE), + symbolic: matches.is_present(options::SYMBOLIC), + relative: matches.is_present(options::RELATIVE), + target_dir: matches + .value_of(options::TARGET_DIRECTORY) + .map(String::from), + no_target_dir: matches.is_present(options::NO_TARGET_DIRECTORY), + no_dereference: matches.is_present(options::NO_DEREFERENCE), + verbose: matches.is_present(options::VERBOSE), }; exec(&paths[..], &settings) From d846c403724be80714b090b0b7bad507ddbb06b8 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Tue, 8 Jun 2021 21:45:02 +0200 Subject: [PATCH 02/33] groups: fix test for arch --- tests/by-util/test_groups.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 26ab6a75a..657503471 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -13,7 +13,7 @@ fn test_groups() { } #[test] -#[cfg(any(target_os = "linux"))] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[ignore = "fixme: 'groups USERNAME' needs more debugging"] fn test_groups_username() { let scene = TestScenario::new(util_name!()); @@ -39,15 +39,13 @@ fn test_groups_username() { #[cfg(any(target_vendor = "apple", target_os = "linux"))] fn expected_result(args: &[&str]) -> String { - #[cfg(target_os = "linux")] - let util_name = util_name!(); - #[cfg(target_vendor = "apple")] - let util_name = format!("g{}", util_name!()); + let util_name = "id"; TestScenario::new(&util_name) .cmd_keepenv(util_name) .env("LANGUAGE", "C") .args(args) + .args(&["-Gn"]) .succeeds() .stdout_move_str() } From 06b6066e89bfe32bcff277ff41e8adfe8cbed1dd Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Tue, 8 Jun 2021 22:53:48 +0200 Subject: [PATCH 03/33] groups: enable tests for non-linux unix systems --- tests/by-util/test_groups.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 657503471..af0334e5a 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -1,7 +1,7 @@ use crate::common::util::*; #[test] -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] fn test_groups() { if !is_ci() { new_ucmd!().succeeds().stdout_is(expected_result(&[])); @@ -13,7 +13,7 @@ fn test_groups() { } #[test] -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[ignore = "fixme: 'groups USERNAME' needs more debugging"] fn test_groups_username() { let scene = TestScenario::new(util_name!()); @@ -37,9 +37,14 @@ fn test_groups_username() { .stdout_is(expected_result(&[&username])); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] fn expected_result(args: &[&str]) -> String { + // We want to use GNU id. On most linux systems, this is "id", but on + // bsd-like systems (e.g. FreeBSD, MacOS), it is commonly "gid". + #[cfg(any(target_os = "linux"))] let util_name = "id"; + #[cfg(not(target_os = "linux"))] + let util_name = "gid"; TestScenario::new(&util_name) .cmd_keepenv(util_name) From 145e705b746d0bdf777ea180a99de70e7cd5a509 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 9 Jun 2021 12:39:25 +0200 Subject: [PATCH 04/33] groups: fix clippy lint in test --- tests/by-util/test_groups.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index af0334e5a..c1b98aea1 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -46,7 +46,7 @@ fn expected_result(args: &[&str]) -> String { #[cfg(not(target_os = "linux"))] let util_name = "gid"; - TestScenario::new(&util_name) + TestScenario::new(util_name) .cmd_keepenv(util_name) .env("LANGUAGE", "C") .args(args) From 3818e5441594b1ed439e2b4bf0fc17dae60223e5 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 9 Jun 2021 14:34:37 +0200 Subject: [PATCH 05/33] who: cleanup argument handling --- src/uu/who/src/who.rs | 126 ++++++++++-------------------------------- 1 file changed, 30 insertions(+), 96 deletions(-) diff --git a/src/uu/who/src/who.rs b/src/uu/who/src/who.rs index d2f64aa94..44f565438 100644 --- a/src/uu/who/src/who.rs +++ b/src/uu/who/src/who.rs @@ -179,124 +179,58 @@ pub fn uumain(args: impl uucore::Args) -> i32 { // Ignored for 'who am i'. let short_list = matches.is_present(options::COUNT); - // If true, display only name, line, and time fields. - let mut short_output = false; - - // If true, display the hours:minutes since each user has touched - // the keyboard, or "." if within the last minute, or "old" if - // not within the last day. - let mut include_idle = false; + let all = matches.is_present(options::ALL); // If true, display a line at the top describing each field. let include_heading = matches.is_present(options::HEADING); // If true, display a '+' for each user if mesg y, a '-' if mesg n, // or a '?' if their tty cannot be statted. - let include_mesg = matches.is_present(options::ALL) - || matches.is_present(options::MESG) - || matches.is_present("w"); - - // If true, display process termination & exit status. - let mut include_exit = false; + let include_mesg = all || matches.is_present(options::MESG) || matches.is_present("w"); // If true, display the last boot time. - let mut need_boottime = false; + let need_boottime = all || matches.is_present(options::BOOT); // If true, display dead processes. - let mut need_deadprocs = false; + let need_deadprocs = all || matches.is_present(options::DEAD); // If true, display processes waiting for user login. - let mut need_login = false; + let need_login = all || matches.is_present(options::LOGIN); // If true, display processes started by init. - let mut need_initspawn = false; + let need_initspawn = all || matches.is_present(options::PROCESS); // If true, display the last clock change. - let mut need_clockchange = false; + let need_clockchange = all || matches.is_present(options::TIME); // If true, display the current runlevel. - let mut need_runlevel = false; + let need_runlevel = all || matches.is_present(options::RUNLEVEL); + + let use_defaults = !(all + || need_boottime + || need_deadprocs + || need_login + || need_initspawn + || need_runlevel + || need_clockchange + || matches.is_present(options::USERS)); // If true, display user processes. - let mut need_users = false; + let need_users = all || matches.is_present(options::USERS) || use_defaults; + + // If true, display the hours:minutes since each user has touched + // the keyboard, or "." if within the last minute, or "old" if + // not within the last day. + let include_idle = need_deadprocs || need_login || need_runlevel || need_users; + + // If true, display process termination & exit status. + let include_exit = need_deadprocs; + + // If true, display only name, line, and time fields. + let short_output = !include_exit && use_defaults; // If true, display info only for the controlling tty. - let mut my_line_only = false; - - let mut assumptions = true; - - #[allow(clippy::useless_let_if_seq)] - { - if matches.is_present(options::ALL) { - need_boottime = true; - need_deadprocs = true; - need_login = true; - need_initspawn = true; - need_runlevel = true; - need_clockchange = true; - need_users = true; - include_idle = true; - include_exit = true; - assumptions = false; - } - - if matches.is_present(options::BOOT) { - need_boottime = true; - assumptions = false; - } - - if matches.is_present(options::DEAD) { - need_deadprocs = true; - include_idle = true; - include_exit = true; - assumptions = false; - } - - if matches.is_present(options::LOGIN) { - need_login = true; - include_idle = true; - assumptions = false; - } - - if matches.is_present(options::ONLY_HOSTNAME_USER) || files.len() == 2 { - my_line_only = true; - } - - if matches.is_present(options::PROCESS) { - need_initspawn = true; - assumptions = false; - } - - if matches.is_present(options::RUNLEVEL) { - need_runlevel = true; - include_idle = true; - assumptions = false; - } - - if matches.is_present(options::SHORT) { - short_output = true; - } - - if matches.is_present(options::TIME) { - need_clockchange = true; - assumptions = false; - } - - if matches.is_present(options::USERS) { - need_users = true; - include_idle = true; - assumptions = false; - } - - if assumptions { - need_users = true; - short_output = true; - } - - if include_exit { - short_output = false; - } - } + let my_line_only = matches.is_present(options::ONLY_HOSTNAME_USER) || files.len() == 2; let mut who = Who { do_lookup, From 8ae4a8d06e20221a801d779f5b97d4ac8708bec7 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 9 Jun 2021 14:37:19 +0200 Subject: [PATCH 06/33] Revert "groups: fix test for arch" This reverts commit d846c403724be80714b090b0b7bad507ddbb06b8. --- tests/by-util/test_groups.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 657503471..26ab6a75a 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -13,7 +13,7 @@ fn test_groups() { } #[test] -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(any(target_os = "linux"))] #[ignore = "fixme: 'groups USERNAME' needs more debugging"] fn test_groups_username() { let scene = TestScenario::new(util_name!()); @@ -39,13 +39,15 @@ fn test_groups_username() { #[cfg(any(target_vendor = "apple", target_os = "linux"))] fn expected_result(args: &[&str]) -> String { - let util_name = "id"; + #[cfg(target_os = "linux")] + let util_name = util_name!(); + #[cfg(target_vendor = "apple")] + let util_name = format!("g{}", util_name!()); TestScenario::new(&util_name) .cmd_keepenv(util_name) .env("LANGUAGE", "C") .args(args) - .args(&["-Gn"]) .succeeds() .stdout_move_str() } From f40f9fbf91298f920e0ce5760768c5a083e5db08 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 9 Jun 2021 23:51:04 +0900 Subject: [PATCH 07/33] Fix build when not(feature = "process") --- src/uucore/src/lib/features/entries.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uucore/src/lib/features/entries.rs b/src/uucore/src/lib/features/entries.rs index b94abbe4f..988d88fd3 100644 --- a/src/uucore/src/lib/features/entries.rs +++ b/src/uucore/src/lib/features/entries.rs @@ -94,6 +94,7 @@ pub fn get_groups() -> IOResult> { /// groups is the same (in the mathematical sense of ``set''). (The /// history of a process and its parents could affect the details of /// the result.) +#[cfg(all(unix, feature = "process"))] pub fn get_groups_gnu(arg_id: Option) -> IOResult> { let mut groups = get_groups()?; let egid = arg_id.unwrap_or_else(crate::features::process::getegid); From 394eb82af1be3aa44abb857e38199c4888fc5074 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 9 Jun 2021 17:07:44 +0200 Subject: [PATCH 08/33] cat/cut/tty/nohup: replace is_std{in, out, err}_interactive with atty --- Cargo.lock | 4 +++ src/uu/cat/Cargo.toml | 1 + src/uu/cat/src/cat.rs | 3 +-- src/uu/cut/Cargo.toml | 1 + src/uu/cut/src/cut.rs | 3 +-- src/uu/nohup/Cargo.toml | 1 + src/uu/nohup/src/nohup.rs | 7 +++-- src/uu/tty/Cargo.toml | 1 + src/uu/tty/src/tty.rs | 3 +-- src/uucore/src/lib/features/fs.rs | 45 ------------------------------- 10 files changed, 14 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b2d989be..931bff981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1772,6 +1772,7 @@ dependencies = [ name = "uu_cat" version = "0.0.6" dependencies = [ + "atty", "clap", "nix 0.20.0", "thiserror", @@ -1872,6 +1873,7 @@ dependencies = [ name = "uu_cut" version = "0.0.6" dependencies = [ + "atty", "bstr", "clap", "memchr 2.4.0", @@ -2262,6 +2264,7 @@ dependencies = [ name = "uu_nohup" version = "0.0.6" dependencies = [ + "atty", "clap", "libc", "uucore", @@ -2660,6 +2663,7 @@ dependencies = [ name = "uu_tty" version = "0.0.6" dependencies = [ + "atty", "clap", "libc", "uucore", diff --git a/src/uu/cat/Cargo.toml b/src/uu/cat/Cargo.toml index 09b289253..9218e84fe 100644 --- a/src/uu/cat/Cargo.toml +++ b/src/uu/cat/Cargo.toml @@ -17,6 +17,7 @@ path = "src/cat.rs" [dependencies] clap = "2.33" thiserror = "1.0" +atty = "0.2" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index 005802ce5..889ba424a 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -20,7 +20,6 @@ use clap::{crate_version, App, Arg}; use std::fs::{metadata, File}; use std::io::{self, Read, Write}; use thiserror::Error; -use uucore::fs::is_stdin_interactive; /// Linux splice support #[cfg(any(target_os = "linux", target_os = "android"))] @@ -306,7 +305,7 @@ fn cat_path(path: &str, options: &OutputOptions, state: &mut OutputState) -> Cat #[cfg(any(target_os = "linux", target_os = "android"))] file_descriptor: stdin.as_raw_fd(), reader: stdin, - is_interactive: is_stdin_interactive(), + is_interactive: atty::is(atty::Stream::Stdin), }; return cat_handle(&mut handle, options, state); } diff --git a/src/uu/cut/Cargo.toml b/src/uu/cut/Cargo.toml index c863c1772..47b8223c5 100644 --- a/src/uu/cut/Cargo.toml +++ b/src/uu/cut/Cargo.toml @@ -20,6 +20,7 @@ uucore = { version=">=0.0.8", package="uucore", path="../../uucore" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } memchr = "2" bstr = "0.2" +atty = "0.2" [[bin]] name = "cut" diff --git a/src/uu/cut/src/cut.rs b/src/uu/cut/src/cut.rs index 819cbb989..af4a27d8a 100644 --- a/src/uu/cut/src/cut.rs +++ b/src/uu/cut/src/cut.rs @@ -17,7 +17,6 @@ use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write}; use std::path::Path; use self::searcher::Searcher; -use uucore::fs::is_stdout_interactive; use uucore::ranges::Range; use uucore::InvalidEncodingHandling; @@ -127,7 +126,7 @@ enum Mode { } fn stdout_writer() -> Box { - if is_stdout_interactive() { + if atty::is(atty::Stream::Stdout) { Box::new(stdout()) } else { Box::new(BufWriter::new(stdout())) as Box diff --git a/src/uu/nohup/Cargo.toml b/src/uu/nohup/Cargo.toml index 5bbbd9dff..0e47b5cad 100644 --- a/src/uu/nohup/Cargo.toml +++ b/src/uu/nohup/Cargo.toml @@ -17,6 +17,7 @@ path = "src/nohup.rs" [dependencies] clap = "2.33" libc = "0.2.42" +atty = "0.2.14" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/nohup/src/nohup.rs b/src/uu/nohup/src/nohup.rs index ea379ff49..4e6fd7a7e 100644 --- a/src/uu/nohup/src/nohup.rs +++ b/src/uu/nohup/src/nohup.rs @@ -19,7 +19,6 @@ use std::fs::{File, OpenOptions}; use std::io::Error; use std::os::unix::prelude::*; use std::path::{Path, PathBuf}; -use uucore::fs::{is_stderr_interactive, is_stdin_interactive, is_stdout_interactive}; use uucore::InvalidEncodingHandling; static ABOUT: &str = "Run COMMAND ignoring hangup signals."; @@ -84,7 +83,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { } fn replace_fds() { - if is_stdin_interactive() { + if atty::is(atty::Stream::Stdin) { let new_stdin = match File::open(Path::new("/dev/null")) { Ok(t) => t, Err(e) => crash!(2, "Cannot replace STDIN: {}", e), @@ -94,7 +93,7 @@ fn replace_fds() { } } - if is_stdout_interactive() { + if atty::is(atty::Stream::Stdout) { let new_stdout = find_stdout(); let fd = new_stdout.as_raw_fd(); @@ -103,7 +102,7 @@ fn replace_fds() { } } - if is_stderr_interactive() && unsafe { dup2(1, 2) } != 2 { + if atty::is(atty::Stream::Stderr) && unsafe { dup2(1, 2) } != 2 { crash!(2, "Cannot replace STDERR: {}", Error::last_os_error()) } } diff --git a/src/uu/tty/Cargo.toml b/src/uu/tty/Cargo.toml index 7be27a900..49b7669df 100644 --- a/src/uu/tty/Cargo.toml +++ b/src/uu/tty/Cargo.toml @@ -17,6 +17,7 @@ path = "src/tty.rs" [dependencies] clap = "2.33" libc = "0.2.42" +atty = "0.2" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/tty/src/tty.rs b/src/uu/tty/src/tty.rs index 074bcf182..edcdf091e 100644 --- a/src/uu/tty/src/tty.rs +++ b/src/uu/tty/src/tty.rs @@ -14,7 +14,6 @@ extern crate uucore; use clap::{crate_version, App, Arg}; use std::ffi::CStr; -use uucore::fs::is_stdin_interactive; use uucore::InvalidEncodingHandling; static ABOUT: &str = "Print the file name of the terminal connected to standard input."; @@ -67,7 +66,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { } } - if is_stdin_interactive() { + if atty::is(atty::Stream::Stdin) { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE diff --git a/src/uucore/src/lib/features/fs.rs b/src/uucore/src/lib/features/fs.rs index 38cdbef94..525f305e3 100644 --- a/src/uucore/src/lib/features/fs.rs +++ b/src/uucore/src/lib/features/fs.rs @@ -225,51 +225,6 @@ pub fn canonicalize>(original: P, can_mode: CanonicalizeMode) -> Ok(result) } -#[cfg(unix)] -pub fn is_stdin_interactive() -> bool { - unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } -} - -#[cfg(windows)] -pub fn is_stdin_interactive() -> bool { - false -} - -#[cfg(target_os = "redox")] -pub fn is_stdin_interactive() -> bool { - termion::is_tty(&io::stdin()) -} - -#[cfg(unix)] -pub fn is_stdout_interactive() -> bool { - unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 } -} - -#[cfg(windows)] -pub fn is_stdout_interactive() -> bool { - false -} - -#[cfg(target_os = "redox")] -pub fn is_stdout_interactive() -> bool { - termion::is_tty(&io::stdout()) -} - -#[cfg(unix)] -pub fn is_stderr_interactive() -> bool { - unsafe { libc::isatty(libc::STDERR_FILENO) == 1 } -} - -#[cfg(windows)] -pub fn is_stderr_interactive() -> bool { - false -} - -#[cfg(target_os = "redox")] -pub fn is_stderr_interactive() -> bool { - termion::is_tty(&io::stderr()) -} - #[cfg(not(unix))] #[allow(unused_variables)] pub fn display_permissions(metadata: &fs::Metadata, display_file_type: bool) -> String { From be8e5f5f30f8f94b1c03ea1125f8273dec7aeb2c Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 9 Jun 2021 17:15:42 +0200 Subject: [PATCH 09/33] use the same spec for atty everywhere --- Cargo.toml | 2 +- src/uu/more/Cargo.toml | 2 +- src/uu/nohup/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 19ebca511..804c5f978 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -351,7 +351,7 @@ time = "0.1" unindent = "0.1" uucore = { version=">=0.0.8", package="uucore", path="src/uucore", features=["entries", "process"] } walkdir = "2.2" -atty = "0.2.14" +atty = "0.2" [target.'cfg(unix)'.dev-dependencies] rlimit = "0.4.0" diff --git a/src/uu/more/Cargo.toml b/src/uu/more/Cargo.toml index b3b97e6dd..af6781876 100644 --- a/src/uu/more/Cargo.toml +++ b/src/uu/more/Cargo.toml @@ -19,7 +19,7 @@ clap = "2.33" uucore = { version = ">=0.0.7", package = "uucore", path = "../../uucore" } uucore_procs = { version = ">=0.0.5", package = "uucore_procs", path = "../../uucore_procs" } crossterm = ">=0.19" -atty = "0.2.14" +atty = "0.2" unicode-width = "0.1.7" unicode-segmentation = "1.7.1" diff --git a/src/uu/nohup/Cargo.toml b/src/uu/nohup/Cargo.toml index 0e47b5cad..839219a84 100644 --- a/src/uu/nohup/Cargo.toml +++ b/src/uu/nohup/Cargo.toml @@ -17,7 +17,7 @@ path = "src/nohup.rs" [dependencies] clap = "2.33" libc = "0.2.42" -atty = "0.2.14" +atty = "0.2" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } From 7009cb04869b9abc9ca1e81774ff97a6ed96594c Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 01:07:01 +0900 Subject: [PATCH 10/33] Add "process" dependency to groups/Cargo.toml --- src/uu/groups/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/groups/Cargo.toml b/src/uu/groups/Cargo.toml index 1a56bc2ab..4a5a537e5 100644 --- a/src/uu/groups/Cargo.toml +++ b/src/uu/groups/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" path = "src/groups.rs" [dependencies] -uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["entries"] } +uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["entries", "process"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } clap = "2.33" From cebf1f09dff0925b5056bc49c5c43751a168dc30 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 01:54:10 +0900 Subject: [PATCH 11/33] get_groups_gnu sort with rotate_right --- src/uucore/src/lib/features/entries.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/uucore/src/lib/features/entries.rs b/src/uucore/src/lib/features/entries.rs index b94abbe4f..75bf245e4 100644 --- a/src/uucore/src/lib/features/entries.rs +++ b/src/uucore/src/lib/features/entries.rs @@ -95,15 +95,18 @@ pub fn get_groups() -> IOResult> { /// history of a process and its parents could affect the details of /// the result.) pub fn get_groups_gnu(arg_id: Option) -> IOResult> { - let mut groups = get_groups()?; + let groups = get_groups()?; let egid = arg_id.unwrap_or_else(crate::features::process::getegid); - if !groups.is_empty() && *groups.first().unwrap() == egid { - return Ok(groups); - } else if let Some(index) = groups.iter().position(|&x| x == egid) { - groups.remove(index); + Ok(sort_groups(groups, egid)) +} + +fn sort_groups(mut groups: Vec, egid: gid_t) -> Vec { + if let Some(index) = groups.iter().position(|&x| x == egid) { + groups[..index + 1].rotate_right(1); + } else { + groups.insert(0, egid); } - groups.insert(0, egid); - Ok(groups) + groups } #[derive(Copy, Clone)] @@ -308,6 +311,15 @@ pub fn grp2gid(name: &str) -> IOResult { mod test { use super::*; + #[test] + fn test_sort_groups() { + assert_eq!(sort_groups(vec![1, 2, 3], 4), vec![4, 1, 2, 3]); + assert_eq!(sort_groups(vec![1, 2, 3], 3), vec![3, 1, 2]); + assert_eq!(sort_groups(vec![1, 2, 3], 2), vec![2, 1, 3]); + assert_eq!(sort_groups(vec![1, 2, 3], 1), vec![1, 2, 3]); + assert_eq!(sort_groups(vec![1, 2, 3], 0), vec![0, 1, 2, 3]); + } + #[test] fn test_entries_get_groups_gnu() { if let Ok(mut groups) = get_groups() { From 44f6dc6098d6f47fbd054ac170ebeec7fd81535d Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Wed, 9 Jun 2021 22:10:28 +0200 Subject: [PATCH 12/33] whoami: remove advapi32-sys dependency --- Cargo.lock | 11 ----------- src/uu/whoami/Cargo.toml | 1 - src/uu/whoami/src/platform/windows.rs | 4 ++-- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b2d989be..9c03e22bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,16 +6,6 @@ version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -[[package]] -name = "advapi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "aho-corasick" version = "0.7.18" @@ -2751,7 +2741,6 @@ dependencies = [ name = "uu_whoami" version = "0.0.6" dependencies = [ - "advapi32-sys", "clap", "uucore", "uucore_procs", diff --git a/src/uu/whoami/Cargo.toml b/src/uu/whoami/Cargo.toml index f8dc01440..28670c8b5 100644 --- a/src/uu/whoami/Cargo.toml +++ b/src/uu/whoami/Cargo.toml @@ -20,7 +20,6 @@ uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=[" uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } [target.'cfg(target_os = "windows")'.dependencies] -advapi32-sys = "0.2.0" winapi = { version = "0.3", features = ["lmcons"] } [[bin]] diff --git a/src/uu/whoami/src/platform/windows.rs b/src/uu/whoami/src/platform/windows.rs index 5d648877b..3fe8eb1e7 100644 --- a/src/uu/whoami/src/platform/windows.rs +++ b/src/uu/whoami/src/platform/windows.rs @@ -11,7 +11,7 @@ extern crate winapi; use self::winapi::shared::lmcons; use self::winapi::shared::minwindef; -use self::winapi::um::winnt; +use self::winapi::um::{winbase, winnt}; use std::io::{Error, Result}; use std::mem; use uucore::wide::FromWide; @@ -20,7 +20,7 @@ pub unsafe fn get_username() -> Result { #[allow(deprecated)] let mut buffer: [winnt::WCHAR; lmcons::UNLEN as usize + 1] = mem::uninitialized(); let mut len = buffer.len() as minwindef::DWORD; - if advapi32::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 { + if winbase::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 { return Err(Error::last_os_error()); } let username = String::from_wide(&buffer[..len as usize - 1]); From 6d7d57e13c9f0e3de2a3f00be09d66087b186360 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 9 Jun 2021 22:52:59 +0200 Subject: [PATCH 13/33] remove a legacy declaration to getopt --- Cargo.lock | 1 - src/uu/timeout/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b2d989be..c69e1fde3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2602,7 +2602,6 @@ name = "uu_timeout" version = "0.0.6" dependencies = [ "clap", - "getopts", "libc", "uucore", "uucore_procs", diff --git a/src/uu/timeout/Cargo.toml b/src/uu/timeout/Cargo.toml index 206a98c08..d16559858 100644 --- a/src/uu/timeout/Cargo.toml +++ b/src/uu/timeout/Cargo.toml @@ -16,7 +16,6 @@ path = "src/timeout.rs" [dependencies] clap = "2.33" -getopts = "0.2.18" libc = "0.2.42" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["parse_time", "process", "signals"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } From 23f655e2a514ee2730601f7ac184d84763e8e07e Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 11:15:01 +0900 Subject: [PATCH 14/33] Use inclusive range Co-authored-by: Michael Debertol --- src/uucore/src/lib/features/entries.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/entries.rs b/src/uucore/src/lib/features/entries.rs index 75bf245e4..7d8c78a2f 100644 --- a/src/uucore/src/lib/features/entries.rs +++ b/src/uucore/src/lib/features/entries.rs @@ -102,7 +102,7 @@ pub fn get_groups_gnu(arg_id: Option) -> IOResult> { fn sort_groups(mut groups: Vec, egid: gid_t) -> Vec { if let Some(index) = groups.iter().position(|&x| x == egid) { - groups[..index + 1].rotate_right(1); + groups[..=index].rotate_right(1); } else { groups.insert(0, egid); } From 3eae399ec4e38bf4ea9fb4600a34b792e1076145 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 11:51:04 +0900 Subject: [PATCH 15/33] Remove trivially unnessessary unwrap() from base32/64 --- src/uu/base32/src/base32.rs | 9 +-------- src/uu/base64/src/base64.rs | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/uu/base32/src/base32.rs b/src/uu/base32/src/base32.rs index f0e187c31..e6a01cb34 100644 --- a/src/uu/base32/src/base32.rs +++ b/src/uu/base32/src/base32.rs @@ -38,18 +38,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let config_result: Result = base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage); - - if config_result.is_err() { - match config_result { - Ok(_) => panic!(), - Err(s) => crash!(BASE_CMD_PARSE_ERROR, "{}", s), - } - } + let config = config_result.unwrap_or_else(|s| crash!(BASE_CMD_PARSE_ERROR, "{}", s)); // Create a reference to stdin so we can return a locked stdin from // parse_base_cmd_args let stdin_raw = stdin(); - let config = config_result.unwrap(); let mut input: Box = base_common::get_input(&config, &stdin_raw); base_common::handle_input( diff --git a/src/uu/base64/src/base64.rs b/src/uu/base64/src/base64.rs index 810df4fe8..0dd831027 100644 --- a/src/uu/base64/src/base64.rs +++ b/src/uu/base64/src/base64.rs @@ -38,18 +38,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let name = executable!(); let config_result: Result = base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage); - - if config_result.is_err() { - match config_result { - Ok(_) => panic!(), - Err(s) => crash!(BASE_CMD_PARSE_ERROR, "{}", s), - } - } + let config = config_result.unwrap_or_else(|s| crash!(BASE_CMD_PARSE_ERROR, "{}", s)); // Create a reference to stdin so we can return a locked stdin from // parse_base_cmd_args let stdin_raw = stdin(); - let config = config_result.unwrap(); let mut input: Box = base_common::get_input(&config, &stdin_raw); base_common::handle_input( From 774c01f00800be92ec28501731ffd917c8847f42 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 12:29:41 +0900 Subject: [PATCH 16/33] Remove trivially unnessessary unwrap() from du --- src/uu/du/src/du.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 82424ca32..94d90c6cd 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -320,8 +320,7 @@ fn du( if this_stat.is_dir { futures.push(du(this_stat, options, depth + 1, inodes)); } else { - if this_stat.inode.is_some() { - let inode = this_stat.inode.unwrap(); + if let Some(inode) = this_stat.inode { if inodes.contains(&inode) { continue; } @@ -360,7 +359,9 @@ fn du( my_stat.size += stat.size; my_stat.blocks += stat.blocks; } - options.max_depth == None || depth < options.max_depth.unwrap() + options + .max_depth + .map_or(true, |max_depth| depth < max_depth) })); stats.push(my_stat); Box::new(stats.into_iter()) From da9558c6841e7721fcbecb71da9f860e7a07d004 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 12:36:34 +0900 Subject: [PATCH 17/33] Remove trivially unnessessary unwrap() from expr --- src/uu/expr/src/expr.rs | 6 +----- src/uu/expr/src/syntax_tree.rs | 17 ++++------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/uu/expr/src/expr.rs b/src/uu/expr/src/expr.rs index 329a79ba2..8238917f7 100644 --- a/src/uu/expr/src/expr.rs +++ b/src/uu/expr/src/expr.rs @@ -56,11 +56,7 @@ fn print_expr_error(expr_error: &str) -> ! { } fn evaluate_ast(maybe_ast: Result, String>) -> Result { - if maybe_ast.is_err() { - Err(maybe_ast.err().unwrap()) - } else { - maybe_ast.ok().unwrap().evaluate() - } + maybe_ast.and_then(|ast| ast.evaluate()) } fn maybe_handle_help_or_version(args: &[String]) -> bool { diff --git a/src/uu/expr/src/syntax_tree.rs b/src/uu/expr/src/syntax_tree.rs index b72d78729..ba477414e 100644 --- a/src/uu/expr/src/syntax_tree.rs +++ b/src/uu/expr/src/syntax_tree.rs @@ -175,23 +175,14 @@ impl AstNode { pub fn tokens_to_ast( maybe_tokens: Result, String>, ) -> Result, String> { - if maybe_tokens.is_err() { - Err(maybe_tokens.err().unwrap()) - } else { - let tokens = maybe_tokens.ok().unwrap(); + maybe_tokens.and_then(|tokens| { let mut out_stack: TokenStack = Vec::new(); let mut op_stack: TokenStack = Vec::new(); for (token_idx, token) in tokens { - if let Err(reason) = - push_token_to_either_stack(token_idx, &token, &mut out_stack, &mut op_stack) - { - return Err(reason); - } - } - if let Err(reason) = move_rest_of_ops_to_out(&mut out_stack, &mut op_stack) { - return Err(reason); + push_token_to_either_stack(token_idx, &token, &mut out_stack, &mut op_stack)?; } + move_rest_of_ops_to_out(&mut out_stack, &mut op_stack)?; assert!(op_stack.is_empty()); maybe_dump_rpn(&out_stack); @@ -205,7 +196,7 @@ pub fn tokens_to_ast( maybe_dump_ast(&result); result } - } + }) } fn maybe_dump_ast(result: &Result, String>) { From 797c4a340e1941ecd276f0241f24bf90f63c7f00 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 13:10:16 +0900 Subject: [PATCH 18/33] Remove trivially unnessessary unwrap() from od --- src/uu/od/src/parse_formats.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/uu/od/src/parse_formats.rs b/src/uu/od/src/parse_formats.rs index abf05ea18..ccac44d72 100644 --- a/src/uu/od/src/parse_formats.rs +++ b/src/uu/od/src/parse_formats.rs @@ -275,17 +275,13 @@ fn parse_type_string(params: &str) -> Result, Strin let mut chars = params.chars(); let mut ch = chars.next(); - while ch.is_some() { - let type_char = ch.unwrap(); - let type_char = match format_type(type_char) { - Some(t) => t, - None => { - return Err(format!( - "unexpected char '{}' in format specification '{}'", - type_char, params - )); - } - }; + while let Some(type_char) = ch { + let type_char = format_type(type_char).ok_or_else(|| { + format!( + "unexpected char '{}' in format specification '{}'", + type_char, params + ) + })?; let type_cat = format_type_category(type_char); From 1ac4eb171ee7976c8de30fcf786e2873ec2b7685 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 12:37:52 +0900 Subject: [PATCH 19/33] move cmode rather than mut --- src/uu/chmod/src/chmod.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index 7d171a6f7..2d5787099 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -134,23 +134,25 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Err(err) => crash!(1, "cannot stat attributes of '{}': {}", fref, err), }); let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required - let mut cmode = if mode_had_minus_prefix { + let cmode = if mode_had_minus_prefix { // clap parsing is finished, now put prefix back - Some(format!("-{}", modes)) + format!("-{}", modes) } else { - Some(modes.to_string()) + modes.to_string() }; let mut files: Vec = matches .values_of(options::FILE) .map(|v| v.map(ToString::to_string).collect()) .unwrap_or_default(); - if fmode.is_some() { + let cmode = if fmode.is_some() { // "--reference" and MODE are mutually exclusive // if "--reference" was used MODE needs to be interpreted as another FILE // it wasn't possible to implement this behavior directly with clap - files.push(cmode.unwrap()); - cmode = None; - } + files.push(cmode); + None + } else { + Some(cmode) + }; let chmoder = Chmoder { changes, From ded92dbca0253be2bd5b9cd886bbc5e8ed2bc6d6 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 13:09:35 +0900 Subject: [PATCH 20/33] clean up fold, hashsum, kill --- src/uu/fold/src/fold.rs | 2 +- src/uu/hashsum/src/hashsum.rs | 6 ++---- src/uu/kill/src/kill.rs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/uu/fold/src/fold.rs b/src/uu/fold/src/fold.rs index c49809549..118f7f5f9 100644 --- a/src/uu/fold/src/fold.rs +++ b/src/uu/fold/src/fold.rs @@ -98,7 +98,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { fn handle_obsolete(args: &[String]) -> (Vec, Option) { for (i, arg) in args.iter().enumerate() { let slice = &arg; - if slice.starts_with('-') && slice.len() > 1 && slice.chars().nth(1).unwrap().is_digit(10) { + if slice.starts_with('-') && slice.chars().nth(1).map_or(false, |c| c.is_digit(10)) { let mut v = args.to_vec(); v.remove(i); return (v, Some(slice[1..].to_owned())); diff --git a/src/uu/hashsum/src/hashsum.rs b/src/uu/hashsum/src/hashsum.rs index 1f097e128..a007473ab 100644 --- a/src/uu/hashsum/src/hashsum.rs +++ b/src/uu/hashsum/src/hashsum.rs @@ -255,10 +255,8 @@ fn detect_algo<'a>( } } } - if alg.is_none() { - crash!(1, "You must specify hash algorithm!") - }; - (name, alg.unwrap(), output_bits) + let alg = alg.unwrap_or_else(|| crash!(1, "You must specify hash algorithm!")); + (name, alg, output_bits) } } } diff --git a/src/uu/kill/src/kill.rs b/src/uu/kill/src/kill.rs index 6c2464c92..a49acaa05 100644 --- a/src/uu/kill/src/kill.rs +++ b/src/uu/kill/src/kill.rs @@ -111,7 +111,7 @@ fn handle_obsolete(mut args: Vec) -> (Vec, Option) { while i < args.len() { // this is safe because slice is valid when it is referenced let slice = &args[i].clone(); - if slice.starts_with('-') && slice.len() > 1 && slice.chars().nth(1).unwrap().is_digit(10) { + if slice.starts_with('-') && slice.chars().nth(1).map_or(false, |c| c.is_digit(10)) { let val = &slice[1..]; match val.parse() { Ok(num) => { From 9c6750252d2c7a981de5cf6ff527fc54de69b147 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 15:07:07 +0900 Subject: [PATCH 21/33] du winapi dependency only for windows --- src/uu/du/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/uu/du/Cargo.toml b/src/uu/du/Cargo.toml index 023c0a021..dcd1f720e 100644 --- a/src/uu/du/Cargo.toml +++ b/src/uu/du/Cargo.toml @@ -19,6 +19,8 @@ clap = "2.33" chrono = "0.4" uucore = { version=">=0.0.8", package="uucore", path="../../uucore" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } + +[target.'cfg(target_os = "windows")'.dependencies] winapi = { version="0.3", features=[] } [[bin]] From 357886b5999205317bbfcc1479d40ebf7d9e63de Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 18:05:36 +0900 Subject: [PATCH 22/33] Remove unnessassary chars() and unwrap_or() from tail --- src/uu/tail/src/tail.rs | 44 ++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 15a819d35..7670313a4 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -174,7 +174,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { match matches.value_of(options::LINES) { Some(n) => { let mut slice: &str = n; - if slice.chars().next().unwrap_or('_') == '+' { + if slice.as_bytes().first() == Some(&b'+') { settings.beginning = true; slice = &slice[1..]; } @@ -189,7 +189,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { None => { if let Some(n) = matches.value_of(options::BYTES) { let mut slice: &str = n; - if slice.chars().next().unwrap_or('_') == '+' { + if slice.as_bytes().first() == Some(&b'+') { settings.beginning = true; slice = &slice[1..]; } @@ -305,41 +305,35 @@ impl ParseSizeErr { pub type ParseSizeResult = Result; pub fn parse_size(mut size_slice: &str) -> Result { - let mut base = if size_slice.chars().last().unwrap_or('_') == 'B' { + let mut base = if size_slice.as_bytes().last() == Some(&b'B') { size_slice = &size_slice[..size_slice.len() - 1]; 1000u64 } else { 1024u64 }; - let exponent = if !size_slice.is_empty() { - let mut has_suffix = true; - let exp = match size_slice.chars().last().unwrap_or('_') { - 'K' | 'k' => 1u64, - 'M' => 2u64, - 'G' => 3u64, - 'T' => 4u64, - 'P' => 5u64, - 'E' => 6u64, - 'Z' | 'Y' => { + let exponent = match size_slice.as_bytes().last() { + Some(unit) => match unit { + b'K' | b'k' => 1u64, + b'M' => 2u64, + b'G' => 3u64, + b'T' => 4u64, + b'P' => 5u64, + b'E' => 6u64, + b'Z' | b'Y' => { return Err(ParseSizeErr::size_too_big(size_slice)); } - 'b' => { + b'b' => { base = 512u64; 1u64 } - _ => { - has_suffix = false; - 0u64 - } - }; - if has_suffix { - size_slice = &size_slice[..size_slice.len() - 1]; - } - exp - } else { - 0u64 + _ => 0u64, + }, + None => 0u64, }; + if exponent != 0 { + size_slice = &size_slice[..size_slice.len() - 1]; + } let mut multiplier = 1u64; for _ in 0u64..exponent { From 1fecd98ebe805f778f6fb0f6073613fb21507ba2 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 18:30:19 +0900 Subject: [PATCH 23/33] bytes operation for pathchk --- src/uu/pathchk/src/pathchk.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/uu/pathchk/src/pathchk.rs b/src/uu/pathchk/src/pathchk.rs index 07e3a3289..358881509 100644 --- a/src/uu/pathchk/src/pathchk.rs +++ b/src/uu/pathchk/src/pathchk.rs @@ -241,13 +241,14 @@ fn no_leading_hyphen(path_segment: &str) -> bool { // check whether a path segment contains only valid (read: portable) characters fn check_portable_chars(path_segment: &str) -> bool { - let valid_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-".to_string(); - for ch in path_segment.chars() { - if !valid_str.contains(ch) { + const VALID_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"; + for (i, ch) in path_segment.as_bytes().iter().enumerate() { + if !VALID_CHARS.contains(ch) { + let invalid = path_segment[i..].chars().next().unwrap(); writeln!( &mut std::io::stderr(), "nonportable character '{}' in file name component '{}'", - ch, + invalid, path_segment ); return false; From 3ee09fa783026a02c892440b2d380370beeb2403 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 12:29:41 +0900 Subject: [PATCH 24/33] only matches Some() in match --- src/uu/du/src/du.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 94d90c6cd..bf1272a44 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -229,10 +229,9 @@ fn unit_string_to_number(s: &str) -> Option { let mut offset = 0; let mut s_chars = s.chars().rev(); - let (mut ch, multiple) = match s_chars.next() { - Some('B') | Some('b') => ('B', 1000u64), - Some(ch) => (ch, 1024u64), - None => return None, + let (mut ch, multiple) = match s_chars.next()? { + 'B' | 'b' => ('B', 1000u64), + ch => (ch, 1024u64), }; if ch == 'B' { ch = s_chars.next()?; From cc6c2f64b1ce36f02501b8c0fb52ddb66cdf7a46 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 13:09:35 +0900 Subject: [PATCH 25/33] clean up fold, hashsum, kill, nl, printf, truncate --- src/uu/nl/src/nl.rs | 2 +- .../src/tokenize/num_format/formatters/decf.rs | 15 +++------------ .../num_format/formatters/float_common.rs | 13 +++++++------ src/uu/truncate/src/truncate.rs | 5 +---- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/uu/nl/src/nl.rs b/src/uu/nl/src/nl.rs index c062eedd9..41750259f 100644 --- a/src/uu/nl/src/nl.rs +++ b/src/uu/nl/src/nl.rs @@ -247,7 +247,7 @@ fn nl(reader: &mut BufReader, settings: &Settings) { let mut line_filter: fn(&str, ®ex::Regex) -> bool = pass_regex; for mut l in reader.lines().map(|r| r.unwrap()) { // Sanitize the string. We want to print the newline ourselves. - if !l.is_empty() && l.chars().rev().next().unwrap() == '\n' { + if l.chars().last() == Some('\n') { l.pop(); } // Next we iterate through the individual chars to see if this diff --git a/src/uu/printf/src/tokenize/num_format/formatters/decf.rs b/src/uu/printf/src/tokenize/num_format/formatters/decf.rs index 5798eadcb..3376345e0 100644 --- a/src/uu/printf/src/tokenize/num_format/formatters/decf.rs +++ b/src/uu/printf/src/tokenize/num_format/formatters/decf.rs @@ -55,18 +55,9 @@ impl Formatter for Decf { ); // strip trailing zeroes if let Some(ref post_dec) = f_sci.post_decimal { - let mut i = post_dec.len(); - { - let mut it = post_dec.chars(); - while let Some(c) = it.next_back() { - if c != '0' { - break; - } - i -= 1; - } - } - if i != post_dec.len() { - f_sci.post_decimal = Some(String::from(&post_dec[0..i])); + let trimmed = post_dec.trim_end_matches('0'); + if trimmed.len() != post_dec.len() { + f_sci.post_decimal = Some(trimmed.to_owned()); } } let f_fl = get_primitive_dec( diff --git a/src/uu/printf/src/tokenize/num_format/formatters/float_common.rs b/src/uu/printf/src/tokenize/num_format/formatters/float_common.rs index dfd64296c..97009b586 100644 --- a/src/uu/printf/src/tokenize/num_format/formatters/float_common.rs +++ b/src/uu/printf/src/tokenize/num_format/formatters/float_common.rs @@ -247,8 +247,12 @@ pub fn get_primitive_dec( first_segment.len() as isize - 1, ) } else { - match first_segment.chars().next() { - Some('0') => { + match first_segment + .chars() + .next() + .expect("float_common: no chars in first segment.") + { + '0' => { let it = second_segment.chars().enumerate(); let mut m: isize = 0; let mut pre = String::from("0"); @@ -266,10 +270,7 @@ pub fn get_primitive_dec( } (pre, post, m) } - Some(_) => (first_segment, second_segment, 0), - None => { - panic!("float_common: no chars in first segment."); - } + _ => (first_segment, second_segment, 0), } } } else { diff --git a/src/uu/truncate/src/truncate.rs b/src/uu/truncate/src/truncate.rs index 8e785ad21..22c0252f7 100644 --- a/src/uu/truncate/src/truncate.rs +++ b/src/uu/truncate/src/truncate.rs @@ -363,10 +363,7 @@ fn parse_size(size: &str) -> Result { // Get the numeric part of the size argument. For example, if the // argument is "123K", then the numeric part is "123". let numeric_string: String = size.chars().take_while(|c| c.is_digit(10)).collect(); - let number: u64 = match numeric_string.parse() { - Ok(n) => n, - Err(_) => return Err(()), - }; + let number: u64 = numeric_string.parse().map_err(|_| ())?; // Get the alphabetic units part of the size argument and compute // the factor it represents. For example, if the argument is "123K", From b21d189fcfa99af3b78b2e8a3206460d313f75a9 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 14:35:09 +0900 Subject: [PATCH 26/33] Remove trivially unnessessary unwrap() pr --- src/uu/pr/src/pr.rs | 53 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/uu/pr/src/pr.rs b/src/uu/pr/src/pr.rs index 0761dd09d..d7b95d215 100644 --- a/src/uu/pr/src/pr.rs +++ b/src/uu/pr/src/pr.rs @@ -401,18 +401,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 { for file_group in file_groups { let result_options = build_options(&matches, &file_group, args.join(" ")); + let options = match result_options { + Ok(options) => options, + Err(err) => { + print_error(&matches, err); + return 1; + } + }; - if result_options.is_err() { - print_error(&matches, result_options.err().unwrap()); - return 1; - } - - let options = &result_options.unwrap(); - - let cmd_result = if file_group.len() == 1 { - pr(file_group.get(0).unwrap(), options) + let cmd_result = if let Ok(group) = file_group.iter().exactly_one() { + pr(group, &options) } else { - mpr(&file_group, options) + mpr(&file_group, &options) }; let status = match cmd_result { @@ -442,11 +442,12 @@ fn recreate_arguments(args: &[String]) -> Vec { let mut arguments = args.to_owned(); let num_option = args.iter().find_position(|x| n_regex.is_match(x.trim())); if let Some((pos, _value)) = num_option { - let num_val_opt = args.get(pos + 1); - if num_val_opt.is_some() && !num_regex.is_match(num_val_opt.unwrap()) { - let could_be_file = arguments.remove(pos + 1); - arguments.insert(pos + 1, format!("{}", NumberingMode::default().width)); - arguments.insert(pos + 2, could_be_file); + if let Some(num_val_opt) = args.get(pos + 1) { + if !num_regex.is_match(num_val_opt) { + let could_be_file = arguments.remove(pos + 1); + arguments.insert(pos + 1, format!("{}", NumberingMode::default().width)); + arguments.insert(pos + 2, could_be_file); + } } } @@ -666,12 +667,14 @@ fn build_options( None => end_page_in_plus_option, }; - if end_page.is_some() && start_page > end_page.unwrap() { - return Err(PrError::EncounteredErrors(format!( - "invalid --pages argument '{}:{}'", - start_page, - end_page.unwrap() - ))); + if let Some(end_page) = end_page { + if start_page > end_page { + return Err(PrError::EncounteredErrors(format!( + "invalid --pages argument '{}:{}'", + start_page, + end_page + ))); + } } let default_lines_per_page = if form_feed_used { @@ -947,7 +950,7 @@ fn read_stream_and_create_pages( let current_page = x + 1; current_page >= start_page - && (last_page.is_none() || current_page <= last_page.unwrap()) + && last_page.map_or(true, |last_page| current_page <= last_page) }), ) } @@ -1030,8 +1033,7 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul let lines_written = write_columns(lines, options, out)?; - for index in 0..trailer_content.len() { - let x = trailer_content.get(index).unwrap(); + for (index, x) in trailer_content.iter().enumerate() { out.write_all(x.as_bytes())?; if index + 1 != trailer_content.len() { out.write_all(line_separator)?; @@ -1074,8 +1076,7 @@ fn write_columns( let mut offset = 0; for col in 0..columns { let mut inserted = 0; - for i in offset..lines.len() { - let line = lines.get(i).unwrap(); + for line in &lines[offset..] { if line.file_id != col { break; } From b9611b71ee46b761b2e29e6dec2af3a78b2841b5 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 17:22:05 +0900 Subject: [PATCH 27/33] use ? operator for od --- src/uu/od/src/parse_formats.rs | 48 ++++++++++++++-------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/src/uu/od/src/parse_formats.rs b/src/uu/od/src/parse_formats.rs index ccac44d72..fca908016 100644 --- a/src/uu/od/src/parse_formats.rs +++ b/src/uu/od/src/parse_formats.rs @@ -297,30 +297,25 @@ fn parse_type_string(params: &str) -> Result, Strin ch = chars.next(); } if !decimal_size.is_empty() { - byte_size = match decimal_size.parse() { - Err(_) => { - return Err(format!( - "invalid number '{}' in format specification '{}'", - decimal_size, params - )) - } - Ok(n) => n, - } + byte_size = decimal_size.parse().map_err(|_| { + format!( + "invalid number '{}' in format specification '{}'", + decimal_size, params + ) + })?; } } if is_format_dump_char(ch, &mut show_ascii_dump) { ch = chars.next(); } - match od_format_type(type_char, byte_size) { - Some(ft) => formats.push(ParsedFormatterItemInfo::new(ft, show_ascii_dump)), - None => { - return Err(format!( - "invalid size '{}' in format specification '{}'", - byte_size, params - )) - } - } + let ft = od_format_type(type_char, byte_size).ok_or_else(|| { + format!( + "invalid size '{}' in format specification '{}'", + byte_size, params + ) + })?; + formats.push(ParsedFormatterItemInfo::new(ft, show_ascii_dump)); } Ok(formats) @@ -331,16 +326,13 @@ pub fn parse_format_flags_str( args_str: &Vec<&'static str>, ) -> Result, String> { let args: Vec = args_str.iter().map(|s| s.to_string()).collect(); - match parse_format_flags(&args) { - Err(e) => Err(e), - Ok(v) => { - // tests using this function assume add_ascii_dump is not set - Ok(v.into_iter() - .inspect(|f| assert!(!f.add_ascii_dump)) - .map(|f| f.formatter_item_info) - .collect()) - } - } + parse_format_flags(&args).map(|v| { + // tests using this function assume add_ascii_dump is not set + v.into_iter() + .inspect(|f| assert!(!f.add_ascii_dump)) + .map(|f| f.formatter_item_info) + .collect() + }) } #[test] From 8433c7726ddadf186fe322aa1345d1c78ecf8573 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 10 Jun 2021 17:41:39 +0900 Subject: [PATCH 28/33] tr parse_sequence reuses chars iterator --- src/uu/tr/src/expand.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/uu/tr/src/expand.rs b/src/uu/tr/src/expand.rs index 7d0c61c30..5d960921e 100644 --- a/src/uu/tr/src/expand.rs +++ b/src/uu/tr/src/expand.rs @@ -22,14 +22,15 @@ use std::ops::RangeInclusive; /// character; octal escape sequences consume 1 to 3 octal digits. #[inline] fn parse_sequence(s: &str) -> (char, usize) { - let c = s.chars().next().expect("invalid escape: empty string"); + let mut s = s.chars(); + let c = s.next().expect("invalid escape: empty string"); if ('0'..='7').contains(&c) { let mut v = c.to_digit(8).unwrap(); let mut consumed = 1; let bits_per_digit = 3; - for c in s.chars().skip(1).take(2) { + for c in s.take(2) { match c.to_digit(8) { Some(c) => { v = (v << bits_per_digit) | c; From dc57e1535eb708e2acbbf6b7d60e05147a0a932f Mon Sep 17 00:00:00 2001 From: Dean Li Date: Wed, 9 Jun 2021 22:42:19 +0800 Subject: [PATCH 29/33] more: Implement option '-d' Implement option '-d' (silent mode) Related to #2320 --- src/uu/more/src/more.rs | 53 ++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/uu/more/src/more.rs b/src/uu/more/src/more.rs index 4d345e96b..fa21c1e12 100644 --- a/src/uu/more/src/more.rs +++ b/src/uu/more/src/more.rs @@ -32,6 +32,8 @@ use crossterm::{ use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; +const BELL: &str = "\x07"; + pub mod options { pub const SILENT: &str = "silent"; pub const LOGICAL: &str = "logical"; @@ -53,14 +55,14 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let matches = App::new(executable!()) .about("A file perusal filter for CRT viewing.") .version(crate_version!()) - // The commented arguments below are unimplemented: - /* .arg( Arg::with_name(options::SILENT) .short("d") .long(options::SILENT) .help("Display help instead of ringing bell"), ) + // The commented arguments below are unimplemented: + /* .arg( Arg::with_name(options::LOGICAL) .short("f") @@ -140,6 +142,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .get_matches_from(args); let mut buff = String::new(); + let silent = matches.is_present(options::SILENT); if let Some(files) = matches.values_of(options::FILES) { let mut stdout = setup_term(); let length = files.len(); @@ -162,14 +165,14 @@ pub fn uumain(args: impl uucore::Args) -> i32 { } let mut reader = BufReader::new(File::open(file).unwrap()); reader.read_to_string(&mut buff).unwrap(); - more(&buff, &mut stdout, next_file.copied()); + more(&buff, &mut stdout, next_file.copied(), silent); buff.clear(); } reset_term(&mut stdout); } else if atty::isnt(atty::Stream::Stdin) { stdin().read_to_string(&mut buff).unwrap(); let mut stdout = setup_term(); - more(&buff, &mut stdout, None); + more(&buff, &mut stdout, None, silent); reset_term(&mut stdout); } else { show_usage_error!("bad usage"); @@ -204,13 +207,14 @@ fn reset_term(stdout: &mut std::io::Stdout) { #[inline(always)] fn reset_term(_: &mut usize) {} -fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>) { +fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>, silent: bool) { let (cols, rows) = terminal::size().unwrap(); let lines = break_buff(buff, usize::from(cols)); let line_count: u16 = lines.len().try_into().unwrap(); let mut upper_mark = 0; let mut lines_left = line_count.saturating_sub(upper_mark + rows); + let mut wrong_key = false; draw( &mut upper_mark, @@ -219,6 +223,8 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>) { lines.clone(), line_count, next_file, + silent, + wrong_key, ); let is_last = next_file.is_none(); @@ -237,6 +243,7 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>) { loop { if event::poll(Duration::from_millis(10)).unwrap() { + wrong_key = false; match event::read().unwrap() { Event::Key(KeyEvent { code: KeyCode::Char('q'), @@ -265,7 +272,9 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>) { }) => { upper_mark = upper_mark.saturating_sub(rows.saturating_sub(1)); } - _ => continue, + _ => { + wrong_key = true; + } } lines_left = line_count.saturating_sub(upper_mark + rows); draw( @@ -275,6 +284,8 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>) { lines.clone(), line_count, next_file, + silent, + wrong_key, ); if lines_left == 0 { @@ -287,6 +298,7 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>) { } } +#[allow(clippy::too_many_arguments)] fn draw( upper_mark: &mut u16, rows: u16, @@ -294,6 +306,8 @@ fn draw( lines: Vec, lc: u16, next_file: Option<&str>, + silent: bool, + wrong_key: bool, ) { execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap(); let (up_mark, lower_mark) = calc_range(*upper_mark, rows, lc); @@ -308,7 +322,7 @@ fn draw( .write_all(format!("\r{}\n", line).as_bytes()) .unwrap(); } - make_prompt_and_flush(&mut stdout, lower_mark, lc, next_file); + make_prompt_and_flush(&mut stdout, lower_mark, lc, next_file, silent, wrong_key); *upper_mark = up_mark; } @@ -364,8 +378,15 @@ fn calc_range(mut upper_mark: u16, rows: u16, line_count: u16) -> (u16, u16) { } // Make a prompt similar to original more -fn make_prompt_and_flush(stdout: &mut Stdout, lower_mark: u16, lc: u16, next_file: Option<&str>) { - let status = if lower_mark == lc { +fn make_prompt_and_flush( + stdout: &mut Stdout, + lower_mark: u16, + lc: u16, + next_file: Option<&str>, + silent: bool, + wrong_key: bool, +) { + let status_inner = if lower_mark == lc { format!("Next file: {}", next_file.unwrap_or_default()) } else { format!( @@ -373,11 +394,21 @@ fn make_prompt_and_flush(stdout: &mut Stdout, lower_mark: u16, lc: u16, next_fil (lower_mark as f64 / lc as f64 * 100.0).round() as u16 ) }; + + let status = format!("--More--({})", status_inner); + + let banner = match (silent, wrong_key) { + (true, true) => "[Press 'h' for instructions. (unimplemented)]".to_string(), + (true, false) => format!("{}[Press space to continue, 'q' to quit.]", status), + (false, true) => format!("{}{}", status, BELL), + (false, false) => status, + }; + write!( stdout, - "\r{}--More--({}){}", + "\r{}{}{}", Attribute::Reverse, - status, + banner, Attribute::Reset ) .unwrap(); From 0a1dcc27bb4e1ac0c1b4116d5059c81b9c5df884 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Fri, 11 Jun 2021 04:29:56 +0900 Subject: [PATCH 30/33] prevent utf8 iteration for ascii str from shred (#2389) --- src/uu/shred/src/shred.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/uu/shred/src/shred.rs b/src/uu/shred/src/shred.rs index 964e68a9e..177143811 100644 --- a/src/uu/shred/src/shred.rs +++ b/src/uu/shred/src/shred.rs @@ -24,7 +24,7 @@ extern crate uucore; static NAME: &str = "shred"; const BLOCK_SIZE: usize = 512; -const NAME_CHARSET: &str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_."; +const NAME_CHARSET: &[u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_."; // Patterns as shown in the GNU coreutils shred implementation const PATTERNS: [&[u8]; 22] = [ @@ -89,7 +89,7 @@ impl Iterator for FilenameGenerator { // Make the return value, then increment let mut ret = String::new(); for i in name_charset_indices.iter() { - let c: char = NAME_CHARSET.chars().nth(*i).unwrap(); + let c = char::from(NAME_CHARSET[*i]); ret.push(c); } @@ -163,16 +163,14 @@ impl<'a> BytesGenerator<'a> { return None; } - let this_block_size = { - if !self.exact { + let this_block_size = if !self.exact { + self.block_size + } else { + let bytes_left = self.total_bytes - self.bytes_generated.get(); + if bytes_left >= self.block_size as u64 { self.block_size } else { - let bytes_left = self.total_bytes - self.bytes_generated.get(); - if bytes_left >= self.block_size as u64 { - self.block_size - } else { - (bytes_left % self.block_size as u64) as usize - } + (bytes_left % self.block_size as u64) as usize } }; @@ -184,12 +182,10 @@ impl<'a> BytesGenerator<'a> { rng.fill(bytes); } PassType::Pattern(pattern) => { - let skip = { - if self.bytes_generated.get() == 0 { - 0 - } else { - (pattern.len() as u64 % self.bytes_generated.get()) as usize - } + let skip = if self.bytes_generated.get() == 0 { + 0 + } else { + (pattern.len() as u64 % self.bytes_generated.get()) as usize }; // Copy the pattern in chunks rather than simply one byte at a time From 3347dacfc825fda8e6ce43378f6098847744b259 Mon Sep 17 00:00:00 2001 From: Yagiz Degirmenci <62724709+ycd@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:46:17 +0300 Subject: [PATCH 31/33] chroot: refactor undocumented features (#2365) --- src/uu/chroot/src/chroot.rs | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/uu/chroot/src/chroot.rs b/src/uu/chroot/src/chroot.rs index 8e23d8227..86d4a4900 100644 --- a/src/uu/chroot/src/chroot.rs +++ b/src/uu/chroot/src/chroot.rs @@ -28,6 +28,7 @@ mod options { pub const GROUP: &str = "group"; pub const GROUPS: &str = "groups"; pub const USERSPEC: &str = "userspec"; + pub const COMMAND: &str = "command"; } pub fn uumain(args: impl uucore::Args) -> i32 { @@ -39,7 +40,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .version(crate_version!()) .about(ABOUT) .usage(SYNTAX) - .arg(Arg::with_name(options::NEWROOT).hidden(true).required(true)) + .arg( + Arg::with_name(options::NEWROOT) + .hidden(true) + .required(true) + .index(1), + ) .arg( Arg::with_name(options::USER) .short("u") @@ -71,6 +77,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 { ) .value_name("USER:GROUP"), ) + .arg( + Arg::with_name(options::COMMAND) + .hidden(true) + .multiple(true) + .index(2), + ) .get_matches_from(args); let default_shell: &'static str = "/bin/sh"; @@ -94,7 +106,14 @@ pub fn uumain(args: impl uucore::Args) -> i32 { ); } - let command: Vec<&str> = match matches.args.len() { + let commands = match matches.values_of(options::COMMAND) { + Some(v) => v.collect(), + None => vec![], + }; + + // TODO: refactor the args and command matching + // See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967 + let command: Vec<&str> = match commands.len() { 1 => { let shell: &str = match user_shell { Err(_) => default_shell, @@ -102,14 +121,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { }; vec![shell, default_option] } - _ => { - let mut vector: Vec<&str> = Vec::new(); - for (&k, v) in matches.args.iter() { - vector.push(k); - vector.push(v.vals[0].to_str().unwrap()); - } - vector - } + _ => commands, }; set_context(newroot, &matches); From 46981a69f9ea29d631a5182e4f77fc7218b186a2 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Fri, 11 Jun 2021 07:33:11 +0200 Subject: [PATCH 32/33] util: fix path (#2396) suggest to clone into the path that `util/run-gnu-test.sh` will be using --- util/build-gnu.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/build-gnu.sh b/util/build-gnu.sh index 44ecd2044..798a33456 100644 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -5,12 +5,12 @@ set -e if test ! -d ../gnu; then echo "Could not find ../gnu" - echo "git clone git@github.com:coreutils/coreutils.git ../gnu" + echo "git clone git@github.com:coreutils/coreutils.git gnu" exit 1 fi if test ! -d ../gnulib; then echo "Could not find ../gnulib" - echo "git clone git@github.com:coreutils/gnulib.git ../gnulib" + echo "git clone git@github.com:coreutils/gnulib.git gnulib" exit 1 fi From 0c364e635bf44330e728ef957f72d586d951c5fd Mon Sep 17 00:00:00 2001 From: Syukron Rifail M Date: Sun, 6 Jun 2021 20:34:40 +0700 Subject: [PATCH 33/33] du: add --one-file-system --- src/uu/du/src/du.rs | 24 ++++++++++++++++++------ tests/by-util/test_du.rs | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index bf1272a44..a1c2182c2 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -57,6 +57,7 @@ mod options { pub const SI: &str = "si"; pub const TIME: &str = "time"; pub const TIME_STYLE: &str = "time-style"; + pub const ONE_FILE_SYSTEM: &str = "one-file-system"; pub const FILE: &str = "FILE"; } @@ -81,6 +82,7 @@ struct Options { max_depth: Option, total: bool, separate_dirs: bool, + one_file_system: bool, } #[derive(PartialEq, Eq, Hash, Clone, Copy)] @@ -317,6 +319,15 @@ fn du( Ok(entry) => match Stat::new(entry.path()) { Ok(this_stat) => { if this_stat.is_dir { + if options.one_file_system { + if let (Some(this_inode), Some(my_inode)) = + (this_stat.inode, my_stat.inode) + { + if this_inode.dev_id != my_inode.dev_id { + continue; + } + } + } futures.push(du(this_stat, options, depth + 1, inodes)); } else { if let Some(inode) = this_stat.inode { @@ -532,12 +543,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .long(options::SI) .help("like -h, but use powers of 1000 not 1024") ) - // .arg( - // Arg::with_name("one-file-system") - // .short("x") - // .long("one-file-system") - // .help("skip directories on different file systems") - // ) + .arg( + Arg::with_name(options::ONE_FILE_SYSTEM) + .short("x") + .long(options::ONE_FILE_SYSTEM) + .help("skip directories on different file systems") + ) // .arg( // Arg::with_name("") // .short("x") @@ -602,6 +613,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { max_depth, total: matches.is_present(options::TOTAL), separate_dirs: matches.is_present(options::SEPARATE_DIRS), + one_file_system: matches.is_present(options::ONE_FILE_SYSTEM), }; let files = match matches.value_of(options::FILE) { diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 3c177c6bf..231451b95 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -312,3 +312,20 @@ fn _du_no_permission(s: &str) { fn _du_no_permission(s: &str) { assert_eq!(s, "4\tsubdir/links\n"); } + +#[test] +fn test_du_one_file_system() { + let scene = TestScenario::new(util_name!()); + + let result = scene.ucmd().arg("-x").arg(SUB_DIR).succeeds(); + + #[cfg(target_os = "linux")] + { + let result_reference = scene.cmd("du").arg("-x").arg(SUB_DIR).run(); + if result_reference.succeeded() { + assert_eq!(result.stdout_str(), result_reference.stdout_str()); + return; + } + } + _du_basics_subdir(result.stdout_str()); +}