Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change: Print info/error output to stderr #601

Merged
merged 1 commit into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Upon updating Pueue and restarting the daemon, the previous state will be wiped,
- **Breaking**: Redesigned task editing process [#553](https://github.com/Nukesor/pueue/issues/553).
Pueue now allows editing all properties a task in one editor session. There're two modes to do so: `toml` and `files`.
- Revisited, fixed and cleaned up CLI help texts.
- Print most of Pueue's info/log messages to `stderr`. Only keep useful stuff like json and task log output on `stdout`.

### Add

Expand Down
4 changes: 2 additions & 2 deletions pueue/src/bin/pueued.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// subcommand to install the service
#[cfg(target_os = "windows")]
if opt.service.is_some() {
println!("daemonize flag cannot be used with service subcommand");
eprintln!("daemonize flag cannot be used with service subcommand");
return Ok(());
}

Expand Down Expand Up @@ -120,7 +120,7 @@
let current_exe = if let Ok(path) = std::env::current_exe() {
path.to_string_lossy().clone().to_string()
} else {
println!("Couldn't detect path of current binary. Falling back to 'pueue' in $PATH");
eprintln!("Couldn't detect path of current binary. Falling back to 'pueue' in $PATH");

Check warning on line 123 in pueue/src/bin/pueued.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/bin/pueued.rs#L123

Added line #L123 was not covered by tests
"pueued".to_string()
};

Expand Down
4 changes: 2 additions & 2 deletions pueue/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@
.map(|t| format!("task{t}"))
.collect::<Vec<String>>()
.join(", ");
println!("You are trying to {action}: {task_ids}",);
eprintln!("You are trying to {action}: {task_ids}",);

Check warning on line 355 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L355

Added line #L355 was not covered by tests

let mut input = String::new();

Expand All @@ -364,7 +364,7 @@

match input.chars().next().unwrap() {
'N' | 'n' => {
println!("Aborted!");
eprintln!("Aborted!");

Check warning on line 367 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L367

Added line #L367 was not covered by tests
std::process::exit(1);
}
'\n' | 'Y' | 'y' => {
Expand Down
2 changes: 1 addition & 1 deletion pueue/src/client/commands/restart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
println!("Restarted tasks: {:?}", filtered_tasks.matching_ids);
}
if !filtered_tasks.non_matching_ids.is_empty() {
println!(
eprintln!(

Check warning on line 168 in pueue/src/client/commands/restart.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/commands/restart.rs#L168

Added line #L168 was not covered by tests
"Couldn't restart tasks: {:?}",
filtered_tasks.non_matching_ids
);
Expand Down
2 changes: 1 addition & 1 deletion pueue/src/client/commands/wait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
let tasks = get_tasks(&state, &selection);

if tasks.is_empty() {
println!("No tasks found for selection {selection:?}");
eprintln!("No tasks found for selection {selection:?}");

Check warning on line 61 in pueue/src/client/commands/wait.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/commands/wait.rs#L61

Added line #L61 was not covered by tests
return Ok(());
}

Expand Down
14 changes: 7 additions & 7 deletions pueue/src/client/display/follow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
// Ensure that it exists and is started.
loop {
let Some(task) = get_task(stream, task_id).await? else {
println!("Pueue: The task to be followed doesn't exist.");
eprintln!("Pueue: The task to be followed doesn't exist.");
std::process::exit(1);
};
// Task started up, we can start to follow.
Expand All @@ -42,7 +42,7 @@
let mut handle = match get_log_file_handle(task_id, pueue_directory) {
Ok(stdout) => stdout,
Err(err) => {
println!("Failed to get log file handles: {err}");
eprintln!("Failed to get log file handles: {err}");

Check warning on line 45 in pueue/src/client/display/follow.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/follow.rs#L45

Added line #L45 was not covered by tests
return Ok(());
}
};
Expand All @@ -58,7 +58,7 @@
// The loop following this section will then only copy those last lines to stdout.
if let Some(lines) = lines {
if let Err(err) = seek_to_last_lines(&mut handle, lines) {
println!("Error seeking to last lines from log: {err}");
eprintln!("Error seeking to last lines from log: {err}");

Check warning on line 61 in pueue/src/client/display/follow.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/follow.rs#L61

Added line #L61 was not covered by tests
}
}

Expand All @@ -73,17 +73,17 @@
loop {
// Check whether the file still exists. Exit if it doesn't.
if !path.exists() {
println!("Pueue: Log file has gone away. Has the task been removed?");
eprintln!("Pueue: Log file has gone away. Has the task been removed?");

Check warning on line 76 in pueue/src/client/display/follow.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/follow.rs#L76

Added line #L76 was not covered by tests
return Ok(());
}
// Read the next chunk of text from the last position.
if let Err(err) = io::copy(&mut handle, &mut stdout) {
println!("Pueue: Error while reading file: {err}");
eprintln!("Pueue: Error while reading file: {err}");

Check warning on line 81 in pueue/src/client/display/follow.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/follow.rs#L81

Added line #L81 was not covered by tests
return Ok(());
};
// Flush the stdout buffer to actually print the output.
if let Err(err) = stdout.flush() {
println!("Pueue: Error while flushing stdout: {err}");
eprintln!("Pueue: Error while flushing stdout: {err}");

Check warning on line 86 in pueue/src/client/display/follow.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/follow.rs#L86

Added line #L86 was not covered by tests
return Ok(());
};

Expand All @@ -94,7 +94,7 @@
// In case either is not, exit.
if (last_check % task_check_interval) == 0 {
let Some(task) = get_task(stream, task_id).await? else {
println!("Pueue: The followed task has been removed.");
eprintln!("Pueue: The followed task has been removed.");

Check warning on line 97 in pueue/src/client/display/follow.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/follow.rs#L97

Added line #L97 was not covered by tests
std::process::exit(1);
};
// Task exited by itself. We can stop following.
Expand Down
8 changes: 4 additions & 4 deletions pueue/src/client/display/log/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
let mut file = match get_log_file_handle(task_id, &settings.shared.pueue_directory()) {
Ok(file) => file,
Err(err) => {
println!("Failed to get log file handle: {err}");
eprintln!("Failed to get log file handle: {err}");

Check warning on line 22 in pueue/src/client/display/log/local.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/local.rs#L22

Added line #L22 was not covered by tests
return;
}
};
Expand Down Expand Up @@ -47,7 +47,7 @@
match seek_to_last_lines(file, *lines) {
Ok(complete) => output_complete = complete,
Err(err) => {
println!("Failed reading local log file: {err}");
eprintln!("Failed reading local log file: {err}");

Check warning on line 50 in pueue/src/client/display/log/local.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/local.rs#L50

Added line #L50 was not covered by tests
return;
}
}
Expand All @@ -61,11 +61,11 @@
}

// Print a newline between the task information and the first output.
println!("\n{header}{line_info}");
eprintln!("\n{header}{line_info}");

// Print everything
if let Err(err) = io::copy(file, stdout) {
println!("Failed reading local log file: {err}");
eprintln!("Failed reading local log file: {err}");

Check warning on line 68 in pueue/src/client/display/log/local.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/local.rs#L68

Added line #L68 was not covered by tests
};
}
}
Expand Down
10 changes: 5 additions & 5 deletions pueue/src/client/display/log/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@
if task_logs.is_empty() {
match selection {
TaskSelection::TaskIds(_) => {
println!("There are no finished tasks for your specified ids");
eprintln!("There are no finished tasks for your specified ids");

Check warning on line 77 in pueue/src/client/display/log/mod.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/mod.rs#L77

Added line #L77 was not covered by tests
return;
}
TaskSelection::Group(group) => {
println!("There are no finished tasks for group '{group}'");
eprintln!("There are no finished tasks for group '{group}'");

Check warning on line 81 in pueue/src/client/display/log/mod.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/mod.rs#L81

Added line #L81 was not covered by tests
return;
}
TaskSelection::All => {
println!("There are no finished tasks");
eprintln!("There are no finished tasks");

Check warning on line 85 in pueue/src/client/display/log/mod.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/mod.rs#L85

Added line #L85 was not covered by tests
return;
}
}
Expand Down Expand Up @@ -174,7 +174,7 @@
if style.enabled {
table.enforce_styling();
}
println!("{table}");
eprintln!("{table}");

// All other information is aligned and styled by using a separate table.
let mut table = Table::new();
Expand Down Expand Up @@ -218,5 +218,5 @@
first_column.set_cell_alignment(CellAlignment::Right);
first_column.set_padding((0, 0));

println!("{table}");
eprintln!("{table}");
}
2 changes: 1 addition & 1 deletion pueue/src/client/display/log/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
println!("\n{header}{line_info}");

if let Err(err) = decompress_and_print_remote_log(bytes) {
println!("Error while parsing stdout: {err}");
eprintln!("Error while parsing stdout: {err}");

Check warning on line 29 in pueue/src/client/display/log/remote.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/display/log/remote.rs#L29

Added line #L29 was not covered by tests
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pueue/src/client/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ pub fn print_success(_style: &OutputStyle, message: &str) {
/// Used to style any generic failure message from the daemon.
pub fn print_error(style: &OutputStyle, message: &str) {
let styled = style.style_text(message, Some(Color::Red), None);
println!("{styled}");
eprintln!("{styled}");
}
8 changes: 4 additions & 4 deletions pueue/src/daemon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,14 @@

// Cleanup the pid file
if let Err(error) = pid::cleanup_pid_file(&settings_clone.shared.pid_path()) {
println!("Failed to cleanup pid after panic.");
println!("{error}");
eprintln!("Failed to cleanup pid after panic.");
eprintln!("{error}");

Check warning on line 159 in pueue/src/daemon/mod.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/mod.rs#L158-L159

Added lines #L158 - L159 were not covered by tests
}

// Remove the unix socket.
if let Err(error) = socket_cleanup(&settings_clone.shared) {
println!("Failed to cleanup socket after panic.");
println!("{error}");
eprintln!("Failed to cleanup socket after panic.");
eprintln!("{error}");

Check warning on line 165 in pueue/src/daemon/mod.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/mod.rs#L164-L165

Added lines #L164 - L165 were not covered by tests
}

std::process::exit(1);
Expand Down
2 changes: 1 addition & 1 deletion pueue/src/daemon/network/message_handler/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
// The loop following this section will then only copy those last lines to stdout.
if let Some(lines) = message.lines {
if let Err(err) = seek_to_last_lines(&mut handle, lines) {
println!("Error seeking to last lines from log: {err}");
eprintln!("Error seeking to last lines from log: {err}");

Check warning on line 143 in pueue/src/daemon/network/message_handler/log.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/log.rs#L143

Added line #L143 was not covered by tests
}
}

Expand Down
8 changes: 4 additions & 4 deletions pueue/src/daemon/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ pub fn start_service() -> Result<()> {
service.start::<String>(&[])?;
println!("Successfully started service");
}
ServiceState::StartPending => println!("Service is already starting"),
ServiceState::Running => println!("Service is already running"),
ServiceState::StartPending => eprintln!("Service is already starting"),
ServiceState::Running => eprintln!("Service is already running"),

_ => (),
}
Expand All @@ -211,8 +211,8 @@ pub fn stop_service() -> Result<()> {
let service = service_manager.open_service(SERVICE_NAME, service_access)?;

match service.query_status()?.current_state {
ServiceState::Stopped => println!("Service is already stopped"),
ServiceState::StartPending => println!("Service cannot stop because it is starting (please wait until it fully started to stop it)"),
ServiceState::Stopped => eprintln!("Service is already stopped"),
ServiceState::StartPending => eprintln!("Service cannot stop because it is starting (please wait until it fully started to stop it)"),
ServiceState::Running => {
service.stop()?;
println!("Successfully stopped service");
Expand Down
8 changes: 4 additions & 4 deletions pueue/src/daemon/task_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@

// Remove the unix socket.
if let Err(error) = socket_cleanup(&settings.shared) {
println!("Failed to cleanup socket during shutdown.");
println!("{error}");
eprintln!("Failed to cleanup socket during shutdown.");
eprintln!("{error}");

Check warning on line 84 in pueue/src/daemon/task_handler.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/task_handler.rs#L83-L84

Added lines #L83 - L84 were not covered by tests
}

// Cleanup the pid file
if let Err(error) = cleanup_pid_file(&settings.shared.pid_path()) {
println!("Failed to cleanup pid during shutdown.");
println!("{error}");
eprintln!("Failed to cleanup pid during shutdown.");
eprintln!("{error}");

Check warning on line 90 in pueue/src/daemon/task_handler.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/task_handler.rs#L89-L90

Added lines #L89 - L90 were not covered by tests
}

// Actually exit the program the way we're supposed to.
Expand Down
10 changes: 7 additions & 3 deletions pueue/tests/client/helper/compare_output.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::process::Output;

use anyhow::{bail, Context, Result};
use chrono::Local;
Expand Down Expand Up @@ -84,16 +85,19 @@ pub async fn get_task_context(settings: &Settings) -> Result<HashMap<String, Str
/// and compares it with a given process's `stdout`.
pub fn assert_template_matches(
name: &str,
stdout: Vec<u8>,
output: Output,
context: HashMap<String, String>,
) -> Result<()> {
let mut combined_output = output.stderr.clone();
combined_output.append(&mut output.stdout.clone());

let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("client")
.join("_templates")
.join(name);

let actual = String::from_utf8(stdout).context("Got invalid utf8 as stdout!")?;
let actual = String::from_utf8(combined_output).context("Got invalid utf8 as output!")?;

let Ok(mut expected) = read_to_string(&path) else {
println!("Actual output:\n{actual}");
Expand All @@ -119,7 +123,7 @@ pub fn assert_template_matches(
}

/// Convenience wrapper to compare process stdout with snapshots.
pub fn assert_snapshot_matches_stdout(name: &str, stdout: Vec<u8>) -> Result<()> {
pub fn assert_snapshot_matches_output(name: &str, stdout: Vec<u8>) -> Result<()> {
let actual = String::from_utf8(stdout).context("Got invalid utf8 as stdout!")?;
assert_snapshot_matches(name, actual)
}
Expand Down
8 changes: 4 additions & 4 deletions pueue/tests/client/integration/follow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async fn default(#[case] read_local_logs: bool) -> Result<()> {
// This will result in the client receiving the streamed output until the task finished.
let output = run_client_command(shared, &["follow"])?;

assert_snapshot_matches_stdout("follow__default", output.stdout)?;
assert_snapshot_matches_output("follow__default", output.stdout)?;

Ok(())
}
Expand All @@ -58,7 +58,7 @@ async fn last_lines(#[case] read_local_logs: bool) -> Result<()> {
// Follow the task, but only print the last 4 lines of the output.
let output = run_client_command(shared, &["follow", "--lines=4"])?;

assert_snapshot_matches_stdout("follow__last_lines", output.stdout)?;
assert_snapshot_matches_output("follow__last_lines", output.stdout)?;

Ok(())
}
Expand All @@ -79,7 +79,7 @@ async fn wait_for_task(#[case] read_local_logs: bool) -> Result<()> {
// Wait for the task to start and follow until it finisheds.
let output = run_client_command(shared, &["follow", "0"])?;

assert_snapshot_matches_stdout("follow__default", output.stdout)?;
assert_snapshot_matches_output("follow__default", output.stdout)?;

Ok(())
}
Expand All @@ -98,7 +98,7 @@ async fn fail_on_non_existing(#[case] read_local_logs: bool) -> Result<()> {
// The client should exit with exit code `1`.
let output = run_client_command(shared, &["follow", "0"])?;
assert!(!output.status.success(), "follow got an unexpected exit 0");
assert_snapshot_matches_stdout("follow__fail_on_non_existing", output.stdout)?;
assert_snapshot_matches_output("follow__fail_on_non_existing", output.stderr)?;

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions pueue/tests/client/integration/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async fn default() -> Result<()> {
// Get the group status output
let output = run_client_command(shared, &["group"])?;

assert_snapshot_matches_stdout("group__default", output.stdout)?;
assert_snapshot_matches_output("group__default", output.stdout)?;

Ok(())
}
Expand Down Expand Up @@ -48,7 +48,7 @@ async fn colored() -> Result<()> {
// Get the group status output
let output = run_client_command(shared, &["--color", "always", "group"])?;

assert_snapshot_matches_stdout("group__colored", output.stdout)?;
assert_snapshot_matches_output("group__colored", output.stdout)?;

Ok(())
}
Expand Down
8 changes: 4 additions & 4 deletions pueue/tests/client/integration/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async fn read(#[case] read_local_logs: bool) -> Result<()> {
let output = run_client_command(shared, &["log"])?;

let context = get_task_context(&daemon.settings).await?;
assert_template_matches("log__default", output.stdout, context)?;
assert_template_matches("log__default", output, context)?;

Ok(())
}
Expand Down Expand Up @@ -65,7 +65,7 @@ async fn read_truncated(#[case] read_local_logs: bool) -> Result<()> {
let output = run_client_command(shared, &["log", "--lines=5"])?;

let context = get_task_context(&daemon.settings).await?;
assert_template_matches("log__last_lines", output.stdout, context)?;
assert_template_matches("log__last_lines", output, context)?;

Ok(())
}
Expand All @@ -83,7 +83,7 @@ async fn task_with_label() -> Result<()> {
let output = run_client_command(shared, &["log"])?;

let context = get_task_context(&daemon.settings).await?;
assert_template_matches("log__with_label", output.stdout, context)?;
assert_template_matches("log__with_label", output, context)?;

Ok(())
}
Expand All @@ -101,7 +101,7 @@ async fn colored() -> Result<()> {
let output = run_client_command(shared, &["--color", "always", "log"])?;

let context = get_task_context(&daemon.settings).await?;
assert_template_matches("log__colored", output.stdout, context)?;
assert_template_matches("log__colored", output, context)?;

Ok(())
}
Expand Down
Loading
Loading