Skip to content

Commit 250708b

Browse files
committed
fix(upgrade): refuse to upgrade Homebrew-managed binary
Detects /Cellar/ or /homebrew/ in current_exe() path and aborts with a message directing user to 'brew upgrade icm'. Prevents breaking the Cellar structure and Homebrew metadata. Also warns for /usr/bin and /opt/ (non-brew) paths which may be managed by apt/dnf/rpm.
1 parent 67e7d05 commit 250708b

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

crates/icm-cli/src/upgrade.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,26 @@ pub fn cmd_upgrade(apply: bool, check_only: bool) -> Result<()> {
137137
return Ok(());
138138
}
139139

140+
// Detect package-managed installations — refuse to avoid breaking metadata
141+
let current_exe =
142+
std::env::current_exe().context("cannot determine current executable path")?;
143+
let path_str = current_exe.to_string_lossy();
144+
if path_str.contains("/Cellar/") || path_str.contains("/homebrew/") {
145+
bail!(
146+
"Detected Homebrew installation ({}).\nUse 'brew upgrade icm' instead to keep metadata consistent.",
147+
current_exe.display()
148+
);
149+
}
150+
if path_str.starts_with("/usr/bin/")
151+
|| path_str.starts_with("/opt/") && !path_str.contains("/homebrew/")
152+
{
153+
eprintln!(
154+
"Warning: {} may be managed by a package manager (apt/dnf/rpm).",
155+
current_exe.display()
156+
);
157+
eprintln!("Consider using your package manager to upgrade instead.");
158+
}
159+
140160
// 2. Detect target
141161
let (target, ext) = detect_target()?;
142162
let archive_name = format!("{BINARY_NAME}-{target}.{ext}");
@@ -170,8 +190,6 @@ pub fn cmd_upgrade(apply: bool, check_only: bool) -> Result<()> {
170190
let new_binary = extract_binary(&archive_bytes, is_zip)?;
171191

172192
// 6. Replace running binary atomically
173-
let current_exe =
174-
std::env::current_exe().context("cannot determine current executable path")?;
175193
let backup_path: PathBuf = current_exe.with_extension("old");
176194
let new_path: PathBuf = current_exe.with_extension("new");
177195

0 commit comments

Comments
 (0)