du: Add support for reading time-style from environment

Similar as what ls does, but du has an extra compatibility layer
described in the GNU manual (and that upstream dev helped me
understand: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79113 ).
This commit is contained in:
Nicolas Boichat
2025-07-30 17:27:22 +08:00
parent b99615c1e3
commit 2d63020cd9
2 changed files with 83 additions and 9 deletions
+31 -9
View File
@@ -666,7 +666,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};
let time_format = if time.is_some() {
parse_time_style(matches.get_one::<String>("time-style").map(|s| s.as_str()))?.to_string()
parse_time_style(matches.get_one::<String>("time-style"))?
} else {
format::LONG_ISO.to_string()
};
@@ -755,18 +755,40 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
Ok(())
}
fn parse_time_style(s: Option<&str>) -> UResult<&str> {
// Parse --time-style argument, falling back to environment variable if necessary.
fn parse_time_style(s: Option<&String>) -> UResult<String> {
let s = match s {
Some(s) => Some(s.into()),
None => {
match env::var("TIME_STYLE") {
// Per GNU manual, strip `posix-` if present, ignore anything after a newline if
// the string starts with +, and ignore "locale".
Ok(s) => {
let s = s.strip_prefix("posix-").unwrap_or(s.as_str());
let s = match s.chars().next().unwrap() {
'+' => s.split('\n').next().unwrap(),
_ => s,
};
match s {
"locale" => None,
_ => Some(s.to_string()),
}
}
Err(_) => None,
}
}
};
match s {
Some(s) => match s {
"full-iso" => Ok(format::FULL_ISO),
"long-iso" => Ok(format::LONG_ISO),
"iso" => Ok(format::ISO),
Some(s) => match s.as_ref() {
"full-iso" => Ok(format::FULL_ISO.to_string()),
"long-iso" => Ok(format::LONG_ISO.to_string()),
"iso" => Ok(format::ISO.to_string()),
_ => match s.chars().next().unwrap() {
'+' => Ok(&s[1..]),
_ => Err(DuError::InvalidTimeStyleArg(s.into()).into()),
'+' => Ok(s[1..].to_string()),
_ => Err(DuError::InvalidTimeStyleArg(s).into()),
},
},
None => Ok(format::LONG_ISO),
None => Ok(format::LONG_ISO.to_string()),
}
}
+52
View File
@@ -591,6 +591,7 @@ fn test_du_h_precision() {
}
}
#[allow(clippy::too_many_lines)]
#[cfg(feature = "touch")]
#[test]
fn test_du_time() {
@@ -676,6 +677,57 @@ fn test_du_time() {
.succeeds();
result.stdout_only("0\t2016_\n_00\tdate_test\n");
// Time style can also be setup from environment
let result = ts
.ucmd()
.env("TZ", "UTC")
.env("TIME_STYLE", "full-iso")
.arg("--time")
.arg("date_test")
.succeeds();
result.stdout_only("0\t2016-06-16 00:00:00.000000000 +0000\tdate_test\n");
// For compatibility reason, we also allow posix- prefix.
let result = ts
.ucmd()
.env("TZ", "UTC")
.env("TIME_STYLE", "posix-full-iso")
.arg("--time")
.arg("date_test")
.succeeds();
result.stdout_only("0\t2016-06-16 00:00:00.000000000 +0000\tdate_test\n");
// ... and we strip content after a new line
let result = ts
.ucmd()
.env("TZ", "UTC")
.env("TIME_STYLE", "+XXX\nYYY")
.arg("--time")
.arg("date_test")
.succeeds();
result.stdout_only("0\tXXX\tdate_test\n");
// ... and we ignore "locale", fall back to full-iso.
let result = ts
.ucmd()
.env("TZ", "UTC")
.env("TIME_STYLE", "locale")
.arg("--time")
.arg("date_test")
.succeeds();
result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");
// Command line option takes precedence
let result = ts
.ucmd()
.env("TZ", "UTC")
.env("TIME_STYLE", "full-iso")
.arg("--time")
.arg("--time-style=iso")
.arg("date_test")
.succeeds();
result.stdout_only("0\t2016-06-16\tdate_test\n");
for argument in ["--time=atime", "--time=atim", "--time=a"] {
let result = ts
.ucmd()