Skip to content

Commit 47e6a98

Browse files
committed
Ban use of print macros in non-test code
With f472bce (Ignore EPIPE in CLI (#746), 2024-07-17) we added the `_nopipe` variants of the `(e)print(ln)!` macros to avoid panicking when piping to head(1). However, we do not systematically enforce their use, which will inevitably lead inconsistent usage within the project. Add `clippy` lints to ban use of the print macros in all non-test code. Either the `_nopipe` variants should be used when we don't care if the input is read, or `write!` when the information is crucial, such as an interactive session.
1 parent 47e2a94 commit 47e6a98

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

cli/src/cmd_auth.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Copyright 2024 Oxide Computer Company
66

77
use std::fs::File;
8+
use std::io::{self, Write};
89

910
use anyhow::{anyhow, bail, Result};
1011
use async_trait::async_trait;
@@ -237,12 +238,16 @@ impl CmdAuthLogin {
237238
};
238239

239240
if opened {
240-
println!("Opened this URL in your browser:\n {}", uri);
241+
writeln!(io::stdout(), "Opened this URL in your browser:\n {}", uri)?;
241242
} else {
242-
println!("Open this URL in your browser:\n {}", uri);
243+
writeln!(io::stdout(), "Open this URL in your browser:\n {}", uri)?;
243244
}
244245

245-
println!("\nEnter the code: {}\n", details.user_code().secret());
246+
writeln!(
247+
io::stdout(),
248+
"\nEnter the code: {}\n",
249+
details.user_code().secret()
250+
)?;
246251

247252
let token = auth_client
248253
.exchange_device_access_token(&details)
@@ -357,13 +362,17 @@ impl CmdAuthLogin {
357362
silo_name,
358363
} = &user;
359364

360-
println!("Login successful");
361-
println!(" silo: {} ({})", **silo_name, silo_id);
362-
println!(" user: {} ({})", display_name, id);
365+
writeln!(io::stdout(), "Login successful")?;
366+
writeln!(io::stdout(), " silo: {} ({})", **silo_name, silo_id)?;
367+
writeln!(io::stdout(), " user: {} ({})", display_name, id)?;
363368
if ctx.config_file().basics.default_profile.is_none() {
364-
println!("Profile '{}' set as the default", profile_name);
369+
writeln!(
370+
io::stdout(),
371+
"Profile '{}' set as the default",
372+
profile_name
373+
)?;
365374
} else {
366-
println!("Use --profile '{}'", profile_name);
375+
writeln!(io::stdout(), "Use --profile '{}'", profile_name)?;
367376
}
368377

369378
Ok(())
@@ -396,7 +405,7 @@ impl CmdAuthLogout {
396405
if self.all {
397406
// Clear the entire file for users who want to reset their known hosts.
398407
let _ = File::create(credentials_path)?;
399-
println!("Removed all authentication information");
408+
writeln!(io::stdout(), "Removed all authentication information")?;
400409
} else {
401410
let profile = ctx
402411
.client_config()
@@ -424,10 +433,11 @@ impl CmdAuthLogout {
424433
});
425434
std::fs::write(credentials_path, credentials.to_string())
426435
.expect("unable to write credentials.toml");
427-
println!(
436+
writeln!(
437+
io::stdout(),
428438
"Removed authentication information for profile \"{}\"",
429439
profile_name,
430-
);
440+
)?;
431441
}
432442

433443
Ok(())

cli/src/cmd_docs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Copyright 2024 Oxide Computer Company
66

77
use crate::context::Context;
8-
use crate::RunnableCmd;
8+
use crate::{println_nopipe, RunnableCmd};
99

1010
use super::cmd_version::built_info;
1111
use anyhow::Result;
@@ -97,7 +97,7 @@ impl RunnableCmd for CmdDocs {
9797
app.build();
9898
let json_doc = to_json(&app);
9999
let pretty_json = serde_json::to_string_pretty(&json_doc)?;
100-
println!("{}", pretty_json);
100+
println_nopipe!("{}", pretty_json);
101101
Ok(())
102102
}
103103
}

cli/src/cmd_instance.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use oxide::types::{
1414

1515
use oxide::ClientInstancesExt;
1616
use oxide::{Client, ClientImagesExt};
17+
use std::io::{self, Write};
1718
use std::path::PathBuf;
1819

1920
/// Connect to or retrieve data from the instance's serial console.
@@ -196,7 +197,7 @@ impl CmdInstanceSerialHistory {
196197
let data = req.send().await.map_err(|e| e.into_untyped())?.into_inner();
197198

198199
if self.json {
199-
println!("{}", serde_json::to_string(&data)?);
200+
writeln!(io::stdout(), "{}", serde_json::to_string(&data)?)?;
200201
} else {
201202
let mut tty = thouart::Console::new_stdio(None).await?;
202203
tty.write_stdout(&data.data).await?;

cli/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Copyright 2024 Oxide Computer Company
66

77
#![forbid(unsafe_code)]
8+
#![cfg_attr(not(test), deny(clippy::print_stdout, clippy::print_stderr))]
89

910
use std::io;
1011
use std::net::IpAddr;

0 commit comments

Comments
 (0)