74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
package agent
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
// EnsurePathContainsSiblings prepends sherlock-adjacent directories to
|
|
// $PATH if they're not already there, then re-sets PATH in the
|
|
// current process's environment so syscall.Exec children inherit it.
|
|
//
|
|
// This is sherlock's "no manual setup" guarantee: dropping a binary
|
|
// at `go install`'s default destination (~/go/bin) is enough; the
|
|
// operator never has to edit a shell rc.
|
|
//
|
|
// Dirs added (in order, deduped):
|
|
//
|
|
// 1. Directory of os.Executable() — wherever this sherlock binary
|
|
// lives, all sibling MCPs live too if installed via `go install`.
|
|
// 2. $GOBIN.
|
|
// 3. $GOPATH/bin (resolved via `go env` defaults).
|
|
// 4. $HOME/go/bin (the canonical fallback when neither is set).
|
|
//
|
|
// Idempotent: re-runs are no-ops because each candidate is checked
|
|
// for presence in PATH before being prepended.
|
|
func EnsurePathContainsSiblings() {
|
|
current := os.Getenv("PATH")
|
|
sep := string(os.PathListSeparator)
|
|
existing := strings.Split(current, sep)
|
|
|
|
var toAdd []string
|
|
add := func(dir string) {
|
|
if dir == "" {
|
|
return
|
|
}
|
|
abs, err := filepath.Abs(dir)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if slices.Contains(existing, abs) || slices.Contains(toAdd, abs) {
|
|
return
|
|
}
|
|
if fi, err := os.Stat(abs); err != nil || !fi.IsDir() {
|
|
return
|
|
}
|
|
toAdd = append(toAdd, abs)
|
|
}
|
|
|
|
if exe, err := os.Executable(); err == nil {
|
|
if real, err := filepath.EvalSymlinks(exe); err == nil {
|
|
exe = real
|
|
}
|
|
add(filepath.Dir(exe))
|
|
}
|
|
add(os.Getenv("GOBIN"))
|
|
if gopath := os.Getenv("GOPATH"); gopath != "" {
|
|
// GOPATH can be a list on some setups; canonical is one entry.
|
|
for _, p := range strings.Split(gopath, sep) {
|
|
add(filepath.Join(p, "bin"))
|
|
}
|
|
}
|
|
if home, err := os.UserHomeDir(); err == nil {
|
|
add(filepath.Join(home, "go", "bin"))
|
|
}
|
|
|
|
if len(toAdd) == 0 {
|
|
return
|
|
}
|
|
updated := strings.Join(append(toAdd, existing...), sep)
|
|
_ = os.Setenv("PATH", updated)
|
|
}
|