From ec2924d0d1f21417802c3efd0ed46b9db2c00582 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Sat, 23 May 2026 17:34:01 +0300 Subject: feat: add optional nix flake support refs #208 refs #221 refs #264 --- src/update.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/update.rs b/src/update.rs index f37a9265..2a2776fa 100644 --- a/src/update.rs +++ b/src/update.rs @@ -21,6 +21,7 @@ const UPDATE_MANIFEST_URL: &str = "https://herdr.dev/latest.json"; const HOMEBREW_FORMULA_API_URL: &str = "https://formulae.brew.sh/api/formula/herdr.json"; const HERDR_UPDATE_COMMAND: &str = "herdr update"; const HOMEBREW_UPDATE_COMMAND: &str = "brew update && brew upgrade herdr"; +const NIX_UPDATE_COMMAND: &str = "update through Nix"; const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION"); const FAKE_UPDATE_VERSION_ENV: &str = "HERDR_FAKE_UPDATE_VERSION"; const FAKE_UPDATE_NOTES_VERSION_ENV: &str = "HERDR_FAKE_UPDATE_NOTES_VERSION"; @@ -678,6 +679,8 @@ fn wait_for_server_shutdown(timeout: Duration) -> Result<(), String> { pub(crate) fn update_install_command() -> &'static str { if is_homebrew_managed_install() { HOMEBREW_UPDATE_COMMAND + } else if is_nix_managed_install() { + NIX_UPDATE_COMMAND } else { HERDR_UPDATE_COMMAND } @@ -697,6 +700,24 @@ fn is_homebrew_managed_install() -> bool { .is_ok_and(|path| is_homebrew_managed_exe_path(&path)) } +fn is_nix_managed_install() -> bool { + let Ok(current_exe) = env::current_exe() else { + return false; + }; + + if is_nix_store_exe_path(¤t_exe) { + return true; + } + + current_exe + .canonicalize() + .is_ok_and(|path| is_nix_store_exe_path(&path)) +} + +fn is_nix_store_exe_path(path: &Path) -> bool { + path.starts_with("/nix/store") +} + fn is_homebrew_managed_exe_path(path: &Path) -> bool { homebrew_cellar_keg_root(path).is_some() } @@ -991,6 +1012,12 @@ pub fn self_update() -> Result { )); } + if is_nix_managed_install() { + return Err( + "self-update is disabled for Nix installs; update with `nix profile upgrade` or update the flake input that provides Herdr".into(), + ); + } + if running_inside_herdr() { return Err("run `herdr update` outside herdr after detaching from the session".into()); } @@ -1075,6 +1102,8 @@ pub fn auto_update(events: tokio::sync::mpsc::Sender) { return; } + let nix_managed_install = is_nix_managed_install(); + let release = match check_latest() { Ok(Some(r)) => r, Ok(None) => return, @@ -1103,9 +1132,15 @@ pub fn auto_update(events: tokio::sync::mpsc::Sender) { ); // Notify the TUI — blocking_send is safe from a std::thread + let install_command = if nix_managed_install { + NIX_UPDATE_COMMAND + } else { + HERDR_UPDATE_COMMAND + }; + let _ = events.blocking_send(crate::events::AppEvent::UpdateReady { version: release.version.to_string(), - install_command: HERDR_UPDATE_COMMAND.to_string(), + install_command: install_command.to_string(), }); } @@ -1287,6 +1322,20 @@ mod tests { assert!(!is_homebrew_managed_exe_path(path)); } + #[test] + fn nix_store_path_is_detected() { + let path = Path::new("/nix/store/abc123-herdr-0.6.1/bin/herdr"); + + assert!(is_nix_store_exe_path(path)); + } + + #[test] + fn non_nix_store_path_is_not_detected() { + let path = Path::new("/usr/local/bin/herdr"); + + assert!(!is_nix_store_exe_path(path)); + } + #[test] fn parse_homebrew_formula_stable_version_reads_versions_stable() { let version = parse_homebrew_formula_stable_version( -- cgit v1.2.3