返回 DeepSeek-Reasonix
updater_mac_bundle.go
根目录 / desktop / updater_mac_bundle.go
1 //go:build darwin
2
3 package main
4
5 import (
6 "fmt"
7 "os"
8 "os/exec"
9 "path/filepath"
10 "strings"
11 )
12
13 func currentMacAppBundle() (string, error) {
14 exe, err := os.Executable()
15 if err != nil {
16 return "", fmt.Errorf("update: locate current executable: %w", err)
17 }
18 return macAppBundleForExecutable(exe)
19 }
20
21 func macAppBundleForExecutable(exe string) (string, error) {
22 exe = strings.TrimSpace(exe)
23 if exe == "" {
24 return "", fmt.Errorf("update: current executable path is empty")
25 }
26 absolute, err := filepath.Abs(exe)
27 if err != nil {
28 return "", fmt.Errorf("update: make current executable path absolute: %w", err)
29 }
30 resolved, err := filepath.EvalSymlinks(filepath.Clean(absolute))
31 if err != nil {
32 return "", fmt.Errorf("update: resolve current executable: %w", err)
33 }
34 // Keep the installed path spelling while requiring the link chain to resolve.
35 // An external launcher may instead use its resolved in-bundle target.
36 contents, ok := macAppContentsForExecutable(absolute)
37 if !ok {
38 contents, ok = macAppContentsForExecutable(resolved)
39 }
40 if !ok {
41 return "", fmt.Errorf("update: current executable is not inside a macOS .app bundle")
42 }
43 app := filepath.Dir(contents)
44 info := filepath.Join(contents, "Info.plist")
45 if st, err := os.Lstat(info); err != nil || !st.Mode().IsRegular() || st.Mode()&os.ModeSymlink != 0 {
46 if err == nil {
47 err = fmt.Errorf("Info.plist is not a regular file")
48 }
49 return "", fmt.Errorf("update: current app bundle is invalid: %w", err)
50 }
51 out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print :CFBundleIdentifier", info).Output()
52 if err != nil {
53 return "", fmt.Errorf("update: current app bundle is invalid: read bundle identifier: %w", err)
54 }
55 if got := strings.TrimSpace(string(out)); got != macBundleID {
56 return "", fmt.Errorf("update: current app bundle identifier %q does not match %q", got, macBundleID)
57 }
58 return app, nil
59 }
60
60 lines GO