1//go:build !windows
2
3package update
4
5import (
6 "fmt"
7 "os"
8 "path/filepath"
9)
10
11// Apply replaces the current executable with the downloaded binary.
12func Apply(binaryPath string) error {
13 // Get path to current executable.
14 exe, err := os.Executable()
15 if err != nil {
16 return fmt.Errorf("failed to get executable path: %w", err)
17 }
18
19 // Resolve symlinks.
20 exe, err = filepath.EvalSymlinks(exe)
21 if err != nil {
22 return fmt.Errorf("failed to resolve symlinks: %w", err)
23 }
24
25 // Get the directory of the executable.
26 exeDir := filepath.Dir(exe)
27
28 // Check if we have write permissions to the directory.
29 if err := checkWritePermission(exeDir); err != nil {
30 return fmt.Errorf("cannot write to %s: %w (you may need to run with elevated privileges)", exeDir, err)
31 }
32
33 // Copy binary to exe directory first to ensure same filesystem.
34 // os.Rename fails across filesystems, and binaryPath may be in /tmp.
35 localBinary := filepath.Join(exeDir, ".crush-update-new")
36 if err := copyFile(binaryPath, localBinary); err != nil {
37 return fmt.Errorf("failed to copy new binary: %w", err)
38 }
39
40 // Create a backup of the current executable.
41 backupPath := filepath.Join(exeDir, filepath.Base(exe)+".old")
42 if err := os.Rename(exe, backupPath); err != nil {
43 os.Remove(localBinary)
44 return fmt.Errorf("failed to backup current executable: %w", err)
45 }
46
47 // Move new binary to executable location.
48 if err := os.Rename(localBinary, exe); err != nil {
49 // Try to restore backup on failure.
50 _ = os.Rename(backupPath, exe)
51 os.Remove(localBinary)
52 return fmt.Errorf("failed to install new version: %w", err)
53 }
54
55 // Remove backup on success.
56 _ = os.Remove(backupPath)
57
58 return nil
59}
60
61// HasPendingUpdate returns false on Unix since updates are applied immediately.
62func HasPendingUpdate() bool {
63 return false
64}
65
66// ApplyPendingUpdate is a no-op on Unix since updates are applied immediately.
67func ApplyPendingUpdate() error {
68 return nil
69}