Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ digest = "0.10.7"
fluent-bundle = "0.16.0"
fluent = "0.17.0"
unic-langid = "0.9.6"
fluent-syntax = "0.12.0"

uucore = { version = "0.1.0", package = "uucore", path = "src/uucore" }
uucore_procs = { version = "0.1.0", package = "uucore_procs", path = "src/uucore_procs" }
Expand Down
1 change: 1 addition & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

128 changes: 121 additions & 7 deletions src/bin/coreutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore manpages mangen
// spell-checker:ignore manpages mangen prefixcat testcat

use clap::{Arg, Command};
use clap_complete::Shell;
Expand All @@ -14,6 +14,7 @@
use std::path::{Path, PathBuf};
use std::process;
use uucore::display::Quotable;
use uucore::locale;

const VERSION: &str = env!("CARGO_PKG_VERSION");

Expand Down Expand Up @@ -50,6 +51,48 @@
binary_path.file_stem()?.to_str()
}

fn get_canonical_util_name(util_name: &str) -> &str {
match util_name {
// uu_test aliases - '[' is an alias for test
"[" => "test",

// hashsum aliases - all these hash commands are aliases for hashsum
"md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum"
| "sha3sum" | "sha3-224sum" | "sha3-256sum" | "sha3-384sum" | "sha3-512sum"
| "shake128sum" | "shake256sum" | "b2sum" | "b3sum" => "hashsum",

"dir" => "ls", // dir is an alias for ls

// Default case - return the util name as is
_ => util_name,
}
}

fn find_prefixed_util<'a>(
binary_name: &str,
mut util_keys: impl Iterator<Item = &'a str>,
) -> Option<&'a str> {
util_keys.find(|util| {
binary_name.ends_with(*util)
&& binary_name.len() > util.len() // Ensure there's actually a prefix
&& !binary_name[..binary_name.len() - (*util).len()]
.ends_with(char::is_alphanumeric)
})
}

fn setup_localization_or_exit(util_name: &str) {
locale::setup_localization(get_canonical_util_name(util_name)).unwrap_or_else(|err| {
match err {

Check warning on line 85 in src/bin/coreutils.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/coreutils.rs#L85

Added line #L85 was not covered by tests
uucore::locale::LocalizationError::ParseResource {
error: err_msg,
snippet,
} => eprintln!("Localization parse error at {snippet}: {err_msg}"),
other => eprintln!("Could not init the localization system: {other}"),

Check warning on line 90 in src/bin/coreutils.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/coreutils.rs#L87-L90

Added lines #L87 - L90 were not covered by tests
}
process::exit(99)

Check warning on line 92 in src/bin/coreutils.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/coreutils.rs#L92

Added line #L92 was not covered by tests
});
}

#[allow(clippy::cognitive_complexity)]
fn main() {
uucore::panic::mute_sigpipe_panic();
Expand All @@ -70,13 +113,10 @@

// binary name equals prefixed util name?
// * prefix/stem may be any string ending in a non-alphanumeric character
let util_name = if let Some(util) = utils.keys().find(|util| {
binary_as_util.ends_with(*util)
&& !binary_as_util[..binary_as_util.len() - (*util).len()]
.ends_with(char::is_alphanumeric)
}) {
// For example, if the binary is named `uu_test`, it will match `test` as a utility.
let util_name = if let Some(util) = find_prefixed_util(binary_as_util, utils.keys().copied()) {
// prefixed util => replace 0th (aka, executable name) argument
Some(OsString::from(*util))
Some(OsString::from(util))

Check warning on line 119 in src/bin/coreutils.rs

View check run for this annotation

Codecov / codecov/patch

src/bin/coreutils.rs#L119

Added line #L119 was not covered by tests
} else {
// unmatched binary name => regard as multi-binary container and advance argument list
uucore::set_utility_is_second_arg();
Expand Down Expand Up @@ -111,6 +151,12 @@

match utils.get(util) {
Some(&(uumain, _)) => {
// TODO: plug the deactivation of the translation
// and load the English strings directly at compilation time in the
// binary to avoid the load of the flt
// Could be something like:
// #[cfg(not(feature = "only_english"))]
setup_localization_or_exit(util);
process::exit(uumain(vec![util_os].into_iter().chain(args)));
}
None => {
Expand Down Expand Up @@ -213,6 +259,7 @@
let command = if utility == "coreutils" {
gen_coreutils_app(util_map)
} else {
setup_localization_or_exit(utility);
util_map.get(utility).unwrap().1()
};

Expand All @@ -239,3 +286,70 @@
}
command
}

#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;

#[test]
fn test_get_canonical_util_name() {
// Test a few key aliases
assert_eq!(get_canonical_util_name("["), "test");
assert_eq!(get_canonical_util_name("md5sum"), "hashsum");
assert_eq!(get_canonical_util_name("dir"), "ls");

// Test passthrough case
assert_eq!(get_canonical_util_name("cat"), "cat");
}

#[test]
fn test_name() {
// Test normal executable name
assert_eq!(name(Path::new("/usr/bin/ls")), Some("ls"));
assert_eq!(name(Path::new("cat")), Some("cat"));
assert_eq!(
name(Path::new("./target/debug/coreutils")),
Some("coreutils")
);

// Test with extensions
assert_eq!(name(Path::new("program.exe")), Some("program"));
assert_eq!(name(Path::new("/path/to/utility.bin")), Some("utility"));

// Test edge cases
assert_eq!(name(Path::new("")), None);
assert_eq!(name(Path::new("/")), None);
}

#[test]
fn test_find_prefixed_util() {
let utils = ["test", "cat", "ls", "cp"];

// Test exact prefixed matches
assert_eq!(
find_prefixed_util("uu_test", utils.iter().copied()),
Some("test")
);
assert_eq!(
find_prefixed_util("my-cat", utils.iter().copied()),
Some("cat")
);
assert_eq!(
find_prefixed_util("prefix_ls", utils.iter().copied()),
Some("ls")
);

// Test non-alphanumeric separator requirement
assert_eq!(find_prefixed_util("prefixcat", utils.iter().copied()), None); // no separator
assert_eq!(find_prefixed_util("testcat", utils.iter().copied()), None); // no separator

// Test no match
assert_eq!(find_prefixed_util("unknown", utils.iter().copied()), None);
assert_eq!(find_prefixed_util("", utils.iter().copied()), None);

// Test exact util name (should not match as prefixed)
assert_eq!(find_prefixed_util("test", utils.iter().copied()), None);
assert_eq!(find_prefixed_util("cat", utils.iter().copied()), None);
}
}
3 changes: 1 addition & 2 deletions src/uu/arch/src/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ use platform_info::*;

use clap::Command;
use uucore::error::{UResult, USimpleError};
use uucore::locale::{self, get_message};
use uucore::locale::get_message;

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
locale::setup_localization(uucore::util_name())?;
uu_app().try_get_matches_from(args)?;

let uts =
Expand Down
14 changes: 0 additions & 14 deletions src/uu/base32/base32.md

This file was deleted.

9 changes: 9 additions & 0 deletions src/uu/base32/locales/en-US.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
base32-about = encode/decode data and print to standard output
With no FILE, or when FILE is -, read standard input.

The data are encoded as described for the base32 alphabet in RFC 4648.
When decoding, the input may contain newlines in addition
to the bytes of the formal base32 alphabet. Use --ignore-garbage
to attempt to recover from any other non-alphabet bytes in the
encoded stream.
base32-usage = base32 [OPTION]... [FILE]
23 changes: 12 additions & 11 deletions src/uu/base32/src/base32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@

pub mod base_common;

use base_common::ReadSeek;
use clap::Command;
use uucore::{encoding::Format, error::UResult, help_about, help_usage};

const ABOUT: &str = help_about!("base32.md");
const USAGE: &str = help_usage!("base32.md");
use uucore::{encoding::Format, error::UResult, locale::get_message};

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let format = Format::Base32;

let config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;

let mut input: Box<dyn ReadSeek> = base_common::get_input(&config)?;

let (about, usage) = get_info();
let config = base_common::parse_base_cmd_args(args, about, usage)?;
let mut input = base_common::get_input(&config)?;
base_common::handle_input(&mut input, format, config)
}

pub fn uu_app() -> Command {
base_common::base_app(ABOUT, USAGE)
let (about, usage) = get_info();
base_common::base_app(about, usage)
}

Check warning on line 23 in src/uu/base32/src/base32.rs

View check run for this annotation

Codecov / codecov/patch

src/uu/base32/src/base32.rs#L21-L23

Added lines #L21 - L23 were not covered by tests

fn get_info() -> (&'static str, &'static str) {
let about: &'static str = Box::leak(get_message("base32-about").into_boxed_str());
let usage: &'static str = Box::leak(get_message("base32-usage").into_boxed_str());
(about, usage)
}
14 changes: 0 additions & 14 deletions src/uu/base64/base64.md

This file was deleted.

9 changes: 9 additions & 0 deletions src/uu/base64/locales/en-US.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
base64-about = encode/decode data and print to standard output
With no FILE, or when FILE is -, read standard input.

The data are encoded as described for the base64 alphabet in RFC 3548.
When decoding, the input may contain newlines in addition
to the bytes of the formal base64 alphabet. Use --ignore-garbage
to attempt to recover from any other non-alphabet bytes in the
encoded stream.
base64-usage = base64 [OPTION]... [FILE]
20 changes: 11 additions & 9 deletions src/uu/base64/src/base64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@

use clap::Command;
use uu_base32::base_common;
use uucore::{encoding::Format, error::UResult, help_about, help_usage};

const ABOUT: &str = help_about!("base64.md");
const USAGE: &str = help_usage!("base64.md");
use uucore::{encoding::Format, error::UResult, locale::get_message};

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let format = Format::Base64;

let config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;

let (about, usage) = get_info();
let config = base_common::parse_base_cmd_args(args, about, usage)?;
let mut input = base_common::get_input(&config)?;

base_common::handle_input(&mut input, format, config)
}

pub fn uu_app() -> Command {
base_common::base_app(ABOUT, USAGE)
let (about, usage) = get_info();
base_common::base_app(about, usage)
}

fn get_info() -> (&'static str, &'static str) {
let about: &'static str = Box::leak(get_message("base64-about").into_boxed_str());
let usage: &'static str = Box::leak(get_message("base64-usage").into_boxed_str());
(about, usage)
}
9 changes: 0 additions & 9 deletions src/uu/basename/basename.md

This file was deleted.

4 changes: 4 additions & 0 deletions src/uu/basename/locales/en-US.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
basename-about = Print NAME with any leading directory components removed
If specified, also remove a trailing SUFFIX
basename-usage = basename [-z] NAME [SUFFIX]
basename OPTION... NAME...
10 changes: 4 additions & 6 deletions src/uu/basename/src/basename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ use clap::{Arg, ArgAction, Command};
use std::path::{PathBuf, is_separator};
use uucore::display::Quotable;
use uucore::error::{UResult, UUsageError};
use uucore::format_usage;
use uucore::line_ending::LineEnding;
use uucore::{format_usage, help_about, help_usage};

static ABOUT: &str = help_about!("basename.md");

const USAGE: &str = help_usage!("basename.md");
use uucore::locale::get_message;

pub mod options {
pub static MULTIPLE: &str = "multiple";
Expand Down Expand Up @@ -77,8 +75,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.version(uucore::crate_version!())
.about(ABOUT)
.override_usage(format_usage(USAGE))
.about(get_message("basename-about"))
.override_usage(format_usage(&get_message("basename-usage")))
.infer_long_args(true)
.arg(
Arg::new(options::MULTIPLE)
Expand Down
12 changes: 0 additions & 12 deletions src/uu/basenc/basenc.md

This file was deleted.

7 changes: 7 additions & 0 deletions src/uu/basenc/locales/en-US.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
basenc-about = Encode/decode data and print to standard output
With no FILE, or when FILE is -, read standard input.

When decoding, the input may contain newlines in addition to the bytes of
the formal alphabet. Use --ignore-garbage to attempt to recover
from any other non-alphabet bytes in the encoded stream.
basenc-usage = basenc [OPTION]... [FILE]
Loading
Loading