Determine the install source for a binary at `current_exe`. Manifest is consulted first under the trust gate (canonicalized path must match current_exe). Path heuristics provide the fallback.
(current_exe: &Path, env: &dyn EnvLookup)
| 183 | /// Manifest is consulted first under the trust gate (canonicalized path |
| 184 | /// must match current_exe). Path heuristics provide the fallback. |
| 185 | pub fn detect_source(current_exe: &Path, env: &dyn EnvLookup) -> InstallSource { |
| 186 | let canonical_exe = |
| 187 | std::fs::canonicalize(current_exe).unwrap_or_else(|_| current_exe.to_path_buf()); |
| 188 | |
| 189 | // 1. Manifest trust gate. Any parse / schema / mismatch failure falls |
| 190 | // through silently to path heuristics — manifest is best-effort |
| 191 | // metadata, not a source of errors. |
| 192 | let manifest_p = manifest_path(env); |
| 193 | if let Ok(raw) = std::fs::read_to_string(&manifest_p) { |
| 194 | if let Ok(m) = serde_json::from_str::<Manifest>(&raw) { |
| 195 | if m.schema_version == 1 && m.source == "official-installer" { |
| 196 | let recorded = std::fs::canonicalize(&m.install_path).unwrap_or(m.install_path); |
| 197 | if recorded == canonical_exe { |
| 198 | return InstallSource::OfficialInstaller { |
| 199 | manifest_path: manifest_p, |
| 200 | recorded_install_path: recorded, |
| 201 | recorded_version: m.version, |
| 202 | }; |
| 203 | } |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | // 2. Path heuristics. |
| 209 | let path_str = canonical_exe.to_string_lossy(); |
| 210 | |
| 211 | // Homebrew: Apple Silicon (/opt/homebrew), Intel (/usr/local/Cellar), |
| 212 | // and linuxbrew. canonicalize() above already resolved the |
| 213 | // /opt/homebrew/bin/atomic symlink into the Cellar path on macOS. |
| 214 | let homebrew_markers = [ |
| 215 | "/Cellar/", |
| 216 | "/opt/homebrew/", |
| 217 | "/home/linuxbrew/.linuxbrew/", |
| 218 | "/usr/local/Homebrew/", |
| 219 | ]; |
| 220 | for marker in homebrew_markers { |
| 221 | if let Some(idx) = path_str.find(marker) { |
| 222 | let prefix = if marker == "/Cellar/" { |
| 223 | PathBuf::from(&path_str[..idx]) |
| 224 | } else { |
| 225 | PathBuf::from(marker.trim_end_matches('/')) |
| 226 | }; |
| 227 | return InstallSource::Homebrew { prefix }; |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | // Cargo: $CARGO_HOME/bin or ~/.cargo/bin. |
| 232 | if let Some(cargo_home) = env.var("CARGO_HOME") { |
| 233 | if path_str.starts_with(&format!("{}/bin/", cargo_home)) { |
| 234 | return InstallSource::Cargo; |
| 235 | } |
| 236 | } |
| 237 | if let Some(home) = env.var("HOME") { |
| 238 | if path_str.starts_with(&format!("{}/.cargo/bin/", home)) { |
| 239 | return InstallSource::Cargo; |
| 240 | } |
| 241 | } |
| 242 |