Files
navi/internal/update/update_darwin.go
T

51 lines
1.2 KiB
Go

//go:build darwin
package update
import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
)
// Apply downloads the new binary and schedules replacement after exit (macOS).
func Apply(ctx context.Context, manifestURL string) (string, error) {
latest, _, _, exe, tmp, err := prepareDownload(ctx, manifestURL)
if err != nil {
return "", err
}
_ = os.Chmod(tmp, 0o755)
dir := filepath.Dir(exe)
scriptPath := filepath.Join(dir, "navis-update.sh")
pid := os.Getpid()
script := "#!/bin/bash\n" +
"set -e\n" +
"EXE=" + shellQuote(exe) + "\n" +
"NEW=" + shellQuote(tmp) + "\n" +
"PID=" + strconv.Itoa(pid) + "\n" +
"while kill -0 \"$PID\" 2>/dev/null; do sleep 0.4; done\n" +
"sleep 0.5\n" +
"mv -f \"$NEW\" \"$EXE\"\n" +
"chmod +x \"$EXE\"\n" +
"rm -f " + shellQuote(scriptPath) + "\n"
if err := os.WriteFile(scriptPath, []byte(script), 0o755); err != nil {
return "", err
}
cmd := exec.Command("/bin/bash", scriptPath)
cmd.Dir = dir
if err := cmd.Start(); err != nil {
return "", fmt.Errorf("start updater: %w", err)
}
return latest, nil
}
func shellQuote(s string) string {
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
}