asdfg/
asdf.rs

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}