aboutsummaryrefslogtreecommitdiff
path: root/src/update.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-23 17:34:01 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-23 17:42:49 +0300
commitec2924d0d1f21417802c3efd0ed46b9db2c00582 (patch)
tree00432d4dbb46bb82328dfb583e36293c1603bc81 /src/update.rs
parent0d2c20a46235ae2535d4fdef59b9529e44faa98f (diff)
feat: add optional nix flake support
refs #208 refs #221 refs #264
Diffstat (limited to 'src/update.rs')
-rw-r--r--src/update.rs51
1 files changed, 50 insertions, 1 deletions
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(&current_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<Version, String> {
));
}
+ 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<crate::events::AppEvent>) {
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<crate::events::AppEvent>) {
);
// 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(),
});
}
@@ -1288,6 +1323,20 @@ mod tests {
}
#[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(
br#"{"versions":{"stable":"0.5.10","head":"HEAD","bottle":true}}"#,