1use crate::config;
2use colored::*;
3use std::error::Error;
4use std::process;
5
6const BASE_CMD: &str = "asdf";
7const VERSION_LATEST: &str = "latest";
8
9pub fn add_plugin(name: &str) -> Result<(), Box<dyn Error>> {
10 let desc = format!("Adding asdf plugin");
11 let error = format!("Plugin {} could not be installed.", name).red();
12 run_cmd(&["plugin add", name], &desc, &error)?;
13 eprintln!("---");
14
15 Ok(())
16}
17
18pub fn install_package(package: &config::Package) -> Result<(), Box<dyn Error>> {
19 for version in &package.versions {
20 let name = &package.name;
21 install_version(name, version)?;
22 set_global(name, version)?;
23 reshim(name)?;
24 }
25
26 Ok(())
27}
28
29fn install_version(name: &String, version: &String) -> Result<(), Box<dyn Error>> {
30 let desc = format!("Installing {} ({})", name, version);
31 let error = format!("{} v{} could not be installed", name, version).red();
32 run_cmd(&["install", &name, &version], &desc, &error)?;
33
34 Ok(())
35}
36
37fn set_global(name: &String, version: &String) -> Result<(), Box<dyn Error>> {
38 let mut final_version = &version.clone();
39 let available_versions = run_cmd_silent(&["list", name])?;
40 let last_version = available_versions.last().unwrap();
41
42 if final_version == VERSION_LATEST {
43 final_version = last_version;
44 }
45
46 let desc = format!("Setting global {} version to {}", name, final_version);
47 let error = format!("Failed to use global {} v{}", name, final_version);
48 run_cmd(&["global", &name, &final_version], &desc, &error)?;
49
50 Ok(())
51}
52
53fn reshim(name: &String) -> Result<(), Box<dyn Error>> {
54 let error = format!("Failed to reshim {}", name);
55 run_cmd(&["reshim", &name], "", &error)?;
56
57 Ok(())
58}
59
60fn run_cmd(args: &[&str], desc: &str, error: &str) -> Result<(), Box<dyn Error>> {
61 eprintln!("{}", desc);
62
63 let output = process::Command::new(BASE_CMD)
64 .args(args)
65 .output()
66 .expect(error);
67
68 if !output.stdout.is_empty() {
69 eprintln!("{}", String::from_utf8(output.stdout).unwrap().green());
70 }
71
72 if !output.stderr.is_empty() {
73 eprintln!("{}", String::from_utf8(output.stderr).unwrap().yellow());
74 }
75
76 Ok(())
77}
78
79fn run_cmd_silent(args: &[&str]) -> Result<Vec<String>, Box<dyn Error>> {
80 let output = process::Command::new(BASE_CMD).args(args).output().unwrap();
81
82 if !output.stdout.is_empty() {
83 return Ok(String::from_utf8(output.stdout)
84 .unwrap()
85 .split("\n")
86 .map(|s| s.trim().to_string())
87 .filter(|s| !s.is_empty() || s.starts_with("--"))
88 .collect::<Vec<_>>());
89 }
90
91 if !output.stderr.is_empty() {
92 return Ok(vec![String::from_utf8(output.stderr).unwrap()]);
93 }
94
95 Ok(vec![])
96}