Files
snack/detect/detect.go
2026-02-28 06:18:45 +00:00

76 lines
1.8 KiB
Go

// Package detect provides auto-detection of the system's available package manager.
package detect
import (
"os/exec"
"sync"
"github.com/gogrlx/snack"
)
var (
defaultOnce sync.Once
defaultMgr snack.Manager
defaultErr error
)
// Default returns the first available package manager on the system.
// The result is cached after the first call.
// Returns ErrManagerNotFound if no supported manager is detected.
func Default() (snack.Manager, error) {
defaultOnce.Do(func() {
for _, fn := range candidates() {
m := fn()
if m.Available() {
defaultMgr = m
return
}
}
defaultErr = snack.ErrManagerNotFound
})
return defaultMgr, defaultErr
}
// Reset clears the cached result of Default(), forcing re-detection on the
// next call. This is intended for use in tests or dynamic environments where
// the available package managers may change.
// Reset is not safe to call concurrently with Default().
func Reset() {
defaultOnce = sync.Once{}
defaultMgr = nil
defaultErr = nil
}
// All returns all available package managers on the system.
func All() []snack.Manager {
var out []snack.Manager
for _, fn := range candidates() {
m := fn()
if m.Available() {
out = append(out, m)
}
}
return out
}
// ByName returns a specific manager by name, regardless of availability.
// Returns ErrManagerNotFound if the name is not recognized.
func ByName(name string) (snack.Manager, error) {
for _, fn := range allManagers() {
m := fn()
if m.Name() == name {
return m, nil
}
}
return nil, snack.ErrManagerNotFound
}
// managerFactory is a function that returns a new Manager instance.
type managerFactory func() snack.Manager
// HasBinary reports whether a binary is available in PATH.
func HasBinary(name string) bool {
_, err := exec.LookPath(name)
return err == nil
}