1use std::{
2 process::{Command, ExitStatus, Stdio},
3 sync::mpsc::Sender,
4};
5
6use crate::{exec, nix::Nix, Extension};
7use anyhow::Error;
8use fluentci_types::Output;
9
10#[derive(Default)]
11pub struct Devbox {}
12
13impl Devbox {
14 pub fn install(&self, pkgs: Vec<&str>) -> Result<ExitStatus, Error> {
15 self.setup()?;
16 let mut child = Command::new("sh")
17 .arg("-c")
18 .arg(format!("devbox global add {}", pkgs.join(" ")))
19 .stdin(Stdio::inherit())
20 .stdout(Stdio::inherit())
21 .stderr(Stdio::inherit())
22 .spawn()?;
23 child.wait().map_err(Error::from)
24 }
25}
26
27impl Extension for Devbox {
28 fn exec(
29 &mut self,
30 cmd: &str,
31 tx: Sender<String>,
32 out: Output,
33 last_cmd: bool,
34 work_dir: &str,
35 ) -> Result<ExitStatus, Error> {
36 self.setup()?;
37
38 if cmd.is_empty() {
39 return Ok(ExitStatus::default());
40 }
41
42 Command::new("bash")
43 .arg("-c")
44 .arg("[ -f devbox.json ] || devbox init")
45 .current_dir(work_dir)
46 .stdout(Stdio::inherit())
47 .stderr(Stdio::inherit())
48 .spawn()?
49 .wait()?;
50
51 let cmd = format!("devbox run {}", cmd);
52 exec(&cmd, tx, out, last_cmd, work_dir)
53 }
54
55 fn setup(&self) -> Result<(), Error> {
56 Nix::default().setup()?;
57 let mut child = Command::new("sh")
58 .arg("-c")
59 .arg("type devbox > /dev/null || curl -fsSL https://get.jetpack.io/devbox | bash")
60 .env("FORCE", "1")
61 .spawn()?;
62 child.wait()?;
63 Ok(())
64 }
65
66 fn format_command(&self, cmd: &str) -> String {
67 format!("[ -f devbox.json ] || devbox init ; devbox run {}", cmd)
68 }
69}