uucore: Cache args_os(), util_name(), execution_phrase()

And remove args() because there's no valid use for it, invalid unicode
handling is specified in a different way.
This commit is contained in:
Jan Verbeek 2021-09-01 16:34:20 +02:00
parent d093c07887
commit 60df3c6b7c
8 changed files with 37 additions and 35 deletions

1
Cargo.lock generated
View file

@ -3276,6 +3276,7 @@ dependencies = [
"getopts",
"lazy_static",
"libc",
"once_cell",
"termion",
"thiserror",
"time",

View file

@ -38,7 +38,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let name = uucore::util_name();
let config_result: Result<base_common::Config, String> =
base_common::parse_base_cmd_args(args, &name, VERSION, ABOUT, &usage);
base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage);
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
@ -52,12 +52,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
config.wrap_cols,
config.ignore_garbage,
config.decode,
&name,
name,
);
0
}
pub fn uu_app() -> App<'static, 'static> {
base_common::base_app(&uucore::util_name(), VERSION, ABOUT)
base_common::base_app(uucore::util_name(), VERSION, ABOUT)
}

View file

@ -38,7 +38,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = usage();
let name = uucore::util_name();
let config_result: Result<base_common::Config, String> =
base_common::parse_base_cmd_args(args, &name, VERSION, ABOUT, &usage);
base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage);
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
@ -52,7 +52,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
config.wrap_cols,
config.ignore_garbage,
config.decode,
&name,
name,
);
0

View file

@ -47,7 +47,7 @@ fn usage() -> String {
}
pub fn uu_app() -> App<'static, 'static> {
let mut app = base_common::base_app(&uucore::util_name(), crate_version!(), ABOUT);
let mut app = base_common::base_app(uucore::util_name(), crate_version!(), ABOUT);
for encoding in ENCODINGS {
app = app.arg(Arg::with_name(encoding.0).long(encoding.0));
}
@ -88,7 +88,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
config.wrap_cols,
config.ignore_garbage,
config.decode,
&name,
name,
);
0

View file

@ -466,7 +466,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let options = Options {
all: matches.is_present(options::ALL),
util_name: uucore::util_name(),
util_name: uucore::util_name().to_owned(),
max_depth,
total: matches.is_present(options::TOTAL),
separate_dirs: matches.is_present(options::SEPARATE_DIRS),

View file

@ -35,7 +35,7 @@ fn get_userlogin() -> Option<String> {
static SUMMARY: &str = "Print user's login name";
fn usage() -> String {
fn usage() -> &'static str {
uucore::execution_phrase()
}
@ -44,8 +44,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let usage = usage();
let _ = uu_app().usage(&usage[..]).get_matches_from(args);
let _ = uu_app().usage(usage()).get_matches_from(args);
match get_userlogin() {
Some(userlogin) => println!("{}", userlogin),

View file

@ -30,6 +30,7 @@ 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"
[dev-dependencies]
clap = "2.33.3"

View file

@ -70,6 +70,8 @@ pub use crate::features::wide;
use std::ffi::OsString;
use std::sync::atomic::Ordering;
use once_cell::sync::Lazy;
pub fn get_utility_is_second_arg() -> bool {
crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
}
@ -78,36 +80,40 @@ pub fn set_utility_is_second_arg() {
crate::macros::UTILITY_IS_SECOND_ARG.store(true, Ordering::SeqCst)
}
/// Get the executable path (as `OsString`).
fn executable_os() -> OsString {
args_os().next().unwrap()
}
// args_os() can be expensive to call, it copies all of argv before iterating.
// So if we want only the first arg or so it's overkill. We cache it.
static ARGV: Lazy<Vec<OsString>> = Lazy::new(|| wild::args_os().collect());
/// Get the executable path (as `String`).
fn executable() -> String {
executable_os().to_string_lossy().into_owned()
}
static UTIL_NAME: Lazy<String> = Lazy::new(|| {
if get_utility_is_second_arg() {
&ARGV[1]
} else {
&ARGV[0]
}
.to_string_lossy()
.into_owned()
});
/// Derive the utility name.
pub fn util_name() -> String {
if get_utility_is_second_arg() {
args_os().nth(1).unwrap().to_string_lossy().into_owned()
} else {
executable()
}
pub fn util_name() -> &'static str {
&UTIL_NAME
}
/// Derive the complete execution phrase for "usage".
pub fn execution_phrase() -> String {
static EXECUTION_PHRASE: Lazy<String> = Lazy::new(|| {
if get_utility_is_second_arg() {
args_os()
ARGV.iter()
.take(2)
.map(|os_str| os_str.to_string_lossy().into_owned())
.collect::<Vec<_>>()
.join(" ")
} else {
executable()
ARGV[0].to_string_lossy().into_owned()
}
});
/// Derive the complete execution phrase for "usage".
pub fn execution_phrase() -> &'static str {
&EXECUTION_PHRASE
}
pub enum InvalidEncodingHandling {
@ -204,13 +210,8 @@ pub trait Args: Iterator<Item = OsString> + Sized {
impl<T: Iterator<Item = OsString> + Sized> Args for T {}
// args() ...
pub fn args() -> impl Iterator<Item = String> {
wild::args()
}
pub fn args_os() -> impl Iterator<Item = OsString> {
wild::args_os()
ARGV.iter().cloned()
}
#[cfg(test)]