/ veet / internal / detector / goinstall.go
swadhinbiswas feat: initial release of VEET (Universal Linux App Uninstaller & Deep-Clean Residual Purger) · 8/15/2026
5e0888a
58 lines · 1.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package detector

import (
	"context"
	"os"
	"path/filepath"
	"strings"

	"github.com/swadhinbiswas/veet/internal/model"
)

type goinstallDetector struct {
	ex   Execer
	path string
}

// NewGoInstallDetector detects binaries installed via `go install`.
func NewGoInstallDetector(ex Execer) Detector {
	path, _ := ex.LookPath("go")
	return &goinstallDetector{ex: ex, path: path}
}

func (d *goinstallDetector) Source() string  { return "go" }
func (d *goinstallDetector) Available() bool { return d.path != "" }

func (d *goinstallDetector) Detect(ctx context.Context) ([]model.AppInfo, error) {
	gopath := ""
	if dir, err := Exec(ctx, d.ex, "go", "env", "GOPATH"); err == nil {
		gopath = strings.TrimSpace(dir)
	} else {
		return nil, err
	}
	bin := filepath.Join(gopath, "bin")
	entries, err := os.ReadDir(bin)
	if err != nil {
		return nil, err
	}
	var apps []model.AppInfo
	for _, e := range entries {
		if e.IsDir() {
			continue
		}
		info, err := e.Info()
		if err != nil || info.Mode()&0111 == 0 {
			continue // heuristic: only executable files are go-installed binaries
		}
		size := (info.Size() + 1023) / 1024
		apps = append(apps, model.AppInfo{
			Name:          e.Name(),
			Version:       "unknown",
			Source:        "go",
			InstallSizeKB: size,
			Status:        "Installed",
		})
	}
	return apps, nil
}