51 lines
1.2 KiB
Go
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, "'", `'\''`) + "'"
|
|
}
|