basename: Take in parameters as OSString

This will allow us to handle non-Unicode strings correctly.

The logic needs to be updated, next.
This commit is contained in:
Nicolas Boichat 2025-07-22 22:26:55 +08:00
parent cf3fece177
commit 2f53d594aa

View file

@ -5,8 +5,10 @@
// spell-checker:ignore (ToDO) fullname
use clap::builder::ValueParser;
use clap::{Arg, ArgAction, Command};
use std::collections::HashMap;
use std::ffi::OsString;
use std::path::PathBuf;
use uucore::display::Quotable;
use uucore::error::{UResult, UUsageError};
@ -24,8 +26,6 @@ pub mod options {
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = args.collect_lossy();
//
// Argument parsing
//
@ -34,7 +34,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO));
let mut name_args = matches
.get_many::<String>(options::NAME)
.get_many::<OsString>(options::NAME)
.unwrap_or_default()
.collect::<Vec<_>>();
if name_args.is_empty() {
@ -43,18 +43,18 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
get_message("basename-error-missing-operand"),
));
}
let multiple_paths =
matches.get_one::<String>(options::SUFFIX).is_some() || matches.get_flag(options::MULTIPLE);
let multiple_paths = matches.get_one::<OsString>(options::SUFFIX).is_some()
|| matches.get_flag(options::MULTIPLE);
let suffix = if multiple_paths {
matches
.get_one::<String>(options::SUFFIX)
.get_one::<OsString>(options::SUFFIX)
.cloned()
.unwrap_or_default()
} else {
// "simple format"
match name_args.len() {
0 => panic!("already checked"),
1 => String::default(),
1 => OsString::default(),
2 => name_args.pop().unwrap().clone(),
_ => {
return Err(UUsageError::new(
@ -96,6 +96,7 @@ pub fn uu_app() -> Command {
.arg(
Arg::new(options::NAME)
.action(ArgAction::Append)
.value_parser(ValueParser::os_string())
.value_hint(clap::ValueHint::AnyPath)
.hide(true)
.trailing_var_arg(true),
@ -105,6 +106,7 @@ pub fn uu_app() -> Command {
.short('s')
.long(options::SUFFIX)
.value_name("SUFFIX")
.value_parser(ValueParser::os_string())
.help(get_message("basename-help-suffix"))
.overrides_with(options::SUFFIX),
)
@ -118,13 +120,16 @@ pub fn uu_app() -> Command {
)
}
fn basename(fullname: &str, suffix: &str) -> String {
fn basename(fullname: &OsString, suffix: &OsString) -> String {
// TODO: Remove those 2 lines.
let fullname = &fullname.to_string_lossy().to_string();
let suffix = &suffix.to_string_lossy().to_string();
// Handle special case where path ends with /.
if fullname.ends_with("/.") {
return ".".to_string();
}
// Convert to path buffer and get last path component
let pb = PathBuf::from(fullname);
pb.components().next_back().map_or_else(String::new, |c| {