Files
agent-manager/src/commands/self_update.rs
T

82 lines
3.0 KiB
Rust

//! self-update: download a newer agent-manager binary from GitHub Releases.
use super::*;
use crate::download;
use anyhow::{anyhow, bail, Context, Result};
use std::cmp::Ordering;
use std::path::Path;
pub fn run(app: &App, check: bool, to: Option<&Path>) -> Result<i32> {
let Some(repo) = app.config.settings.self_update_repo.clone() else {
bail!(
"self-update is not configured: set 'settings.self_update_repo: \"owner/repo\"' in your config"
);
};
let current = env!("CARGO_PKG_VERSION");
let release = download::latest_release_with_base(
&repo,
app.config.settings.self_update_base_url.as_deref(),
)?;
let tag = release.tag_name.trim_start_matches('v').to_string();
if check {
match crate::version::compare(&tag, current) {
Some(Ordering::Greater) => {
println!("update available: {current} -> {tag}");
Ok(0)
}
_ => {
println!("agent-manager {current} is up to date");
Ok(0)
}
}
} else {
if crate::version::compare(&tag, current) != Some(Ordering::Greater) {
app.log.success(&format!(
"agent-manager {current} is already the latest version"
));
return Ok(0);
}
if app.dry_run() {
app.log
.dry(format!("would download agent-manager {tag}"));
return Ok(0);
}
let picked = download::pick_asset(&release, &[], &[], None)
.ok_or_else(|| anyhow!("no release asset of '{repo}' matches this platform"))?;
app.log.info(&format!(
"downloading agent-manager {tag} ({})",
picked.name
));
let current_exe = std::env::current_exe()?;
let dest = to.map(|p| p.to_path_buf()).unwrap_or_else(|| current_exe.clone());
let tmpdir = tempfile::tempdir()?;
let tmp = tmpdir.path().join("am.new");
download::download(&picked.url, &tmp, None, true)?;
if dest == current_exe && cfg!(windows) {
// The running executable is locked on Windows.
let new_path = current_exe.with_extension("exe.new");
std::fs::copy(&tmp, &new_path)
.with_context(|| format!("cannot write {}", new_path.display()))?;
app.log.success(&format!(
"downloaded {tag} to {} — replace the running binary manually",
new_path.display()
));
} else {
std::fs::copy(&tmp, &dest)
.with_context(|| format!("cannot write {}", dest.display()))?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let _ = std::fs::set_permissions(
&dest,
std::fs::Permissions::from_mode(0o755),
);
}
app.log
.success(&format!("updated agent-manager to {tag} ({})", dest.display()));
}
Ok(0)
}
}