1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::{
fs::canonicalize,
io::{BufRead, BufReader},
path::PathBuf,
process::{Child, Stdio},
sync::{mpsc::sync_channel, Arc},
};
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 fn connect(
&self,
config: &Config,
cli_path: &PathBuf,
) -> eyre::Result<(ConnectParams, Child)> {
self.inner.connect(config, cli_path)
}
}
#[derive(Debug)]
struct InnerCliSession {}
impl InnerCliSession {
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)?;
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()?;
return Ok(proc);
}
fn get_conn(
&self,
mut proc: std::process::Child,
) -> eyre::Result<(ConnectParams, std::process::Child)> {
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, receiver) = sync_channel(1);
std::thread::spawn(move || {
let stdout_bufr = BufReader::new(stdout);
for line in stdout_bufr.lines() {
let out = line.as_ref().unwrap();
if let Ok(conn) = serde_json::from_str::<ConnectParams>(&out) {
sender.send(conn).unwrap();
}
if let Ok(line) = line {
println!("dagger: {}", line);
}
}
});
std::thread::spawn(|| {
let stderr_bufr = BufReader::new(stderr);
for line in stderr_bufr.lines() {
if let Ok(line) = line {
println!("dagger: {}", line);
}
}
});
let conn = receiver.recv()?;
Ok((conn, proc))
}
}