A shepherd for your Appimages.
0

Configure Feed

Select the types of activity you want to include in your feed.

link: don't clobber existing files

Aly Raffauf (Jun 19, 2026, 3:14 AM EDT) 72f309f5 6015b972

+22 -2
+22 -2
internal/appherder/link.go
··· 4 4 "fmt" 5 5 "os" 6 6 "path/filepath" 7 + "strings" 7 8 ) 8 9 9 10 func (a App) linkPath(appName string) string { ··· 24 25 return fmt.Errorf("create %s: %w", a.binDir, err) 25 26 } 26 27 dst := a.linkPath(appName) 27 - if err := os.Remove(dst); err != nil && !os.IsNotExist(err) { 28 - return fmt.Errorf("remove existing link %s: %w", dst, err) 28 + 29 + if target, err := os.Readlink(dst); err == nil { 30 + if target == src { 31 + return nil 32 + } 33 + fmt.Fprintf(os.Stderr, "Warning: %s is already linked to a different target\n", dst) 34 + return nil 29 35 } 36 + if _, err := os.Lstat(dst); err == nil { 37 + fmt.Fprintf(os.Stderr, "Warning: %s already exists, skipping\n", dst) 38 + return nil 39 + } 40 + 30 41 if err := os.Symlink(src, dst); err != nil { 31 42 return fmt.Errorf("link %s -> %s: %w", dst, src, err) 32 43 } ··· 36 47 func (a App) Unlink(appName string) error { 37 48 appName = NormalizeAppName(appName) 38 49 dst := a.linkPath(appName) 50 + 51 + target, err := os.Readlink(dst) 52 + if err != nil { 53 + return fmt.Errorf("%s is not a link managed by appherder", dst) 54 + } 55 + if !strings.HasPrefix(target, a.appimagesDir+string(filepath.Separator)) { 56 + return fmt.Errorf("%s is not a link managed by appherder", dst) 57 + } 58 + 39 59 if err := os.Remove(dst); err != nil { 40 60 return fmt.Errorf("remove link %s: %w", dst, err) 41 61 }