blue_cli/commands/
setup.rs

1use clap::Args;
2use std::io::{self, BufRead, Write};
3use std::path::PathBuf;
4use std::process::Command;
5use std::{env, fs};
6
7#[derive(Args, Debug)]
8pub struct Setup {}
9
10pub fn run() {
11    println!("Setting up blue...");
12
13    let current_path = env::current_exe().expect("Failed to get current executable path");
14    let binary_name = current_path.file_name().expect("Failed to get binary name");
15
16    // Get the recommended directory based on the current operating system
17    let recommended_dir: PathBuf = match env::consts::OS {
18        "windows" => {
19            let home_dir = match home::home_dir() {
20                Some(path) => path,
21                None => {
22                    eprintln!("Impossible to get your home dir!");
23                    std::process::exit(1);
24                }
25            };
26
27            let target_dir_str = format!("{}\\.blue\\bin", home_dir.to_str().unwrap());
28            let target_dir = PathBuf::from(target_dir_str);
29
30            println!("Target dir 555: {:?}", target_dir.to_str().unwrap());
31
32            // Create the directory if it doesn't exist
33            if !target_dir.exists() {
34                fs::create_dir_all(&target_dir).unwrap_or_else(|_| {
35                    panic!(
36                        "Failed to create directory: {}",
37                        &target_dir.to_str().unwrap()
38                    )
39                });
40            }
41
42            target_dir
43        }
44        "linux" => {
45            let home_dir = match home::home_dir() {
46                Some(path) => path,
47                None => {
48                    eprintln!("Impossible to get your home dir!");
49                    std::process::exit(1);
50                }
51            };
52
53            let target_dir_str = format!("{}/.blue/bin", home_dir.to_str().unwrap());
54            let target_dir = PathBuf::from(&target_dir_str);
55
56            if !target_dir.exists() {
57                fs::create_dir_all(&target_dir).unwrap_or_else(|_| {
58                    panic!(
59                        "Failed to create directory: {}",
60                        &target_dir.to_str().unwrap()
61                    )
62                });
63            }
64
65            target_dir
66        }
67        "macos" => {
68            let target_dir = PathBuf::from("/usr/local/bin/.blue/bin");
69            if !target_dir.exists() {
70                fs::create_dir_all(&target_dir).unwrap_or_else(|_| {
71                    panic!(
72                        "Failed to create directory: {}",
73                        &target_dir.to_str().unwrap()
74                    )
75                });
76            }
77            target_dir
78        }
79        _ => {
80            eprintln!("Unsupported operating system");
81            return;
82        }
83    };
84
85    let new_path = recommended_dir.join(binary_name);
86
87    if let Err(err) = fs::copy(&current_path, &new_path) {
88        eprintln!(
89            "Failed to move the binary to {}: {}",
90            new_path.display(),
91            err
92        );
93        std::process::exit(1);
94    }
95
96    println!("Adding {:?} to PATH", &recommended_dir.to_str().unwrap());
97
98    // Set the new PATH variable for the current process and child processes based on the OS
99    match env::consts::OS {
100        "windows" => {
101            let cmd = &format!(
102                "setx PATH \"{};$Env:PATH\"",
103                &recommended_dir.to_str().unwrap()
104            );
105            println!("Running command: {}", cmd);
106            let result = Command::new("powershell").arg(cmd).status();
107
108            if let Err(err) = result {
109                eprintln!("Failed to set PATH variable: {}", err);
110            } else {
111                // Success message
112                println!("Please restart your terminal to use blue");
113            }
114        }
115        "linux" | "macos" => {
116            let cmd = &format!("export PATH=$PATH:{}", &recommended_dir.to_str().unwrap());
117
118            // add export command to ~/.bashrc
119            let home_dir = match home::home_dir() {
120                Some(path) => path,
121                None => {
122                    eprintln!("Impossible to get your home dir!");
123                    std::process::exit(1);
124                }
125            };
126
127            let required_line = cmd.as_str();
128
129            let bash_file = if env::consts::OS == "linux" {
130                ".bashrc"
131            } else {
132                ".bash_profile"
133            };
134
135            let file_path = format!("{}/{}", home_dir.to_str().unwrap(), bash_file);
136            let file = std::fs::OpenOptions::new()
137                .read(true)
138                .write(true)
139                .create(true)
140                .open(file_path)
141                .expect("Failed to open file");
142
143            let mut found = false;
144            let reader = io::BufReader::new(&file);
145
146            for line in reader.lines().flatten() {
147                if line.contains(required_line) {
148                    found = true;
149                    break;
150                }
151            }
152
153            if !found {
154                let result = writeln!(&file, "{}", &required_line);
155
156                if let Err(err) = result {
157                    eprintln!("Failed to write to file: {}", err);
158                } else {
159                    // Success message
160                    println!("Please restart your terminal to use blue or run the following command: source ~/.bashrc");
161                }
162
163                println!("{} appended to the file!", &required_line);
164            } else {
165                println!("{} already exists in the file.", &required_line);
166            }
167        }
168        _ => {
169            eprintln!("Unsupported operating system");
170            std::process::exit(1);
171        }
172    };
173}