command-ext

Crates.iocommand-ext
lib.rscommand-ext
version0.1.2
sourcesrc
created_at2023-12-13 21:12:11.755493
updated_at2024-03-01 21:40:20.241767
descriptionExtension traits for std::process::Command
homepage
repositoryhttps://github.com/novafacing/command-ext
max_upload_size
id1068447
size80,482
Rowan Hart (novafacing)

documentation

README

CommandExt

CommandExt is a set of convenient extension traits for std::process::Command which make it easier to use, particularly in cargo scripts where many commands may be executed with different requirements for error checking, logging, and so forth.

CommandExtCheck

CommandExtCheck allows you to check the result of a command and get a nicely packaged error containing printable output and error streams.

use std::process::Command;
use command_ext::CommandExtCheck;
fn main() -> anyhow::Result<()> {
    Command::new("echo").arg("x").check()?; // Ok!
    Command::new("noexistcmd").arg("badarg").check().map_err(|e| {
        // StdIoError(Os { code: 2, kind: NotFound, message: "No such file or directory" })
        eprintln!("{}", e);
    }).ok();
    Command::new("false").check().map_err(|e| {
        // Command failed with status (exit status: 1), stdout (), stderr ()
        eprintln!("{}", e);
    }).ok();
    Ok(())
}

Usually, scripts probably will just use Command::new("cmd").args(["arg1", "arg2"]).check()?.

CommandExtLog

CommandExtLog allows you to add customizable logging to your commands.

use std::process::Command;
use command_ext::{CommandExtCheck, CommandExtLog};
use env_logger::Builder;
use log::{LevelFilter, Level};
fn main() -> anyhow::Result<()> {
    Builder::new().filter_level(LevelFilter::max()).init();
    Command::new("bash")
        .args(["-c", "echo err >&2; echo ok"])
        .log_args(Level::Debug)
        .log_status(Level::Info)
        .log_stdout(Level::Trace)
        .log_stderr(Level::Warn)
        .check()?;
    Ok(())
}

This logs:

[2023-12-13T21:04:17Z DEBUG command_ext::log] args: bash -c echo err >&2; echo ok
[2023-12-13T21:04:17Z INFO  command_ext::log] status: exit status: 0
[2023-12-13T21:04:17Z TRACE command_ext::log] stdout: ok
[2023-12-13T21:04:17Z WARN  command_ext::log] stderr: err

CommandExtTrace

CommandExtTrace works very similarly to CommandExtLog

use command_ext::{CommandExtCheck, CommandExtTrace};
use std::io::stdout;
use std::process::Command;
use tracing::{metadata::LevelFilter, Level};
use tracing_subscriber::{fmt, prelude::*, registry, Layer};
fn main() -> Result<(), Box<dyn std::error::Error>> {
    registry()
        .with(
            fmt::layer()
                .with_writer(stdout)
                .with_filter(LevelFilter::TRACE),
        )
        .try_init()?;
    Command::new("bash")
        .args(["-c", "echo err >&2; echo ok"])
        .trace_args(Level::DEBUG)
        .trace_status(Level::INFO)
        .trace_stdout(Level::TRACE)
        .trace_stderr(Level::WARN)
        .check()?;
    Ok(())
}

This traces:

2023-12-13T21:06:31.739932Z DEBUG command_ext::trace: args: bash -c echo err >&2; echo ok
2023-12-13T21:06:31.741100Z  INFO command_ext::trace: status: exit status: 0
2023-12-13T21:06:31.741138Z TRACE command_ext::trace: stdout: ok
2023-12-13T21:06:31.741147Z  WARN command_ext::trace: stderr: err

CommandWrap

For other cases where you might want to hook into what Command is doing, you can use CommandWrap to implement your own wrappers. For example, let's say you want to wrap the Command type so it prints a message when it executes:

use command_ext::CommandExtWrap;
Commit count: 5

cargo fmt