From 60387e922234c9b3674940c8037d55196f955855 Mon Sep 17 00:00:00 2001 From: DuProcess <273172371+DuProcess@users.noreply.github.com> Date: Thu, 2 Jul 2026 18:41:02 -0400 Subject: [PATCH] Install Dosh binaries atomically --- install.ps1 | 24 +++++++++++++++++++----- install.sh | 25 +++++++++++++++++++------ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/install.ps1 b/install.ps1 index c630331..ad23a7e 100644 --- a/install.ps1 +++ b/install.ps1 @@ -141,6 +141,20 @@ function Verify-ArchiveVersion($ExtractDir, $Url) { } } +function Install-Binary($Source, $Destination) { + $dir = Split-Path -Parent $Destination + $name = Split-Path -Leaf $Destination + $tmp = Join-Path $dir ".$name.tmp.$PID" + Copy-Item $Source $tmp -Force + try { + Move-Item $tmp $Destination -Force + } + catch { + Remove-Item $tmp -Force -ErrorAction SilentlyContinue + throw + } +} + $bindir = Join-Path $Prefix "bin" $configDir = Join-Path $HOME ".config\dosh" New-Item -ItemType Directory -Force -Path $bindir, $configDir | Out-Null @@ -168,9 +182,9 @@ function Install-Prebuilt { if (-not $found) { throw "prebuilt archive missing $bin" } - Copy-Item $found.FullName (Join-Path $bindir $bin) -Force + Install-Binary $found.FullName (Join-Path $bindir $bin) } - Copy-Item (Join-Path $bindir "dosh-client.exe") (Join-Path $bindir "dosh.exe") -Force + Install-Binary (Join-Path $bindir "dosh-client.exe") (Join-Path $bindir "dosh.exe") return $true } catch { @@ -202,9 +216,9 @@ function Install-FromSource { try { Push-Location $src cargo build --release --bin dosh-client --bin dosh-bench - Copy-Item "target\release\dosh-client.exe" (Join-Path $bindir "dosh-client.exe") -Force - Copy-Item "target\release\dosh-client.exe" (Join-Path $bindir "dosh.exe") -Force - Copy-Item "target\release\dosh-bench.exe" (Join-Path $bindir "dosh-bench.exe") -Force + Install-Binary "target\release\dosh-client.exe" (Join-Path $bindir "dosh-client.exe") + Install-Binary "target\release\dosh-client.exe" (Join-Path $bindir "dosh.exe") + Install-Binary "target\release\dosh-bench.exe" (Join-Path $bindir "dosh-bench.exe") } finally { Pop-Location diff --git a/install.sh b/install.sh index 8cf362a..c198c7c 100755 --- a/install.sh +++ b/install.sh @@ -226,13 +226,26 @@ find_extracted_binary() { find "$1" -type f -name "$2" 2>/dev/null | sed -n '1p' } +install_binary() { + src="$1" + dst="$2" + dst_dir="$(dirname "$dst")" + dst_base="$(basename "$dst")" + tmp="$dst_dir/.$dst_base.tmp.$$" + install -m 0755 "$src" "$tmp" + if ! mv -f "$tmp" "$dst"; then + rm -f "$tmp" + return 1 + fi +} + install_extracted_binary() { found="$(find_extracted_binary "$1" "$2")" if [ -z "$found" ]; then echo "prebuilt archive missing $2" >&2 return 1 fi - install -m 0755 "$found" "$3" + install_binary "$found" "$3" } sha256_file() { @@ -329,7 +342,7 @@ try_install_prebuilt() { install_extracted_binary "$tmpdir/extract" dosh-auth "$bindir/dosh-auth" || return 1 fi if found_bench="$(find_extracted_binary "$tmpdir/extract" dosh-bench)" && [ -n "$found_bench" ]; then - install -m 0755 "$found_bench" "$bindir/dosh-bench" + install_binary "$found_bench" "$bindir/dosh-bench" fi return 0 } @@ -388,14 +401,14 @@ install_from_source() { fi fi - install -m 0755 target/release/dosh-client "$bindir/dosh-client" + install_binary target/release/dosh-client "$bindir/dosh-client" ln -sf dosh-client "$bindir/dosh" if [ "$role" = "server" ] || [ "$role" = "both" ]; then - install -m 0755 target/release/dosh-server "$bindir/dosh-server" - install -m 0755 target/release/dosh-auth "$bindir/dosh-auth" + install_binary target/release/dosh-server "$bindir/dosh-server" + install_binary target/release/dosh-auth "$bindir/dosh-auth" fi if [ -f target/release/dosh-bench ]; then - install -m 0755 target/release/dosh-bench "$bindir/dosh-bench" + install_binary target/release/dosh-bench "$bindir/dosh-bench" fi }