dagger-rs/crates/dagger-core/src/cli_session.rs

113 lines
3.2 KiB
Rust
Raw Normal View History

2023-01-27 21:57:39 +01:00
use std::{
fs::canonicalize,
path::PathBuf,
process::Stdio,
sync::Arc,
2023-01-27 21:57:39 +01:00
};
2023-02-20 11:42:03 +01:00
use tokio::io::AsyncBufReadExt;
2023-01-27 21:57:39 +01:00
use crate::{config::Config, connect_params::ConnectParams};
#[derive(Clone, Debug)]
pub struct CliSession {
inner: Arc<InnerCliSession>,
}
impl CliSession {
pub fn new() -> Self {
Self {
inner: Arc::new(InnerCliSession {}),
}
}
pub async fn connect(
2023-01-28 13:33:30 +01:00
&self,
config: &Config,
cli_path: &PathBuf,
2023-02-20 11:42:03 +01:00
) -> eyre::Result<(ConnectParams, tokio::process::Child)> {
self.inner.connect(config, cli_path).await
2023-01-27 21:57:39 +01:00
}
}
#[derive(Debug)]
struct InnerCliSession {}
impl InnerCliSession {
pub async fn connect(
2023-01-28 13:33:30 +01:00
&self,
config: &Config,
cli_path: &PathBuf,
2023-02-20 11:42:03 +01:00
) -> eyre::Result<(ConnectParams, tokio::process::Child)> {
2023-01-28 13:33:30 +01:00
let proc = self.start(config, cli_path)?;
let params = self.get_conn(proc).await?;
2023-01-27 21:57:39 +01:00
Ok(params)
}
2023-02-20 11:42:03 +01:00
fn start(&self, config: &Config, cli_path: &PathBuf) -> eyre::Result<tokio::process::Child> {
2023-01-27 21:57:39 +01:00
let mut args: Vec<String> = vec!["session".into()];
if let Some(workspace) = &config.workdir_path {
let abs_path = canonicalize(workspace)?;
args.extend(["--workdir".into(), abs_path.to_string_lossy().to_string()])
}
if let Some(config_path) = &config.config_path {
let abs_path = canonicalize(config_path)?;
args.extend(["--project".into(), abs_path.to_string_lossy().to_string()])
}
2023-02-20 11:42:03 +01:00
let proc = tokio::process::Command::new(
2023-01-27 21:57:39 +01:00
cli_path
.to_str()
.ok_or(eyre::anyhow!("could not get string from path"))?,
)
.args(args.as_slice())
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
//TODO: Add retry mechanism
return Ok(proc);
}
async fn get_conn(
2023-01-28 13:33:30 +01:00
&self,
2023-02-20 11:42:03 +01:00
mut proc: tokio::process::Child,
) -> eyre::Result<(ConnectParams, tokio::process::Child)> {
2023-01-27 21:57:39 +01:00
let stdout = proc
.stdout
.take()
.ok_or(eyre::anyhow!("could not acquire stdout from child process"))?;
let stderr = proc
.stderr
.take()
.ok_or(eyre::anyhow!("could not acquire stderr from child process"))?;
let (sender, mut receiver) = tokio::sync::mpsc::channel(1);
2023-01-27 21:57:39 +01:00
tokio::spawn(async move {
let mut stdout_bufr = tokio::io::BufReader::new(stdout).lines();
while let Ok(Some(line)) = stdout_bufr.next_line().await {
if let Ok(conn) = serde_json::from_str::<ConnectParams>(&line) {
sender.send(conn).await.unwrap();
2023-01-28 13:33:30 +01:00
}
println!("dagger: {}", line);
2023-01-28 13:33:30 +01:00
}
});
2023-01-27 21:57:39 +01:00
tokio::spawn(async move {
let mut stdout_bufr = tokio::io::BufReader::new(stderr).lines();
while let Ok(Some(line)) = stdout_bufr.next_line().await {
println!("dagger: {}", line);
2023-01-28 13:33:30 +01:00
}
2023-01-27 21:57:39 +01:00
});
let conn = receiver.recv().await.ok_or(eyre::anyhow!("could not receive ok signal from dagger-engine"))?;
2023-01-28 13:33:30 +01:00
Ok((conn, proc))
2023-01-27 21:57:39 +01:00
}
}