Fix sys panic (#12846)

# Description
This should fix #10155 where the `sys` command can panic due to date
math in certain cases / on certain systems.

# User-Facing Changes
The `boot_time` column now has a date value instead of a formatted date
string. This is technically a breaking change.
This commit is contained in:
Ian Manske 2024-05-15 07:40:04 +00:00 committed by GitHub
parent a7807735b1
commit 0cfbdc909e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -16,9 +16,8 @@ pub use sys_::Sys;
pub use temp::SysTemp;
pub use users::SysUsers;
use chrono::{DateTime, Local};
use chrono::{DateTime, FixedOffset, Local};
use nu_protocol::{record, Record, Span, Value};
use std::time::{Duration, UNIX_EPOCH};
use sysinfo::{
Components, CpuRefreshKind, Disks, Networks, System, Users, MINIMUM_CPU_UPDATE_INTERVAL,
};
@ -171,22 +170,31 @@ pub fn host(span: Span) -> Record {
record.push("hostname", Value::string(trim_cstyle_null(hostname), span));
}
record.push(
"uptime",
Value::duration(1000000000 * System::uptime() as i64, span),
);
let uptime = System::uptime()
.saturating_mul(1_000_000_000)
.try_into()
.unwrap_or(i64::MAX);
// Creates a new SystemTime from the specified number of whole seconds
let d = UNIX_EPOCH + Duration::from_secs(System::boot_time());
// Create DateTime from SystemTime
let datetime = DateTime::<Local>::from(d);
// Convert to local time and then rfc3339
let timestamp_str = datetime.with_timezone(datetime.offset()).to_rfc3339();
record.push("boot_time", Value::string(timestamp_str, span));
record.push("uptime", Value::duration(uptime, span));
let boot_time = boot_time()
.map(|time| Value::date(time, span))
.unwrap_or(Value::nothing(span));
record.push("boot_time", boot_time);
record
}
fn boot_time() -> Option<DateTime<FixedOffset>> {
// Broken systems can apparently return really high values.
// See: https://github.com/nushell/nushell/issues/10155
// First, try to convert u64 to i64, and then try to create a `DateTime`.
let secs = System::boot_time().try_into().ok()?;
let time = DateTime::from_timestamp(secs, 0)?;
Some(time.with_timezone(&Local).fixed_offset())
}
pub fn temp(span: Span) -> Value {
let components = Components::new_with_refreshed_list()
.iter()