2023-01-28 16:19:57 +01:00
|
|
|
|
2023-01-27 21:57:39 +01:00
|
|
|
use std::{
|
|
|
|
fs::canonicalize,
|
|
|
|
io::{BufRead, BufReader},
|
|
|
|
path::PathBuf,
|
2023-01-28 13:33:30 +01:00
|
|
|
process::{Child, Stdio},
|
|
|
|
sync::{mpsc::sync_channel, Arc},
|
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 {}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-28 13:33:30 +01:00
|
|
|
pub fn connect(
|
|
|
|
&self,
|
|
|
|
config: &Config,
|
|
|
|
cli_path: &PathBuf,
|
|
|
|
) -> eyre::Result<(ConnectParams, Child)> {
|
2023-01-27 21:57:39 +01:00
|
|
|
self.inner.connect(config, cli_path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct InnerCliSession {}
|
|
|
|
|
|
|
|
impl InnerCliSession {
|
2023-01-28 13:33:30 +01:00
|
|
|
pub fn connect(
|
|
|
|
&self,
|
|
|
|
config: &Config,
|
|
|
|
cli_path: &PathBuf,
|
|
|
|
) -> eyre::Result<(ConnectParams, Child)> {
|
|
|
|
let proc = self.start(config, cli_path)?;
|
|
|
|
let params = self.get_conn(proc)?;
|
2023-01-27 21:57:39 +01:00
|
|
|
Ok(params)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn start(&self, config: &Config, cli_path: &PathBuf) -> eyre::Result<std::process::Child> {
|
|
|
|
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()])
|
|
|
|
}
|
|
|
|
|
|
|
|
let proc = std::process::Command::new(
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-01-28 13:33:30 +01:00
|
|
|
fn get_conn(
|
|
|
|
&self,
|
|
|
|
mut proc: std::process::Child,
|
|
|
|
) -> eyre::Result<(ConnectParams, std::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"))?;
|
|
|
|
|
2023-01-28 13:33:30 +01:00
|
|
|
let (sender, receiver) = sync_channel(1);
|
2023-01-27 21:57:39 +01:00
|
|
|
|
2023-01-28 13:33:30 +01:00
|
|
|
std::thread::spawn(move || {
|
|
|
|
let stdout_bufr = BufReader::new(stdout);
|
|
|
|
for line in stdout_bufr.lines() {
|
|
|
|
let out = line.unwrap();
|
|
|
|
if let Ok(conn) = serde_json::from_str::<ConnectParams>(&out) {
|
|
|
|
sender.send(conn).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2023-01-27 21:57:39 +01:00
|
|
|
|
2023-01-28 13:33:30 +01:00
|
|
|
std::thread::spawn(|| {
|
|
|
|
let stderr_bufr = BufReader::new(stderr);
|
|
|
|
for line in stderr_bufr.lines() {
|
|
|
|
let out = line.unwrap();
|
|
|
|
panic!("could not start dagger session: {}", out)
|
|
|
|
}
|
2023-01-27 21:57:39 +01:00
|
|
|
});
|
|
|
|
|
2023-01-28 13:33:30 +01:00
|
|
|
let conn = receiver.recv()?;
|
|
|
|
|
|
|
|
Ok((conn, proc))
|
2023-01-27 21:57:39 +01:00
|
|
|
}
|
|
|
|
}
|