From ee71ecf00efda66430dd7d2ce9469aa665caba60 Mon Sep 17 00:00:00 2001 From: intergrav Date: Wed, 1 Jul 2026 06:47:20 -0400 Subject: [PATCH] feat: bundle restic with macos `.app` downloaded and bundled at build time. still recommend to have a restic binary in path managed by like homebrew or something for latest version --- README.md | 2 +- cmd/restray/restic.go | 19 +++++++++++++++++++ justfile | 20 +++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6fae6a1..ab97f86 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ This is new and somewhat work-in-progress/beta software. You might possibly enco To install, grab a build artifact for your OS and architecture from the [repository's tags](https://tangled.org/devins.page/restray/tags). On MacOS you'll need to [remove quarantine](https://disable-gatekeeper.github.io#disabling-gatekeeper-for-one-application-only) from the `.app`, since I can't pay Apple $100/year to sign it. Sorry. -Restray requires [restic](https://restic.net) installed to your PATH on MacOS/Linux, so install it with your package manager. On Windows, Restray can download and manage it's own restic binary itself if it isn't already in PATH. +On MacOS, a restic binary is downloaded and bundled to the `.app` at build time, though I'd recommend installing restic to your path so you have the latest version. On Windows, Restray can download and update it's own restic binary itself if it isn't already in PATH. On Linux, you should install restic with your package manager. _If you're a Nix/NixOS/Nix-darwin user, I also provide package/module in the project's [flake](https://tangled.org/devins.page/restray) for Linux and MacOS._ diff --git a/cmd/restray/restic.go b/cmd/restray/restic.go index 874b252..e1e4326 100644 --- a/cmd/restray/restic.go +++ b/cmd/restray/restic.go @@ -41,11 +41,30 @@ func findRestic() (path string, managed bool) { if p := managedRestic(); p != "" { resticPath = p resticManaged = true + return + } + if p := bundledRestic(); p != "" { + resticPath = p } }) return resticPath, resticManaged } +func bundledRestic() string { + if runtime.GOOS != "darwin" { + return "" + } + exe, err := os.Executable() + if err != nil { + return "" + } + p := filepath.Join(filepath.Dir(exe), "..", "Resources", "restic") + if _, err := os.Stat(p); err == nil { + return p + } + return "" +} + func findResticFromShell() string { if runtime.GOOS == "windows" { return "" diff --git a/justfile b/justfile index 14bb814..bf08442 100644 --- a/justfile +++ b/justfile @@ -111,14 +111,32 @@ package target="" arch="": esac _package-darwin arch: + #!/usr/bin/env bash + set -e rm -rf {{dist}}/Restray.app mkdir -p {{dist}}/Restray.app/Contents/MacOS {{dist}}/Restray.app/Contents/Resources cp {{bin}}/{{app}}-{{version}}-darwin-{{arch}} {{dist}}/Restray.app/Contents/MacOS/Restray cp packaging/darwin/Info.plist {{dist}}/Restray.app/Contents/Info.plist cp packaging/darwin/restray.icns {{dist}}/Restray.app/Contents/Resources/restray.icns - cd {{dist}} && zip -r {{app}}-{{version}}-darwin-{{arch}}-app.zip Restray.app + just _fetch-restic-darwin {{arch}} + cp {{bin}}/restic-darwin-{{arch}} {{dist}}/Restray.app/Contents/Resources/restic + chmod +x {{dist}}/Restray.app/Contents/Resources/restic + (cd {{dist}} && zip -r {{app}}-{{version}}-darwin-{{arch}}-app.zip Restray.app) rm -rf {{dist}}/Restray.app +_fetch-restic-darwin arch: + #!/usr/bin/env bash + set -e + out="{{bin}}/restic-darwin-{{arch}}" + [ -f "$out" ] && exit 0 + mkdir -p {{bin}} + tmp=$(mktemp -d) + trap 'rm -rf "$tmp"' EXIT + version=$(curl -fsSL https://api.github.com/repos/restic/restic/releases/latest | grep '"tag_name"' | head -1 | cut -d'"' -f4 | sed 's/^v//') + curl -fsSL -o "$tmp/restic.bz2" "https://github.com/restic/restic/releases/download/v${version}/restic_${version}_darwin_{{arch}}.bz2" + bunzip2 -c "$tmp/restic.bz2" > "$out" + chmod +x "$out" + _package-windows arch: mkdir -p {{dist}} cp {{bin}}/{{app}}-{{version}}-windows-{{arch}}.exe {{bin}}/{{app}}.exe -- 2.51.2