返回 DeepSeek-Reasonix
icon_repair_darwin.go
根目录 / desktop / icon_repair_darwin.go
1 //go:build darwin && cgo
2
3 package main
4
5 /*
6 #cgo LDFLAGS: -framework Foundation
7 #include <stdlib.h>
8
9 int reasonix_repair_alias(const char *alias_path, const char *current_app_path,
10 int allow_broken, char **error_message);
11 int reasonix_write_alias(const char *target_path, const char *alias_path,
12 char **error_message);
13 int reasonix_resolve_alias(const char *alias_path, char **target_path,
14 char **error_message);
15 int reasonix_is_reasonix_bundle_url_string(const char *url_string,
16 char **error_message);
17 */
18 import "C"
19
20 import (
21 "errors"
22 "fmt"
23 "os"
24 "path/filepath"
25 "strings"
26 "unsafe"
27 )
28
29 func repairDesktopIconIntegration() error {
30 currentApp, err := currentMacAppBundle()
31 if err != nil {
32 // Developer binaries and tests are not installed app bundles.
33 return nil
34 }
35 home, err := os.UserHomeDir()
36 if err != nil {
37 return err
38 }
39 return repairMacDesktopAliases(filepath.Join(home, "Desktop"), currentApp)
40 }
41
42 func repairMacDesktopAliases(desktopDir, currentApp string) error {
43 entries, err := os.ReadDir(desktopDir)
44 if err != nil {
45 if os.IsNotExist(err) {
46 return nil
47 }
48 return err
49 }
50 var repairErr error
51 for _, entry := range entries {
52 if entry.IsDir() {
53 continue
54 }
55 path := filepath.Join(desktopDir, entry.Name())
56 allowBroken := reasonixExactAliasName(entry.Name())
57 repaired, err := repairMacAlias(path, currentApp, allowBroken)
58 if err != nil {
59 repairErr = errors.Join(repairErr, fmt.Errorf("%s: %w", entry.Name(), err))
60 continue
61 }
62 _ = repaired // Native code returns false for ordinary desktop files.
63 }
64 return repairErr
65 }
66
67 func reasonixExactAliasName(name string) bool {
68 name = strings.TrimSpace(name)
69 return strings.EqualFold(name, "Reasonix") || strings.EqualFold(name, "Reasonix.app")
70 }
71
72 func repairMacAlias(aliasPath, currentApp string, allowBroken bool) (bool, error) {
73 aliasCString := C.CString(aliasPath)
74 appCString := C.CString(currentApp)
75 defer C.free(unsafe.Pointer(aliasCString))
76 defer C.free(unsafe.Pointer(appCString))
77 var nativeErr *C.char
78 allow := C.int(0)
79 if allowBroken {
80 allow = 1
81 }
82 result := C.reasonix_repair_alias(aliasCString, appCString, allow, &nativeErr)
83 if nativeErr != nil {
84 defer C.free(unsafe.Pointer(nativeErr))
85 }
86 if result < 0 {
87 if nativeErr == nil {
88 return false, fmt.Errorf("native alias repair failed")
89 }
90 return false, fmt.Errorf("%s", C.GoString(nativeErr))
91 }
92 return result == 1, nil
93 }
94
95 func writeMacAlias(targetPath, aliasPath string) error {
96 targetCString := C.CString(targetPath)
97 aliasCString := C.CString(aliasPath)
98 defer C.free(unsafe.Pointer(targetCString))
99 defer C.free(unsafe.Pointer(aliasCString))
100 var nativeErr *C.char
101 result := C.reasonix_write_alias(targetCString, aliasCString, &nativeErr)
102 if nativeErr != nil {
103 defer C.free(unsafe.Pointer(nativeErr))
104 }
105 if result != 0 {
106 if nativeErr == nil {
107 return fmt.Errorf("native alias write failed")
108 }
109 return fmt.Errorf("%s", C.GoString(nativeErr))
110 }
111 return nil
112 }
113
114 func resolveMacAlias(aliasPath string) (string, error) {
115 aliasCString := C.CString(aliasPath)
116 defer C.free(unsafe.Pointer(aliasCString))
117 var target, nativeErr *C.char
118 result := C.reasonix_resolve_alias(aliasCString, &target, &nativeErr)
119 if target != nil {
120 defer C.free(unsafe.Pointer(target))
121 }
122 if nativeErr != nil {
123 defer C.free(unsafe.Pointer(nativeErr))
124 }
125 if result != 0 {
126 if nativeErr == nil {
127 return "", fmt.Errorf("native alias resolution failed")
128 }
129 return "", fmt.Errorf("%s", C.GoString(nativeErr))
130 }
131 return C.GoString(target), nil
132 }
133
134 func macURLReferencesReasonixBundle(rawURL string) (bool, error) {
135 urlCString := C.CString(rawURL)
136 defer C.free(unsafe.Pointer(urlCString))
137 var nativeErr *C.char
138 result := C.reasonix_is_reasonix_bundle_url_string(urlCString, &nativeErr)
139 if nativeErr != nil {
140 defer C.free(unsafe.Pointer(nativeErr))
141 }
142 if result < 0 {
143 if nativeErr == nil {
144 return false, fmt.Errorf("native bundle URL inspection failed")
145 }
146 return false, fmt.Errorf("%s", C.GoString(nativeErr))
147 }
148 return result == 1, nil
149 }
150
150 lines GO