Skip to content

Commit

Permalink
feat(Binaries): Add BinaryInstallation::interact for interacting wi…
Browse files Browse the repository at this point in the history
…th long running processes
  • Loading branch information
nokome committed Dec 5, 2021
1 parent 55b1500 commit 19996fe
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
3 changes: 1 addition & 2 deletions rust/binaries/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.72"
structopt = { version = "0.3.25", optional = true }
tar = "0.4.37"
tokio = "1.13.0"
tokio = { version = "1.13.0", features = ["process", "macros"] }
tracing = "0.1.29"
url = "2.2.2"
which = "4.2.2"
Expand All @@ -34,4 +34,3 @@ zip = "0.5.13"

[dev-dependencies]
test-utils = { path = "../test-utils", version = "0.0.0" }
tokio = { version = "1.13.0", features = ["macros"] }
39 changes: 30 additions & 9 deletions rust/binaries/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ use std::{
},
fs, io,
path::{Path, PathBuf},
process::{Command, Output},
process::{Output, Stdio},
str::FromStr,
};
use tokio::sync::Mutex;
use tokio::{
process::{Child, Command},
sync::Mutex,
};

mod binaries;

Expand Down Expand Up @@ -72,8 +75,22 @@ impl BinaryInstallation {
/// Run the binary
///
/// Returns the output of the command
pub fn run(&self, args: &[String]) -> Result<Output> {
Ok(self.command().args(args).output()?)
pub async fn run(&self, args: &[String]) -> Result<Output> {
let output = self.command().args(args).output().await?;
Ok(output)
}

/// Run the binary and connect to stdin, stdout and stderr streams
///
/// Returns a `Child` process whose
pub fn interact(&self, args: &[String]) -> Result<Child> {
Ok(self
.command()
.args(args)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?)
}
}

Expand All @@ -95,11 +112,13 @@ struct Binary {
/// requirements.
installable: Vec<String>,

/// The arguments used to
/// The arguments used to get the version of the binary
#[serde(skip)]
#[def = r#"vec!["--version".to_string()]"#]
version_args: Vec<String>,

/// The regex used to get the version from the output of
/// the binary.
#[serde(skip)]
#[def = r#"Regex::new("\\d+.\\d+(.\\d+)?").unwrap()"#]
version_regex: Regex,
Expand Down Expand Up @@ -156,7 +175,9 @@ impl Binary {
/// Parses the output of the command and adds a `0` patch semver part if
/// necessary.
pub fn version(&self, path: &Path) -> Option<String> {
let output = Command::new(path).args(&self.version_args).output();
let output = std::process::Command::new(path)
.args(&self.version_args)
.output();
if let Ok(output) = output {
let stdout = std::str::from_utf8(&output.stdout).unwrap_or("");
if let Some(version) = self.version_regex.captures(stdout).map(|captures| {
Expand Down Expand Up @@ -212,7 +233,7 @@ impl Binary {
};

// Search for executables with name or one of aliases
tracing::debug!("Searching for executables in {:?}", dirs);
// tracing::debug!("Searching for executables in {:?}", dirs);
let names = [vec![self.name.clone()], self.aliases.clone()].concat();
let paths = names
.iter()
Expand All @@ -232,7 +253,7 @@ impl Binary {
.flatten();

// Get version of each executable found
tracing::debug!("Getting versions for paths {:?}", paths);
// tracing::debug!("Getting versions for paths {:?}", paths);
let mut installs: Vec<BinaryInstallation> = paths
.map(|path| {
BinaryInstallation::new(self.name.clone(), path.clone(), self.version(&path))
Expand Down Expand Up @@ -914,7 +935,7 @@ pub mod commands {
&self.semver.clone().unwrap_or_else(|| "*".to_string()),
)
.await?;
let output = installation.run(&self.args)?;
let output = installation.run(&self.args).await?;

use std::io::Write;
std::io::stdout().write_all(output.stdout.as_ref())?;
Expand Down

0 comments on commit 19996fe

Please sign in to comment.