1use std::{collections::HashMap, process::ExitStatus};
2
3use color_eyre::{
4 eyre::{eyre, Context},
5 Result,
6};
7
8use crate::persistence;
9
10pub fn add(name: &str, path: &str) -> Result<()> {
15 let mut entries = persistence::read_config()?;
16
17 entries.insert(name.to_owned(), path.to_owned());
18
19 persistence::write_config(&entries)?;
20
21 Ok(())
22}
23
24pub fn remove(name: &str) -> Result<String> {
29 let mut entries = persistence::read_config()?;
30
31 check_entry(&entries, name)?;
32
33 let removed = entries.remove(name).expect("key to be present");
34
35 persistence::write_config(&entries)?;
36
37 Ok(removed)
38}
39
40pub fn list() -> Result<()> {
44 let entries = persistence::read_config()?;
45
46 if entries.is_empty() {
47 println!("no entries available");
48 } else {
49 for (name, path) in entries {
50 println!("{name}: \t\t{path}");
51 }
52 }
53
54 Ok(())
55}
56
57pub fn run(name: &str, command: &Vec<String>) -> Result<ExitStatus> {
62 let entries = persistence::read_config()?;
63
64 let entry = check_entry(&entries, name)?;
65
66 let cmd = &command[0];
67 let args = &command[1..];
68
69 let mut process = std::process::Command::new(cmd)
70 .env("JAVA_HOME", entry)
71 .env("PATH", build_path(entry)?)
72 .args(args)
73 .spawn()
74 .expect("to be able to spawn process");
75
76 Ok(process.wait()?)
77}
78
79fn check_entry<'a>(entries: &'a HashMap<String, String>, name: &str) -> Result<&'a str> {
83 if !entries.contains_key(name) {
84 Err(eyre!(Error::NoSuchEntry))
85 } else {
86 Ok(entries.get(name).expect("key to be present"))
87 }
88}
89
90fn build_path(home: &str) -> Result<String> {
91 let formatted = format_bin_path(home);
92 if let Some(path) = std::env::var_os("PATH") {
93 let mut paths = std::env::split_paths(&path).collect::<Vec<_>>();
94 paths.insert(0, formatted.into());
95
96 let joined = std::env::join_paths(paths)
97 .context("failed to read PATH variable")?
98 .into_string()
99 .map_err(|_| Error::Encoding)?;
100
101 Ok(joined)
102 } else {
103 Ok(formatted)
104 }
105}
106
107fn format_bin_path(home: &str) -> String {
108 format!("{home}/bin")
109}
110
111#[derive(Debug, thiserror::Error)]
112pub enum Error {
113 #[error("no such entry exists")]
114 NoSuchEntry,
115
116 #[error("encoding error on PATH variable")]
117 Encoding,
118}