Skip to content

Commit 20f7af8

Browse files
authored
stat: warn once when QUOTING_STYLE env has an unknown value (#12136)
* stat: warn once when QUOTING_STYLE env has an unknown value * Add spell-checker directive to test_stat.rs
1 parent aeaf810 commit 20f7af8

4 files changed

Lines changed: 70 additions & 4 deletions

File tree

src/uu/stat/locales/en-US.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ stat-after-help = Valid format sequences for files (without `--file-system`):
5656
## Error messages
5757

5858
stat-error-invalid-quoting-style = Invalid quoting style: {$style}
59+
stat-warning-invalid-env-quoting-style = ignoring invalid value of environment variable QUOTING_STYLE: '{$style}'
5960
stat-error-missing-operand = missing operand
6061
Try 'stat --help' for more information.
6162
stat-error-invalid-directive = {$directive}: invalid directive

src/uu/stat/locales/fr-FR.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ stat-word-birth = Créé
9292
## Messages d'erreur
9393

9494
stat-error-invalid-quoting-style = Style de guillemets invalide : {$style}
95+
stat-warning-invalid-env-quoting-style = valeur invalide de la variable d'environnement QUOTING_STYLE ignorée : '{$style}'
9596
stat-error-missing-operand = opérande manquant
9697
Essayez 'stat --help' pour plus d'informations.
9798
stat-error-invalid-directive = {$directive} : directive invalide

src/uu/stat/src/stat.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,16 +451,32 @@ fn quote_file_name(file_name: &str, quoting_style: &QuotingStyle) -> String {
451451
}
452452
}
453453

454+
fn warn_invalid_quoting_style(style: &str) {
455+
use std::sync::atomic::{AtomicBool, Ordering};
456+
static WARNED: AtomicBool = AtomicBool::new(false);
457+
if !WARNED.swap(true, Ordering::Relaxed) {
458+
show_error!(
459+
"{}",
460+
translate!("stat-warning-invalid-env-quoting-style", "style" => style.to_string())
461+
);
462+
}
463+
}
464+
454465
fn get_quoted_file_name(
455466
display_name: &str,
456467
file: &OsString,
457468
file_type: FileType,
458469
from_user: bool,
459470
) -> Result<String, i32> {
460-
let quoting_style = env::var("QUOTING_STYLE")
461-
.ok()
462-
.and_then(|style| style.parse().ok())
463-
.unwrap_or_default();
471+
let quoting_style = match env::var("QUOTING_STYLE") {
472+
Ok(style) => style.parse().unwrap_or_else(|_| {
473+
// Match GNU coreutils 9.11: warn (once) when QUOTING_STYLE is set
474+
// to a value we don't understand, then fall back to the default.
475+
warn_invalid_quoting_style(&style);
476+
QuotingStyle::default()
477+
}),
478+
Err(_) => QuotingStyle::default(),
479+
};
464480

465481
if file_type.is_symlink() {
466482
let quoted_display_name = quote_file_name(display_name, &quoting_style);

tests/by-util/test_stat.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
// spell-checker:ignore crème brûlée
7+
68
use uutests::at_and_ucmd;
79
use uutests::new_ucmd;
810
use uutests::unwrap_or_return;
@@ -447,6 +449,52 @@ fn test_quoting_style_locale() {
447449
.stdout_only("\'\"\'\n");
448450
}
449451

452+
#[test]
453+
fn test_quoting_style_invalid_env() {
454+
let ts = TestScenario::new(util_name!());
455+
let at = &ts.fixtures;
456+
at.touch("baguette");
457+
at.touch("Croissant");
458+
at.touch("Escargot");
459+
460+
let needle = "ignoring invalid value of environment variable QUOTING_STYLE";
461+
462+
// A bogus value triggers exactly one warning across multiple files and the
463+
// output falls back to the default (shell-escape) style.
464+
let res = ts
465+
.ucmd()
466+
.env("QUOTING_STYLE", "fromage")
467+
.args(&["-c", "nom=[%N]", "baguette", "Croissant", "Escargot"])
468+
.succeeds();
469+
res.stdout_is("nom=['baguette']\nnom=['Croissant']\nnom=['Escargot']\n");
470+
assert_eq!(res.stderr_str().matches(needle).count(), 1);
471+
472+
// An empty value is also invalid and must be reported with empty quotes.
473+
ts.ucmd()
474+
.env("QUOTING_STYLE", "")
475+
.args(&["-c", "%N", "baguette"])
476+
.succeeds()
477+
.stdout_is("'baguette'\n")
478+
.stderr_is("stat: ignoring invalid value of environment variable QUOTING_STYLE: ''\n");
479+
480+
// %%%N: a literal '%' followed by the quoted name, fallback style applies.
481+
ts.ucmd()
482+
.env("QUOTING_STYLE", "soufflé")
483+
.args(&["-c", "%%%N", "baguette"])
484+
.succeeds()
485+
.stdout_is("%'baguette'\n")
486+
.stderr_is(
487+
"stat: ignoring invalid value of environment variable QUOTING_STYLE: 'soufflé'\n",
488+
);
489+
490+
// When the format never consults %N, QUOTING_STYLE must not be parsed at all.
491+
ts.ucmd()
492+
.env("QUOTING_STYLE", "crème-brûlée")
493+
.args(&["-c", "taille=%s genre:%F brut=%n", "baguette"])
494+
.succeeds()
495+
.no_stderr();
496+
}
497+
450498
#[test]
451499
fn test_printf_octal_1() {
452500
let ts = TestScenario::new(util_name!());

0 commit comments

Comments
 (0)