Skip to main content

intelli_shell/utils/
installation.rs

1use std::{env, path::Path};
2
3#[derive(Debug, PartialEq, Eq)]
4pub enum InstallationMethod {
5    /// Installed via the installer script
6    Installer,
7    /// Installed via `cargo install`
8    Cargo,
9    /// Installed via Nix
10    Nix,
11    /// Installed via Homebrew
12    Homebrew,
13    /// Likely compiled directly from a source checkout
14    Source,
15    /// Could not determine the installation method
16    Unknown(Option<String>),
17}
18
19/// Detects how `intelli-shell` was installed by inspecting the executable's path
20pub fn detect_installation_method(data_dir: impl AsRef<Path>) -> InstallationMethod {
21    let current_exe = match env::current_exe() {
22        Ok(path) => path,
23        Err(_) => return InstallationMethod::Unknown(None),
24    };
25    detect_installation_method_inner(&current_exe, data_dir.as_ref())
26}
27
28fn detect_installation_method_inner(current_exe: &Path, data_dir: &Path) -> InstallationMethod {
29    // Check if the executable is located within the official data directory's `bin` subfolder.
30    // This is the strongest indicator of an installation via the script.
31    let installer_bin_path = data_dir.join("bin");
32    if current_exe.starts_with(installer_bin_path) {
33        return InstallationMethod::Installer;
34    }
35
36    // Fallback to checking for common package manager and development paths
37    let path_str = current_exe.to_string_lossy();
38    if path_str.starts_with("/nix/store/") {
39        // Nix/NixOS path (Linux, macOS)
40        InstallationMethod::Nix
41    } else if path_str.contains(".cargo/bin") {
42        // Cargo path (Linux, macOS, Windows)
43        InstallationMethod::Cargo
44    } else if path_str.contains("target/debug") || path_str.contains("target/release") {
45        // Running from a local build directory
46        InstallationMethod::Source
47    } else if path_str.starts_with("/opt/homebrew/")
48        || path_str.starts_with("/home/linuxbrew/.linuxbrew/")
49        || path_str.contains("/Cellar/")
50        || path_str.contains("/homebrew/")
51    {
52        // Homebrew installation path
53        InstallationMethod::Homebrew
54    } else {
55        InstallationMethod::Unknown(Some(path_str.to_string()))
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_detect_installation_method() {
65        let data_dir = Path::new("/home/user/.config/intelli-shell");
66
67        // Test installer path
68        assert_eq!(
69            detect_installation_method_inner(
70                Path::new("/home/user/.config/intelli-shell/bin/intelli-shell"),
71                data_dir
72            ),
73            InstallationMethod::Installer
74        );
75
76        // Test Nix path
77        assert_eq!(
78            detect_installation_method_inner(
79                Path::new("/nix/store/abc-intelli-shell/bin/intelli-shell"),
80                data_dir
81            ),
82            InstallationMethod::Nix
83        );
84
85        // Test Cargo path
86        assert_eq!(
87            detect_installation_method_inner(
88                Path::new("/home/user/.cargo/bin/intelli-shell"),
89                data_dir
90            ),
91            InstallationMethod::Cargo
92        );
93
94        // Test Source path
95        assert_eq!(
96            detect_installation_method_inner(
97                Path::new("/home/user/projects/intelli-shell/target/release/intelli-shell"),
98                data_dir
99            ),
100            InstallationMethod::Source
101        );
102
103        // Test Homebrew path (Apple Silicon)
104        assert_eq!(
105            detect_installation_method_inner(
106                Path::new("/opt/homebrew/bin/intelli-shell"),
107                data_dir
108            ),
109            InstallationMethod::Homebrew
110        );
111
112        // Test Homebrew path (Intel Mac / Cellar)
113        assert_eq!(
114            detect_installation_method_inner(
115                Path::new("/usr/local/Cellar/intelli-shell/3.4.3/bin/intelli-shell"),
116                data_dir
117            ),
118            InstallationMethod::Homebrew
119        );
120
121        // Test Linuxbrew path
122        assert_eq!(
123            detect_installation_method_inner(
124                Path::new("/home/linuxbrew/.linuxbrew/bin/intelli-shell"),
125                data_dir
126            ),
127            InstallationMethod::Homebrew
128        );
129
130        // Test Unknown path
131        assert_eq!(
132            detect_installation_method_inner(
133                Path::new("/usr/local/bin/intelli-shell"),
134                data_dir
135            ),
136            InstallationMethod::Unknown(Some("/usr/local/bin/intelli-shell".to_string()))
137        );
138    }
139}