1use std::{
2 env,
3 process::{Command, Stdio},
4};
5
6use anyhow::Error;
7use envhub_types::configuration::Configuration;
8
9use crate::Extension;
10
11pub struct Rustup {}
12
13impl Rustup {
14 pub fn new() -> Self {
15 Self {}
16 }
17
18 pub fn set_default_toolchain(&self, toolchain: &str) -> Result<(), Error> {
19 let mut child = Command::new("sh")
20 .arg("-c")
21 .arg(format!(
22 "rustup toolchain install {} && rustup default {}",
23 toolchain, toolchain
24 ))
25 .stdin(Stdio::inherit())
26 .stdout(Stdio::inherit())
27 .stderr(Stdio::inherit())
28 .spawn()?;
29 child.wait()?;
30 Ok(())
31 }
32
33 pub fn install_toolchains(&self, toolchains: Vec<String>) -> Result<(), Error> {
34 for toolchain in toolchains {
35 let mut child = Command::new("sh")
36 .arg("-c")
37 .arg(format!("rustup toolchain install {}", toolchain))
38 .stdin(Stdio::inherit())
39 .stdout(Stdio::inherit())
40 .stderr(Stdio::inherit())
41 .spawn()?;
42 child.wait()?;
43 }
44 Ok(())
45 }
46
47 pub fn install_components(&self, components: Vec<String>) -> Result<(), Error> {
48 for component in components {
49 let mut child = Command::new("sh")
50 .arg("-c")
51 .arg(format!("rustup component add {}", component))
52 .stdin(Stdio::inherit())
53 .stdout(Stdio::inherit())
54 .stderr(Stdio::inherit())
55 .spawn()?;
56 child.wait()?;
57 }
58 Ok(())
59 }
60
61 pub fn add_targets(&self, targets: Vec<String>) -> Result<(), Error> {
62 for target in targets {
63 let mut child = Command::new("sh")
64 .arg("-c")
65 .arg(format!("rustup target add {}", target))
66 .stdin(Stdio::inherit())
67 .stdout(Stdio::inherit())
68 .stderr(Stdio::inherit())
69 .spawn()?;
70 child.wait()?;
71 }
72 Ok(())
73 }
74}
75
76impl Extension for Rustup {
77 fn load(&self, config: &Configuration) -> Result<(), Error> {
78 self.setup()?;
79 match config.rustup {
80 Some(ref rustup) => {
81 if let Some(value) = &rustup.default {
82 self.set_default_toolchain(value)?;
83 }
84 if let Some(value) = &rustup.toolchains {
85 self.install_toolchains(value.clone())?;
86 }
87 if let Some(value) = &rustup.components {
88 self.install_components(value.clone())?;
89 }
90 if let Some(value) = &rustup.targets {
91 self.add_targets(value.clone())?;
92 }
93 }
94 None => {}
95 }
96 Ok(())
97 }
98
99 fn setup(&self) -> Result<(), Error> {
100 env::set_var(
101 "PATH",
102 format!("{}/.cargo/bin:{}", env::var("HOME")?, env::var("PATH")?),
103 );
104 let mut child = Command::new("sh")
105 .arg("-c")
106 .arg("type rustup > /dev/null || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh")
107 .stdin(Stdio::inherit())
108 .stdout(Stdio::inherit())
109 .stderr(Stdio::inherit())
110 .spawn()?;
111 child.wait()?;
112
113 Ok(())
114 }
115}