mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
fix(desktop): repoint dangling versioned shortcut targets to the launcher
This commit is contained in:
1 parent
6c22ae0a3f
commit
a80f75bbf2
2 files changed
+101
-9
No files matched your search
@@ -126,18 +126,39 @@ func repairWindowsShortcut(shortcutPath, launcher string) (bool, error) {
|
||||
}
|
||||
iconLocation := iconValue.ToString()
|
||||
_ = iconValue.Clear()
|
||||
if !reasonixWindowsStaleIcon(iconLocation, launcher) {
|
||||
repointTarget, fixIcon := repairWindowsShortcutPlan(target, iconLocation, launcher)
|
||||
if !repointTarget && !fixIcon {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
result, err := oleutil.PutProperty(shortcut, "IconLocation", launcher+",0")
|
||||
if result != nil {
|
||||
_ = result.Clear()
|
||||
if repointTarget {
|
||||
// A version-scoped target points into versions/<v>/reasonix-desktop.exe,
|
||||
// which the updater deletes when it switches or prunes versions. Repoint
|
||||
// it at the stable launcher so the shortcut survives updates.
|
||||
result, err := oleutil.PutProperty(shortcut, "TargetPath", launcher)
|
||||
if result != nil {
|
||||
_ = result.Clear()
|
||||
}
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("set TargetPath: %w", err)
|
||||
}
|
||||
result, err = oleutil.PutProperty(shortcut, "WorkingDirectory", filepath.Dir(launcher))
|
||||
if result != nil {
|
||||
_ = result.Clear()
|
||||
}
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("set WorkingDirectory: %w", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("set IconLocation: %w", err)
|
||||
if fixIcon {
|
||||
result, err := oleutil.PutProperty(shortcut, "IconLocation", launcher+",0")
|
||||
if result != nil {
|
||||
_ = result.Clear()
|
||||
}
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("set IconLocation: %w", err)
|
||||
}
|
||||
}
|
||||
result, err = oleutil.CallMethod(shortcut, "Save")
|
||||
result, err := oleutil.CallMethod(shortcut, "Save")
|
||||
if result != nil {
|
||||
_ = result.Clear()
|
||||
}
|
||||
@@ -160,7 +181,16 @@ func reasonixWindowsShortcutTarget(target, launcher string) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
rel, err := filepath.Rel(root, target)
|
||||
return reasonixWindowsVersionedTarget(target, launcher)
|
||||
}
|
||||
|
||||
// reasonixWindowsVersionedTarget reports whether target points into this
|
||||
// install's versions/<version>/reasonix-desktop.exe, a version-scoped path
|
||||
// that the updater deletes when it switches or prunes versions. Such targets
|
||||
// dangle after an update, so repair must repoint them at the stable launcher.
|
||||
func reasonixWindowsVersionedTarget(target, launcher string) bool {
|
||||
root := filepath.Dir(filepath.Clean(strings.TrimSpace(launcher)))
|
||||
rel, err := filepath.Rel(root, filepath.Clean(strings.TrimSpace(target)))
|
||||
if err != nil || rel == "." || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
|
||||
return false
|
||||
}
|
||||
@@ -169,6 +199,14 @@ func reasonixWindowsShortcutTarget(target, launcher string) bool {
|
||||
strings.EqualFold(parts[2], "reasonix-desktop.exe")
|
||||
}
|
||||
|
||||
// repairWindowsShortcutPlan decides which owned-shortcut properties need
|
||||
// rewriting. repointTarget is true when TargetPath points into a versioned
|
||||
// directory the updater can delete; fixIcon is true when IconLocation points
|
||||
// at the versioned desktop binary instead of the stable launcher.
|
||||
func repairWindowsShortcutPlan(target, iconLocation, launcher string) (repointTarget, fixIcon bool) {
|
||||
return reasonixWindowsVersionedTarget(target, launcher), reasonixWindowsStaleIcon(iconLocation, launcher)
|
||||
}
|
||||
|
||||
func reasonixWindowsStaleIcon(iconLocation, launcher string) bool {
|
||||
iconPath := strings.TrimSpace(iconLocation)
|
||||
if comma := strings.LastIndex(iconPath, ","); comma >= 0 {
|
||||
|
||||
@@ -95,3 +95,57 @@ func TestReasonixWindowsStaleIconOnlyMatchesVersionedDesktop(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReasonixWindowsVersionedTarget(t *testing.T) {
|
||||
root := filepath.Join(`C:\Program Files`, "Reasonix")
|
||||
launcher := filepath.Join(root, "reasonix-launcher.exe")
|
||||
tests := []struct {
|
||||
name string
|
||||
target string
|
||||
want bool
|
||||
}{
|
||||
{name: "versioned desktop", target: filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe"), want: true},
|
||||
{name: "case-insensitive", target: filepath.Join(root, "Versions", "V1.19.3", "Reasonix-Desktop.exe"), want: true},
|
||||
{name: "launcher", target: launcher, want: false},
|
||||
{name: "launcher alias", target: filepath.Join(root, "Reasonix.exe"), want: false},
|
||||
{name: "flat desktop", target: filepath.Join(root, "reasonix-desktop.exe"), want: false},
|
||||
{name: "deeper versioned path", target: filepath.Join(root, "versions", "v1.19.3", "sub", "reasonix-desktop.exe"), want: false},
|
||||
{name: "wrong binary in versions", target: filepath.Join(root, "versions", "v1.19.3", "reasonix-cli.exe"), want: false},
|
||||
{name: "other install", target: filepath.Join(`D:\Apps`, "Reasonix", "versions", "v1.19.3", "reasonix-desktop.exe"), want: false},
|
||||
{name: "empty", target: "", want: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := reasonixWindowsVersionedTarget(tt.target, launcher); got != tt.want {
|
||||
t.Fatalf("reasonixWindowsVersionedTarget(%q, %q) = %v, want %v", tt.target, launcher, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepairWindowsShortcutPlan(t *testing.T) {
|
||||
root := filepath.Join(`C:\Program Files`, "Reasonix")
|
||||
launcher := filepath.Join(root, "reasonix-launcher.exe")
|
||||
versioned := filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe")
|
||||
tests := []struct {
|
||||
name string
|
||||
target string
|
||||
icon string
|
||||
wantRepoint bool
|
||||
wantFixIcon bool
|
||||
}{
|
||||
{name: "versioned target + versioned icon", target: versioned, icon: versioned + ",0", wantRepoint: true, wantFixIcon: true},
|
||||
{name: "versioned target + clean icon", target: versioned, icon: launcher + ",0", wantRepoint: true, wantFixIcon: false},
|
||||
{name: "stable target + versioned icon", target: launcher, icon: versioned + ",0", wantRepoint: false, wantFixIcon: true},
|
||||
{name: "stable target + clean icon", target: launcher, icon: launcher + ",0", wantRepoint: false, wantFixIcon: false},
|
||||
{name: "custom target + custom icon", target: filepath.Join(root, "custom.ico"), icon: filepath.Join(root, "custom.ico") + ",0", wantRepoint: false, wantFixIcon: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repoint, fixIcon := repairWindowsShortcutPlan(tt.target, tt.icon, launcher)
|
||||
if repoint != tt.wantRepoint || fixIcon != tt.wantFixIcon {
|
||||
t.Fatalf("repairWindowsShortcutPlan(%q, %q) = (%v, %v), want (%v, %v)", tt.target, tt.icon, repoint, fixIcon, tt.wantRepoint, tt.wantFixIcon)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user