Skip to content

Commit 45b0c39

Browse files
authored
Merge pull request #7892 from cakebaker/uptime_refactor_uumain
uptime: refactor `uumain`
2 parents 99be8f8 + 26e1757 commit 45b0c39

File tree

2 files changed

+47
-65
lines changed

2 files changed

+47
-65
lines changed

src/uu/uptime/src/uptime.rs

Lines changed: 46 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
// spell-checker:ignore getloadavg behaviour loadavg uptime upsecs updays upmins uphours boottime nusers utmpxname gettime clockid
77

88
use chrono::{Local, TimeZone, Utc};
9-
use clap::ArgMatches;
9+
#[cfg(unix)]
10+
use std::ffi::OsString;
1011
use std::io;
1112
use thiserror::Error;
1213
use uucore::error::{UError, UResult};
@@ -44,14 +45,10 @@ pub enum UptimeError {
4445
// io::Error wrapper
4546
#[error("couldn't get boot time: {0}")]
4647
IoErr(#[from] io::Error),
47-
4848
#[error("couldn't get boot time: Is a directory")]
4949
TargetIsDir,
50-
5150
#[error("couldn't get boot time: Illegal seek")]
5251
TargetIsFifo,
53-
#[error("extra operand '{0}'")]
54-
ExtraOperandError(String),
5552
}
5653

5754
impl UError for UptimeError {
@@ -64,41 +61,22 @@ impl UError for UptimeError {
6461
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
6562
let matches = uu_app().try_get_matches_from(args)?;
6663

67-
#[cfg(windows)]
68-
return default_uptime(&matches);
69-
7064
#[cfg(unix)]
71-
{
72-
use std::ffi::OsString;
73-
use uucore::error::set_exit_code;
74-
use uucore::show_error;
75-
76-
let argument = matches.get_many::<OsString>(options::PATH);
77-
78-
// Switches to default uptime behaviour if there is no argument
79-
if argument.is_none() {
80-
return default_uptime(&matches);
81-
}
82-
let mut arg_iter = argument.unwrap();
83-
84-
let file_path = arg_iter.next().unwrap();
85-
if let Some(path) = arg_iter.next() {
86-
// Uptime doesn't attempt to calculate boot time if there is extra arguments.
87-
// Its a fatal error
88-
show_error!(
89-
"{}",
90-
UptimeError::ExtraOperandError(path.to_owned().into_string().unwrap())
91-
);
92-
set_exit_code(1);
93-
return Ok(());
94-
}
65+
let file_path = matches.get_one::<OsString>(options::PATH);
66+
#[cfg(windows)]
67+
let file_path = None;
9568

96-
uptime_with_file(file_path)
69+
if matches.get_flag(options::SINCE) {
70+
uptime_since()
71+
} else if let Some(path) = file_path {
72+
uptime_with_file(path)
73+
} else {
74+
default_uptime()
9775
}
9876
}
9977

10078
pub fn uu_app() -> Command {
101-
Command::new(uucore::util_name())
79+
let cmd = Command::new(uucore::util_name())
10280
.version(uucore::crate_version!())
10381
.about(ABOUT)
10482
.override_usage(format_usage(USAGE))
@@ -109,18 +87,20 @@ pub fn uu_app() -> Command {
10987
.long(options::SINCE)
11088
.help("system up since")
11189
.action(ArgAction::SetTrue),
112-
)
113-
.arg(
114-
Arg::new(options::PATH)
115-
.help("file to search boot time from")
116-
.action(ArgAction::Append)
117-
.value_parser(ValueParser::os_string())
118-
.value_hint(ValueHint::AnyPath),
119-
)
90+
);
91+
#[cfg(unix)]
92+
cmd.arg(
93+
Arg::new(options::PATH)
94+
.help("file to search boot time from")
95+
.action(ArgAction::Set)
96+
.num_args(0..=1)
97+
.value_parser(ValueParser::os_string())
98+
.value_hint(ValueHint::AnyPath),
99+
)
120100
}
121101

122102
#[cfg(unix)]
123-
fn uptime_with_file(file_path: &std::ffi::OsString) -> UResult<()> {
103+
fn uptime_with_file(file_path: &OsString) -> UResult<()> {
124104
use std::fs;
125105
use std::os::unix::fs::FileTypeExt;
126106
use uucore::error::set_exit_code;
@@ -212,27 +192,29 @@ fn uptime_with_file(file_path: &std::ffi::OsString) -> UResult<()> {
212192
Ok(())
213193
}
214194

215-
/// Default uptime behaviour i.e. when no file argument is given.
216-
fn default_uptime(matches: &ArgMatches) -> UResult<()> {
217-
if matches.get_flag(options::SINCE) {
218-
#[cfg(unix)]
219-
#[cfg(not(target_os = "openbsd"))]
220-
let (boot_time, _) = process_utmpx(None);
221-
222-
#[cfg(target_os = "openbsd")]
223-
let uptime = get_uptime(None)?;
224-
#[cfg(unix)]
225-
#[cfg(not(target_os = "openbsd"))]
226-
let uptime = get_uptime(boot_time)?;
227-
#[cfg(target_os = "windows")]
228-
let uptime = get_uptime(None)?;
229-
let initial_date = Local
230-
.timestamp_opt(Utc::now().timestamp() - uptime, 0)
231-
.unwrap();
232-
println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
233-
return Ok(());
234-
}
195+
fn uptime_since() -> UResult<()> {
196+
#[cfg(unix)]
197+
#[cfg(not(target_os = "openbsd"))]
198+
let (boot_time, _) = process_utmpx(None);
235199

200+
#[cfg(target_os = "openbsd")]
201+
let uptime = get_uptime(None)?;
202+
#[cfg(unix)]
203+
#[cfg(not(target_os = "openbsd"))]
204+
let uptime = get_uptime(boot_time)?;
205+
#[cfg(target_os = "windows")]
206+
let uptime = get_uptime(None)?;
207+
208+
let initial_date = Local
209+
.timestamp_opt(Utc::now().timestamp() - uptime, 0)
210+
.unwrap();
211+
println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
212+
213+
Ok(())
214+
}
215+
216+
/// Default uptime behaviour i.e. when no file argument is given.
217+
fn default_uptime() -> UResult<()> {
236218
print_time();
237219
print_uptime(None)?;
238220
print_nusers(None);
@@ -251,7 +233,7 @@ fn print_loadavg() {
251233

252234
#[cfg(unix)]
253235
#[cfg(not(target_os = "openbsd"))]
254-
fn process_utmpx(file: Option<&std::ffi::OsString>) -> (Option<time_t>, usize) {
236+
fn process_utmpx(file: Option<&OsString>) -> (Option<time_t>, usize) {
255237
let mut nusers = 0;
256238
let mut boot_time = None;
257239

tests/by-util/test_uptime.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ fn test_uptime_with_extra_argument() {
251251
.arg("a")
252252
.arg("b")
253253
.fails()
254-
.stderr_contains("extra operand 'b'");
254+
.stderr_contains("unexpected value 'b'");
255255
}
256256
/// Checks whether uptime displays the correct stderr msg when its called with a directory
257257
#[test]

0 commit comments

Comments
 (0)