Merge pull request #8204 from sylvestre/l10n-env

l10n: port env for translation + add french
This commit is contained in:
Daniel Hofstetter 2025-06-30 14:38:18 +02:00 committed by GitHub
commit 0e69c01fb1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 284 additions and 94 deletions

View file

@ -1,3 +1,43 @@
env-about = Set each NAME to VALUE in the environment and run COMMAND
env-usage = env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
env-after-help = A mere - implies -i. If no COMMAND, print the resulting environment.
# Help messages
env-help-ignore-environment = start with an empty environment
env-help-chdir = change working directory to DIR
env-help-null = end each output line with a 0 byte rather than a newline (only valid when printing the environment)
env-help-file = read and set variables from a ".env"-style configuration file (prior to any unset and/or set)
env-help-unset = remove variable from the environment
env-help-debug = print verbose information for each processing step
env-help-split-string = process and split S into separate arguments; used to pass multiple arguments on shebang lines
env-help-argv0 = Override the zeroth argument passed to the command being executed. Without this option a default value of `command` is used.
env-help-ignore-signal = set handling of SIG signal(s) to do nothing
# Error messages
env-error-missing-closing-quote = no terminating quote in -S string at position { $position } for quote '{ $quote }'
env-error-invalid-backslash-at-end = invalid backslash at end of string in -S at position { $position } in context { $context }
env-error-backslash-c-not-allowed = '\c' must not appear in double-quoted -S string at position { $position }
env-error-invalid-sequence = invalid sequence '\{ $char }' in -S at position { $position }
env-error-missing-closing-brace = Missing closing brace at position { $position }
env-error-missing-variable = Missing variable name at position { $position }
env-error-missing-closing-brace-after-value = Missing closing brace after default value at position { $position }
env-error-unexpected-number = Unexpected character: '{ $char }', expected variable name must not start with 0..9 at position { $position }
env-error-expected-brace-or-colon = Unexpected character: '{ $char }', expected a closing brace ('{"}"}') or colon (':') at position { $position }
env-error-cannot-specify-null-with-command = cannot specify --null (-0) with command
env-error-invalid-signal = { $signal }: invalid signal
env-error-config-file = { $file }: { $error }
env-error-variable-name-issue = variable name issue (at { $position }): { $error }
env-error-generic = Error: { $error }
env-error-no-such-file = { $program }: No such file or directory
env-error-use-s-shebang = use -[v]S to pass options in shebang lines
env-error-cannot-unset = cannot unset '{ $name }': Invalid argument
env-error-cannot-unset-invalid = cannot unset { $name }: Invalid argument
env-error-must-specify-command-with-chdir = must specify command with --chdir (-C)
env-error-cannot-change-directory = cannot change directory to { $directory }: { $error }
env-error-argv0-not-supported = --argv0 is currently not supported on this platform
env-error-permission-denied = { $program }: Permission denied
env-error-unknown = unknown error: { $error }
env-error-failed-set-signal-action = failed to set signal action for signal { $signal }: { $error }
# Warning messages
env-warning-no-name-specified = no name specified for value { $value }

43
src/uu/env/locales/fr-FR.ftl vendored Normal file
View file

@ -0,0 +1,43 @@
env-about = Définir chaque NOM à VALEUR dans l'environnement et exécuter COMMANDE
env-usage = env [OPTION]... [-] [NOM=VALEUR]... [COMMANDE [ARG]...]
env-after-help = Un simple - implique -i. Si aucune COMMANDE, afficher l'environnement résultant.
# Messages d'aide
env-help-ignore-environment = commencer avec un environnement vide
env-help-chdir = changer le répertoire de travail vers RÉP
env-help-null = terminer chaque ligne de sortie avec un octet 0 plutôt qu'un retour à la ligne (valide uniquement lors de l'affichage de l'environnement)
env-help-file = lire et définir les variables à partir d'un fichier de configuration de style ".env" (avant toute suppression et/ou définition)
env-help-unset = supprimer la variable de l'environnement
env-help-debug = afficher des informations détaillées pour chaque étape de traitement
env-help-split-string = traiter et diviser S en arguments séparés ; utilisé pour passer plusieurs arguments sur les lignes shebang
env-help-argv0 = Remplacer le zéroième argument passé à la commande en cours d'exécution. Sans cette option, une valeur par défaut de `command` est utilisée.
env-help-ignore-signal = définir la gestion du/des signal/signaux SIG pour ne rien faire
# Messages d'erreur
env-error-missing-closing-quote = aucune guillemet de fermeture dans la chaîne -S à la position { $position } pour la guillemet '{ $quote }'
env-error-invalid-backslash-at-end = barre oblique inverse invalide à la fin de la chaîne dans -S à la position { $position } dans le contexte { $context }
env-error-backslash-c-not-allowed = '\\c' ne doit pas apparaître dans une chaîne -S entre guillemets doubles à la position { $position }
env-error-invalid-sequence = séquence invalide '\\{ $char }' dans -S à la position { $position }
env-error-missing-closing-brace = Accolade fermante manquante à la position { $position }
env-error-missing-variable = Nom de variable manquant à la position { $position }
env-error-missing-closing-brace-after-value = Accolade fermante manquante après la valeur par défaut à la position { $position }
env-error-unexpected-number = Caractère inattendu : '{ $char }', le nom de variable attendu ne doit pas commencer par 0..9 à la position { $position }
env-error-expected-brace-or-colon = Caractère inattendu : '{ $char }', accolade fermante ('}') ou deux-points (':') attendu à la position { $position }
env-error-cannot-specify-null-with-command = impossible de spécifier --null (-0) avec une commande
env-error-invalid-signal = { $signal } : signal invalide
env-error-config-file = { $file } : { $error }
env-error-variable-name-issue = problème de nom de variable (à { $position }) : { $error }
env-error-generic = Erreur : { $error }
env-error-no-such-file = { $program } : Aucun fichier ou répertoire de ce type
env-error-use-s-shebang = utilisez -[v]S pour passer des options dans les lignes shebang
env-error-cannot-unset = impossible de supprimer '{ $name }' : Argument invalide
env-error-cannot-unset-invalid = impossible de supprimer { $name } : Argument invalide
env-error-must-specify-command-with-chdir = doit spécifier une commande avec --chdir (-C)
env-error-cannot-change-directory = impossible de changer de répertoire vers { $directory } : { $error }
env-error-argv0-not-supported = --argv0 n'est actuellement pas supporté sur cette plateforme
env-error-permission-denied = { $program } : Permission refusée
env-error-unknown = erreur inconnue : { $error }
env-error-failed-set-signal-action = échec de la définition de l'action du signal pour le signal { $signal } : { $error }
# Messages d'avertissement
env-warning-no-name-specified = aucun nom spécifié pour la valeur { $value }

233
src/uu/env/src/env.rs vendored
View file

@ -22,6 +22,7 @@ use nix::sys::signal::{
SaFlags, SigAction, SigHandler, SigHandler::SigIgn, SigSet, Signal, raise, sigaction, signal,
};
use std::borrow::Cow;
use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
@ -34,6 +35,7 @@ use std::process::{self};
use uucore::display::Quotable;
use uucore::error::{ExitCode, UError, UResult, USimpleError, UUsageError};
use uucore::line_ending::LineEnding;
use uucore::locale::{get_message, get_message_with_args};
#[cfg(unix)]
use uucore::signals::signal_by_name_or_value;
use uucore::{format_usage, show_warning};
@ -42,23 +44,23 @@ use thiserror::Error;
#[derive(Debug, Error, PartialEq)]
pub enum EnvError {
#[error("no terminating quote in -S string")]
#[error("{}", get_message_with_args("env-error-missing-closing-quote", HashMap::from([("position".to_string(), .0.to_string()), ("quote".to_string(), .1.to_string())])))]
EnvMissingClosingQuote(usize, char),
#[error("invalid backslash at end of string in -S")]
#[error("{}", get_message_with_args("env-error-invalid-backslash-at-end", HashMap::from([("position".to_string(), .0.to_string()), ("context".to_string(), .1.clone())])))]
EnvInvalidBackslashAtEndOfStringInMinusS(usize, String),
#[error("'\\c' must not appear in double-quoted -S string")]
#[error("{}", get_message_with_args("env-error-backslash-c-not-allowed", HashMap::from([("position".to_string(), .0.to_string())])))]
EnvBackslashCNotAllowedInDoubleQuotes(usize),
#[error("invalid sequence '\\{}' in -S",.1)]
#[error("{}", get_message_with_args("env-error-invalid-sequence", HashMap::from([("position".to_string(), .0.to_string()), ("char".to_string(), .1.to_string())])))]
EnvInvalidSequenceBackslashXInMinusS(usize, char),
#[error("Missing closing brace")]
#[error("{}", get_message_with_args("env-error-missing-closing-brace", HashMap::from([("position".to_string(), .0.to_string())])))]
EnvParsingOfVariableMissingClosingBrace(usize),
#[error("Missing variable name")]
#[error("{}", get_message_with_args("env-error-missing-variable", HashMap::from([("position".to_string(), .0.to_string())])))]
EnvParsingOfMissingVariable(usize),
#[error("Missing closing brace after default value at {}",.0)]
#[error("{}", get_message_with_args("env-error-missing-closing-brace-after-value", HashMap::from([("position".to_string(), .0.to_string())])))]
EnvParsingOfVariableMissingClosingBraceAfterValue(usize),
#[error("Unexpected character: '{}', expected variable name must not start with 0..9",.1)]
#[error("{}", get_message_with_args("env-error-unexpected-number", HashMap::from([("position".to_string(), .0.to_string()), ("char".to_string(), .1.clone())])))]
EnvParsingOfVariableUnexpectedNumber(usize, String),
#[error("Unexpected character: '{}', expected a closing brace ('}}') or colon (':')",.1)]
#[error("{}", get_message_with_args("env-error-expected-brace-or-colon", HashMap::from([("position".to_string(), .0.to_string()), ("char".to_string(), .1.clone())])))]
EnvParsingOfVariableExceptedBraceOrColon(usize, String),
#[error("")]
EnvReachedEnd,
@ -74,8 +76,6 @@ impl From<string_parser::Error> for EnvError {
}
}
use uucore::locale::get_message;
mod options {
pub const IGNORE_ENVIRONMENT: &str = "ignore-environment";
pub const CHDIR: &str = "chdir";
@ -88,8 +88,6 @@ mod options {
pub const IGNORE_SIGNAL: &str = "ignore-signal";
}
const ERROR_MSG_S_SHEBANG: &str = "use -[v]S to pass options in shebang lines";
struct Options<'a> {
ignore_env: bool,
line_ending: LineEnding,
@ -131,7 +129,7 @@ fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a OsStr) -> UResult<()>
if opts.line_ending == LineEnding::Nul {
Err(UUsageError::new(
125,
"cannot specify --null (-0) with command".to_string(),
get_message("env-error-cannot-specify-null-with-command"),
))
} else {
opts.program.push(opt);
@ -143,7 +141,13 @@ fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a OsStr) -> UResult<()>
fn parse_signal_value(signal_name: &str) -> UResult<usize> {
let signal_name_upcase = signal_name.to_uppercase();
let optional_signal_value = signal_by_name_or_value(&signal_name_upcase);
let error = USimpleError::new(125, format!("{}: invalid signal", signal_name.quote()));
let error = USimpleError::new(
125,
get_message_with_args(
"env-error-invalid-signal",
HashMap::from([("signal".to_string(), signal_name.quote().to_string())]),
),
);
match optional_signal_value {
Some(sig_val) => {
if sig_val == 0 {
@ -177,7 +181,10 @@ fn parse_signal_opt<'a>(opts: &mut Options<'a>, opt: &'a OsStr) -> UResult<()> {
let Some(sig_str) = sig.to_str() else {
return Err(USimpleError::new(
1,
format!("{}: invalid signal", sig.quote()),
get_message_with_args(
"env-error-invalid-signal",
HashMap::from([("signal".to_string(), sig.quote().to_string())]),
),
));
};
let sig_val = parse_signal_value(sig_str)?;
@ -201,8 +208,18 @@ fn load_config_file(opts: &mut Options) -> UResult<()> {
Ini::load_from_file(file)
};
let conf =
conf.map_err(|e| USimpleError::new(1, format!("{}: {e}", file.maybe_quote())))?;
let conf = conf.map_err(|e| {
USimpleError::new(
1,
get_message_with_args(
"env-error-config-file",
HashMap::from([
("file".to_string(), file.maybe_quote().to_string()),
("error".to_string(), e.to_string()),
]),
),
)
})?;
for (_, prop) in &conf {
// ignore all INI section lines (treat them as comments)
@ -229,7 +246,7 @@ pub fn uu_app() -> Command {
Arg::new(options::IGNORE_ENVIRONMENT)
.short('i')
.long(options::IGNORE_ENVIRONMENT)
.help("start with an empty environment")
.help(get_message("env-help-ignore-environment"))
.action(ArgAction::SetTrue),
)
.arg(
@ -240,16 +257,13 @@ pub fn uu_app() -> Command {
.value_name("DIR")
.value_parser(ValueParser::os_string())
.value_hint(clap::ValueHint::DirPath)
.help("change working directory to DIR"),
.help(get_message("env-help-chdir")),
)
.arg(
Arg::new(options::NULL)
.short('0')
.long(options::NULL)
.help(
"end each output line with a 0 byte rather than a newline (only \
valid when printing the environment)",
)
.help(get_message("env-help-null"))
.action(ArgAction::SetTrue),
)
.arg(
@ -260,10 +274,7 @@ pub fn uu_app() -> Command {
.value_hint(clap::ValueHint::FilePath)
.value_parser(ValueParser::os_string())
.action(ArgAction::Append)
.help(
"read and set variables from a \".env\"-style configuration file \
(prior to any unset and/or set)",
),
.help(get_message("env-help-file")),
)
.arg(
Arg::new(options::UNSET)
@ -272,14 +283,14 @@ pub fn uu_app() -> Command {
.value_name("NAME")
.action(ArgAction::Append)
.value_parser(ValueParser::os_string())
.help("remove variable from the environment"),
.help(get_message("env-help-unset")),
)
.arg(
Arg::new(options::DEBUG)
.short('v')
.long(options::DEBUG)
.action(ArgAction::Count)
.help("print verbose information for each processing step"),
.help(get_message("env-help-debug")),
)
.arg(
Arg::new(options::SPLIT_STRING) // split string handling is implemented directly, not using CLAP. But this entry here is needed for the help information output.
@ -288,8 +299,9 @@ pub fn uu_app() -> Command {
.value_name("S")
.action(ArgAction::Set)
.value_parser(ValueParser::os_string())
.help("process and split S into separate arguments; used to pass multiple arguments on shebang lines")
).arg(
.help(get_message("env-help-split-string")),
)
.arg(
Arg::new(options::ARGV0)
.overrides_with(options::ARGV0)
.short('a')
@ -297,13 +309,12 @@ pub fn uu_app() -> Command {
.value_name("a")
.action(ArgAction::Set)
.value_parser(ValueParser::os_string())
.help("Override the zeroth argument passed to the command being executed. \
Without this option a default value of `command` is used.")
.help(get_message("env-help-argv0")),
)
.arg(
Arg::new("vars")
.action(ArgAction::Append)
.value_parser(ValueParser::os_string())
.value_parser(ValueParser::os_string()),
)
.arg(
Arg::new(options::IGNORE_SIGNAL)
@ -311,7 +322,7 @@ pub fn uu_app() -> Command {
.value_name("SIG")
.action(ArgAction::Append)
.value_parser(ValueParser::os_string())
.help("set handling of SIG signal(s) to do nothing")
.help(get_message("env-help-ignore-signal")),
)
}
@ -325,22 +336,63 @@ pub fn parse_args_from_str(text: &NativeIntStr) -> UResult<Vec<NativeIntString>>
USimpleError::new(125, e.to_string())
}
EnvError::EnvMissingClosingQuote(_, _) => USimpleError::new(125, e.to_string()),
EnvError::EnvParsingOfVariableMissingClosingBrace(pos) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {e}"))
}
EnvError::EnvParsingOfMissingVariable(pos) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {e}"))
}
EnvError::EnvParsingOfVariableMissingClosingBraceAfterValue(pos) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {e}"))
}
EnvError::EnvParsingOfVariableUnexpectedNumber(pos, _) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {e}"))
}
EnvError::EnvParsingOfVariableExceptedBraceOrColon(pos, _) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {e}"))
}
_ => USimpleError::new(125, format!("Error: {e:?}")),
EnvError::EnvParsingOfVariableMissingClosingBrace(pos) => USimpleError::new(
125,
get_message_with_args(
"env-error-variable-name-issue",
HashMap::from([
("position".to_string(), pos.to_string()),
("error".to_string(), e.to_string()),
]),
),
),
EnvError::EnvParsingOfMissingVariable(pos) => USimpleError::new(
125,
get_message_with_args(
"env-error-variable-name-issue",
HashMap::from([
("position".to_string(), pos.to_string()),
("error".to_string(), e.to_string()),
]),
),
),
EnvError::EnvParsingOfVariableMissingClosingBraceAfterValue(pos) => USimpleError::new(
125,
get_message_with_args(
"env-error-variable-name-issue",
HashMap::from([
("position".to_string(), pos.to_string()),
("error".to_string(), e.to_string()),
]),
),
),
EnvError::EnvParsingOfVariableUnexpectedNumber(pos, _) => USimpleError::new(
125,
get_message_with_args(
"env-error-variable-name-issue",
HashMap::from([
("position".to_string(), pos.to_string()),
("error".to_string(), e.to_string()),
]),
),
),
EnvError::EnvParsingOfVariableExceptedBraceOrColon(pos, _) => USimpleError::new(
125,
get_message_with_args(
"env-error-variable-name-issue",
HashMap::from([
("position".to_string(), pos.to_string()),
("error".to_string(), e.to_string()),
]),
),
),
_ => USimpleError::new(
125,
get_message_with_args(
"env-error-generic",
HashMap::from([("error".to_string(), format!("{e:?}"))]),
),
),
})
}
@ -385,9 +437,15 @@ struct EnvAppData {
impl EnvAppData {
fn make_error_no_such_file_or_dir(&self, prog: &OsStr) -> Box<dyn UError> {
uucore::show_error!("{}: No such file or directory", prog.quote());
uucore::show_error!(
"{}",
get_message_with_args(
"env-error-no-such-file",
HashMap::from([("program".to_string(), prog.quote().to_string())])
)
);
if !self.had_string_argument {
uucore::show_error!("{ERROR_MSG_S_SHEBANG}");
uucore::show_error!("{}", get_message("env-error-use-s-shebang"));
}
ExitCode::new(127)
}
@ -461,7 +519,10 @@ impl EnvAppData {
{
return Err(USimpleError::new(
125,
format!("cannot unset '{}': Invalid argument", &arg_str[2..]),
get_message_with_args(
"env-error-cannot-unset",
HashMap::from([("name".to_string(), arg_str[2..].to_string())]),
),
));
}
@ -493,7 +554,7 @@ impl EnvAppData {
let s = s.trim_end();
uucore::show_error!("{s}");
}
uucore::show_error!("{ERROR_MSG_S_SHEBANG}");
uucore::show_error!("{}", get_message("env-error-use-s-shebang"));
ExitCode::new(125)
}
}
@ -578,7 +639,7 @@ impl EnvAppData {
#[cfg(not(unix))]
return Err(USimpleError::new(
2,
"--argv0 is currently not supported on this platform",
get_message("env-error-argv0-not-supported"),
));
}
@ -629,11 +690,23 @@ impl EnvAppData {
Err(self.make_error_no_such_file_or_dir(&prog))
}
io::ErrorKind::PermissionDenied => {
uucore::show_error!("{}: Permission denied", prog.quote());
uucore::show_error!(
"{}",
get_message_with_args(
"env-error-permission-denied",
HashMap::from([("program".to_string(), prog.quote().to_string())])
)
);
Err(126.into())
}
_ => {
uucore::show_error!("unknown error: {err:?}");
uucore::show_error!(
"{}",
get_message_with_args(
"env-error-unknown",
HashMap::from([("error".to_string(), format!("{err:?}"))])
)
);
Err(126.into())
}
};
@ -722,7 +795,10 @@ fn apply_unset_env_vars(opts: &Options<'_>) -> Result<(), Box<dyn UError>> {
{
return Err(USimpleError::new(
125,
format!("cannot unset {}: Invalid argument", name.quote()),
get_message_with_args(
"env-error-cannot-unset-invalid",
HashMap::from([("name".to_string(), name.quote().to_string())]),
),
));
}
unsafe {
@ -737,7 +813,7 @@ fn apply_change_directory(opts: &Options<'_>) -> Result<(), Box<dyn UError>> {
if opts.program.is_empty() && opts.running_directory.is_some() {
return Err(UUsageError::new(
125,
"must specify command with --chdir (-C)".to_string(),
get_message("env-error-must-specify-command-with-chdir"),
));
}
@ -747,7 +823,13 @@ fn apply_change_directory(opts: &Options<'_>) -> Result<(), Box<dyn UError>> {
Err(error) => {
return Err(USimpleError::new(
125,
format!("cannot change directory to {}: {error}", d.quote()),
get_message_with_args(
"env-error-cannot-change-directory",
HashMap::from([
("directory".to_string(), d.quote().to_string()),
("error".to_string(), error.to_string()),
]),
),
));
}
};
@ -781,7 +863,13 @@ fn apply_specified_env_vars(opts: &Options<'_>) {
*/
if name.is_empty() {
show_warning!("no name specified for value {}", val.quote());
show_warning!(
"{}",
get_message_with_args(
"env-warning-no-name-specified",
HashMap::from([("value".to_string(), val.quote().to_string())])
)
);
continue;
}
unsafe {
@ -809,10 +897,12 @@ fn ignore_signal(sig: Signal) -> UResult<()> {
if let Err(err) = result {
return Err(USimpleError::new(
125,
format!(
"failed to set signal action for signal {}: {}",
sig as i32,
err.desc()
get_message_with_args(
"env-error-failed-set-signal-action",
HashMap::from([
("signal".to_string(), (sig as i32).to_string()),
("error".to_string(), err.desc().to_string()),
]),
),
));
}
@ -827,6 +917,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
#[cfg(test)]
mod tests {
use super::*;
use uucore::locale;
#[test]
fn test_split_string_environment_vars_test() {
@ -861,12 +952,14 @@ mod tests {
#[test]
fn test_error_cases() {
let _ = locale::setup_localization("env");
// Test EnvBackslashCNotAllowedInDoubleQuotes
let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \c""#));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"'\\c' must not appear in double-quoted -S string"
"'\\c' must not appear in double-quoted -S string at position 13"
);
// Test EnvInvalidBackslashAtEndOfStringInMinusS
@ -874,7 +967,7 @@ mod tests {
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"no terminating quote in -S string"
"no terminating quote in -S string at position 13 for quote '\"'"
);
// Test EnvInvalidSequenceBackslashXInMinusS
@ -892,7 +985,7 @@ mod tests {
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"no terminating quote in -S string"
"no terminating quote in -S string at position 12 for quote '\"'"
);
// Test variable-related errors

View file

@ -522,7 +522,7 @@ fn test_split_string_into_args_s_escaped_c_not_allowed() {
let out = scene.ucmd().args(&[r#"-S"\c""#]).fails().stderr_move_str();
assert_eq!(
out,
"env: '\\c' must not appear in double-quoted -S string\n"
"env: '\\c' must not appear in double-quoted -S string at position 2\n"
);
}
@ -608,91 +608,91 @@ fn test_env_parsing_errors() {
.arg("-S\\|echo hallo") // no quotes, invalid escape sequence |
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\|' in -S\n");
.stderr_is("env: invalid sequence '\\|' in -S at position 1\n");
ts.ucmd()
.arg("-S\\a") // no quotes, invalid escape sequence a
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\a' in -S\n");
.stderr_is("env: invalid sequence '\\a' in -S at position 1\n");
ts.ucmd()
.arg("-S\"\\a\"") // double quotes, invalid escape sequence a
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\a' in -S\n");
.stderr_is("env: invalid sequence '\\a' in -S at position 2\n");
ts.ucmd()
.arg(r#"-S"\a""#) // same as before, just using r#""#
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\a' in -S\n");
.stderr_is("env: invalid sequence '\\a' in -S at position 2\n");
ts.ucmd()
.arg("-S'\\a'") // single quotes, invalid escape sequence a
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\a' in -S\n");
.stderr_is("env: invalid sequence '\\a' in -S at position 2\n");
ts.ucmd()
.arg(r"-S\|\&\;") // no quotes, invalid escape sequence |
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\|' in -S\n");
.stderr_is("env: invalid sequence '\\|' in -S at position 1\n");
ts.ucmd()
.arg(r"-S\<\&\;") // no quotes, invalid escape sequence <
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\<' in -S\n");
.stderr_is("env: invalid sequence '\\<' in -S at position 1\n");
ts.ucmd()
.arg(r"-S\>\&\;") // no quotes, invalid escape sequence >
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\>' in -S\n");
.stderr_is("env: invalid sequence '\\>' in -S at position 1\n");
ts.ucmd()
.arg(r"-S\`\&\;") // no quotes, invalid escape sequence `
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\`' in -S\n");
.stderr_is("env: invalid sequence '\\`' in -S at position 1\n");
ts.ucmd()
.arg(r#"-S"\`\&\;""#) // double quotes, invalid escape sequence `
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\`' in -S\n");
.stderr_is("env: invalid sequence '\\`' in -S at position 2\n");
ts.ucmd()
.arg(r"-S'\`\&\;'") // single quotes, invalid escape sequence `
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\`' in -S\n");
.stderr_is("env: invalid sequence '\\`' in -S at position 2\n");
ts.ucmd()
.arg(r"-S\`") // ` escaped without quotes
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\`' in -S\n");
.stderr_is("env: invalid sequence '\\`' in -S at position 1\n");
ts.ucmd()
.arg(r#"-S"\`""#) // ` escaped in double quotes
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\`' in -S\n");
.stderr_is("env: invalid sequence '\\`' in -S at position 2\n");
ts.ucmd()
.arg(r"-S'\`'") // ` escaped in single quotes
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\`' in -S\n");
.stderr_is("env: invalid sequence '\\`' in -S at position 2\n");
ts.ucmd()
.args(&[r"-S\🦉"]) // ` escaped in single quotes
.fails_with_code(125)
.no_stdout()
.stderr_is("env: invalid sequence '\\\u{FFFD}' in -S\n"); // gnu doesn't show the owl. Instead a invalid unicode ?
.stderr_is("env: invalid sequence '\\\u{FFFD}' in -S at position 1\n"); // gnu doesn't show the owl. Instead a invalid unicode ?
}
#[test]

View file

@ -2,27 +2,41 @@ Index: gnu/tests/env/env-S.pl
===================================================================
--- gnu.orig/tests/env/env-S.pl
+++ gnu/tests/env/env-S.pl
@@ -212,27 +212,28 @@ my @Tests =
{ERR=>"$prog: no terminating quote in -S string\n"}],
@@ -200,36 +200,37 @@ my @Tests =
# Test Error Conditions
['err1', q[-S'"\\c"'], {EXIT=>125},
- {ERR=>"$prog: '\\c' must not appear in double-quoted -S string\n"}],
+ {ERR=>"$prog: '\\c' must not appear in double-quoted -S string at position 2\n"}],
['err2', q[-S'A=B\\'], {EXIT=>125},
- {ERR=>"$prog: invalid backslash at end of string in -S\n"}],
+ {ERR=>"$prog: invalid backslash at end of string in -S at position 4 in context Unquoted\n"}],
['err3', q[-S'"A=B\\"'], {EXIT=>125},
- {ERR=>"$prog: no terminating quote in -S string\n"}],
+ {ERR=>"$prog: no terminating quote in -S string at position 6 for quote '\"'\n"}],
['err4', q[-S"'A=B\\\\'"], {EXIT=>125},
- {ERR=>"$prog: no terminating quote in -S string\n"}],
+ {ERR=>"$prog: no terminating quote in -S string at position 6 for quote '''\n"}],
['err5', q[-S'A=B\\q'], {EXIT=>125},
{ERR=>"$prog: invalid sequence '\\q' in -S\n"}],
- {ERR=>"$prog: invalid sequence '\\q' in -S\n"}],
- ['err6', q[-S'A=$B'], {EXIT=>125},
- {ERR=>"$prog: only \${VARNAME} expansion is supported, error at: \$B\n"}],
+ {ERR=>"$prog: invalid sequence '\\q' in -S at position 4\n"}],
+ ['err6', q[-S'A=$B echo hello'], {EXIT=>0},
+ {OUT=>"hello"}],
['err7', q[-S'A=${B'], {EXIT=>125},
- {ERR=>"$prog: only \${VARNAME} expansion is supported, " .
- "error at: \${B\n"}],
+ {ERR=>"$prog" . qq[: variable name issue (at 5): Missing closing brace\n]}],
+ {ERR=>"$prog" . qq[: variable name issue (at 5): Missing closing brace at position 5\n]}],
['err8', q[-S'A=${B%B}'], {EXIT=>125},
- {ERR=>"$prog: only \${VARNAME} expansion is supported, " .
- "error at: \${B%B}\n"}],
+ {ERR=>"$prog" . qq[: variable name issue (at 5): Unexpected character: '%', expected a closing brace ('}') or colon (':')\n]}],
+ {ERR=>"$prog" . qq[: variable name issue (at 5): Unexpected character: '%', expected a closing brace ('}') or colon (':') at position 5\n]}],
['err9', q[-S'A=${9B}'], {EXIT=>125},
- {ERR=>"$prog: only \${VARNAME} expansion is supported, " .
- "error at: \${9B}\n"}],
+ {ERR=>"$prog" . qq[: variable name issue (at 4): Unexpected character: '9', expected variable name must not start with 0..9\n]}],
+ {ERR=>"$prog" . qq[: variable name issue (at 4): Unexpected character: '9', expected variable name must not start with 0..9 at position 4\n]}],
# Test incorrect shebang usage (extraneous whitespace).
['err_sp2', q['-v -S cat -n'], {EXIT=>125},
- {ERR=>"env: invalid option -- ' '\n" .
@ -42,6 +56,6 @@ Index: gnu/tests/env/env-S.pl
+ "Usage: $prog [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]\n\n" .
+ "For more information, try '--help'.\n" .
+ "$prog: use -[v]S to pass options in shebang lines\n"}],
# Also diagnose incorrect shebang usage when failing to exec.
# This typically happens with: