Skip to main content

Run

Struct Run 

Source
pub struct Run { /* private fields */ }
Expand description

The run of a command that the caller observes while it runs

The handle starts with the command and ends with the result of the run. It gives the output of the command to the caller as lines, in the order in which the lines arrive, and it collects the same capture that a run in one call collects. A caller that reads no line at all therefore still gets every byte that the command wrote.

The handle owns the command. A caller that drops the handle ends the command with it, so a timeout, a select, and a scheduler that abandons a run leave no process behind. The kill that ends such a command is immediate, and a caller that wants the command to end in good order calls stop instead. A caller that waits for the end of the command in a select keeps the handle with wait_for_end.

§Examples

use kawauso_process::Invocation;

let mut run = Invocation::new("cargo").arg("build").start()?;

while let Some(line) = run.next_line().await? {
    println!("[{}] {line}", line.stream());
}

let execution = run.wait().await?.require_success()?;

println!("{}", execution.duration().as_secs());

Implementations§

Source§

impl Run

Source

pub fn id(&self) -> Option<ProcessId>

Returns the identifier that the operating system gave the command

An application that reports which program it started, or that gives the command to a tool of the platform, reads the identifier here. The handle records the value when the command starts, so the value is there for the whole life of the handle. A wait for the end of the command does not remove the value.

The operating system takes the identifier of a command that ended, and it can give the same identifier to another command. A caller that waited for the end therefore reads the identifier of the command that ran, and not the identifier of a command that runs.

The value is None when the operating system gave the command no identifier.

Source

pub fn invocation(&self) -> &Invocation

Returns the command that runs

Source

pub async fn next_line(&mut self) -> Result<Option<Line>, RunCommandError>

Returns the next line of the output of the command

The method waits until the command writes a line to one of its streams, and it returns the lines in the order in which they arrive. It returns None when the command closed both of its streams, which a command does when it ends. A command that writes a last line without the characters that end a line still reports that line.

Every line that the method returns stays in the capture of the result as well, so a caller that shows the output while the command runs and then reports the whole output reads both from the same run.

§Errors

Returns IncompleteRun when a stream of the command cannot be read.

§Cancel safety

The method is cancel safe. A caller often waits for a line and for another event, such as a timeout or another branch of a select. The caller drops the future of the call when the other event occurs first, and the call loses no output. The bytes that the call took stay with the handle, and the call that follows reports the line that they belong to.

§Examples
use kawauso_process::Invocation;

let mut run = Invocation::new("cargo").arg("test").start()?;

while let Some(line) = run.next_line().await? {
    println!("{line}");
}
Source

pub async fn stop(self, grace: Duration) -> Result<Execution, RunCommandError>

Ends the command and reports the result of the run

The method asks the command to end, and it gives the command the time that the caller names. It kills a command that is still there when the time is over. A program that answers the request removes its lock file, writes what it has, and ends, which a kill gives it no time to do.

The request is SIGTERM on a Unix platform. A platform that has no request of this kind kills the command at once, and the time then passes unused. The request reaches the program that the crate started, and not a group of processes, so a program that starts programs of its own decides what happens to them.

The time measures the command, and not the streams of the command. A program that starts programs of its own gives them its streams. Such a program can end while a program that it started holds the streams open.

The method reads both streams while it waits, so a command that fills a pipe ends as well. It takes what the streams hold when the command ends. On a Unix platform, a program that holds a stream open therefore does not hold the call. On a platform that has no read of this kind, the call waits for the end of both streams.

The method reports what wait reports: the exit status, the capture of both streams, and the time that the run took.

A caller that drops the handle instead of this call kills the command at once, with no request before it.

§Errors

Returns IncompleteRun when a stream of the command cannot be read, or when the end of the command cannot be waited for.

§Panics

Panics when the Tokio runtime that drives the future has no timer. The method waits for the time that the caller names, and the timer of the runtime measures it.

§Examples
use std::time::Duration;

use kawauso_process::Invocation;

let run = Invocation::new("cargo").arg("build").start()?;

let execution = run.stop(Duration::from_secs(5)).await?;

println!("{}", execution.status());
Source

pub async fn wait(self) -> Result<Execution, RunCommandError>

Waits for the end of the command and reports the result of the run

The method reads what the command still writes, waits for the end of the command, and reports what a run in one call reports: the exit status, the capture of both streams, and the time that the run took. The capture holds everything that the command wrote, whether or not the caller read a line.

A command that ends without success is no failure of this method. The status travels in the result, and require_success turns a status that is not a success into an error.

§Errors

Returns IncompleteRun when a stream of the command cannot be read, or when the end of the command cannot be waited for.

§Cancel safety

The method is not cancel safe. It takes the handle, so a caller that drops the future of a call ends the command. The caller loses the result of the run, and the capture of both streams with it. A caller that waits for the end of the command, and for an event of its own, calls wait_for_end. That method leaves the handle.

§Examples
use kawauso_process::Invocation;

let run = Invocation::new("cargo").arg("build").start()?;

let execution = run.wait().await?;

println!("{}", execution.status());
Source

pub async fn wait_for_end(&mut self) -> Result<(), RunCommandError>

Waits for the end of the command and leaves the handle with the caller

A caller often waits for the end of a command and for an event of its own, such as a token that cancels the work. wait takes the handle, and this caller needs it. The caller holds nothing when the event comes first, and stop needs the handle. This method reports the end of the command, and it leaves the handle. The caller then asks for the result, or it stops a command that still runs.

The method reports no result of its own. The handle keeps everything that a result needs, so wait reports the result after this call. The wait that follows returns at once, because the command ended.

The method reads both streams while it waits, so a command that fills a pipe ends as well. It waits for the command and not for the output of the command. A command that closed both of its streams can still run, and this method reports that end.

§Errors

Returns IncompleteRun when a stream of the command cannot be read, or when the end of the command cannot be waited for.

§Cancel safety

The method is cancel safe. The caller drops the future of the call when the other event occurs first, and the command continues. The handle keeps the output that the call read, and the caller stops the command, takes the result, or waits again.

§Examples
use std::time::Duration;

use kawauso_process::Invocation;

let mut run = Invocation::new("cargo").arg("build").start()?;

let execution = tokio::select! {
    ended = run.wait_for_end() => {
        ended?;
        run.wait().await?
    }
    () = cancelled() => run.stop(Duration::from_secs(5)).await?,
};

println!("{}", execution.status());

Trait Implementations§

Source§

impl Debug for Run

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Run

§

impl !UnwindSafe for Run

§

impl Freeze for Run

§

impl Send for Run

§

impl Sync for Run

§

impl Unpin for Run

§

impl UnsafeUnpin for Run

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.