superviseur_code/
lib.rs

1use anyhow::Error;
2use std::{io::BufRead, process::Command, thread};
3use tokio::sync::mpsc::UnboundedSender;
4
5pub fn start_code_tunnel(sender: UnboundedSender<String>, dir: &str) -> Result<u32, Error> {
6    verify_if_code_is_installed()?;
7
8    let mut child = Command::new("code")
9        .arg("tunnel")
10        .arg("--accept-server-license-terms")
11        .current_dir(dir)
12        .stdout(std::process::Stdio::piped())
13        .stderr(std::process::Stdio::piped())
14        .spawn()
15        .expect("failed to execute process");
16
17    let pid = child.id();
18
19    thread::spawn(move || {
20        let stdout = child.stdout.take().expect("Failed to get stdout handle");
21        let stderr = child.stderr.take().expect("Failed to get stderr handle");
22        let stdout_reader = std::io::BufReader::new(stdout);
23        let stderr_reader = std::io::BufReader::new(stderr);
24
25        for line in stdout_reader.lines() {
26            if let Ok(line) = line {
27                sender.send(line).unwrap();
28            }
29        }
30
31        for line in stderr_reader.lines() {
32            if let Ok(line) = line {
33                sender.send(line).unwrap();
34            }
35        }
36
37        drop(sender);
38
39        child.wait().expect("Failed to wait on child");
40    });
41
42    Ok(pid)
43}
44
45fn verify_if_code_is_installed() -> Result<(), Error> {
46    let output = Command::new("code")
47        .arg("--version")
48        .output()
49        .expect("failed to execute process");
50
51    if !output.status.success() {
52        return Err(Error::msg("Code is not installed"));
53    }
54
55    Ok(())
56}