From 4ce4bda94073d7d447b670109cbf7d34c4c14b07 Mon Sep 17 00:00:00 2001 From: Andrew Nesbitt Date: Tue, 3 Mar 2026 11:48:47 +0000 Subject: [PATCH] Respect RequireCLI option for explicit manager selection detectExplicit was hardcoding requireCLI=true, ignoring the DetectOptions.RequireCLI field. This caused failures when callers only needed template-based operations (like path lookup) that don't require the CLI binary to be installed. --- detector.go | 6 +++--- detector_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 detector_test.go diff --git a/detector.go b/detector.go index e39056f..be6c1af 100644 --- a/detector.go +++ b/detector.go @@ -52,7 +52,7 @@ func (d *Detector) sortDefinitions() { func (d *Detector) Detect(dir string, opts DetectOptions) (Manager, error) { if opts.Manager != "" { - return d.detectExplicit(dir, opts.Manager) + return d.detectExplicit(dir, opts.Manager, opts.RequireCLI) } files, err := os.ReadDir(dir) @@ -100,10 +100,10 @@ func (d *Detector) Detect(dir string, opts DetectOptions) (Manager, error) { return nil, ErrNoManifest{Dir: dir} } -func (d *Detector) detectExplicit(dir, managerName string) (Manager, error) { +func (d *Detector) detectExplicit(dir, managerName string, requireCLI bool) (Manager, error) { for _, def := range d.definitions { if def.Name == managerName { - return d.buildManager(def, dir, nil, true) + return d.buildManager(def, dir, nil, requireCLI) } } return nil, ErrNoManifest{Dir: dir} diff --git a/detector_test.go b/detector_test.go new file mode 100644 index 0000000..d0bfc84 --- /dev/null +++ b/detector_test.go @@ -0,0 +1,54 @@ +package managers + +import ( + "testing" + + "github.com/git-pkgs/managers/definitions" +) + +func TestDetectExplicit_RequireCLI(t *testing.T) { + translator := NewTranslator() + runner := NewMockRunner() + detector := NewDetector(translator, runner) + + def := &definitions.Definition{ + Name: "fakepkg", + Binary: "binary-that-does-not-exist", + } + detector.Register(def) + + t.Run("require CLI fails when binary missing", func(t *testing.T) { + _, err := detector.Detect("/tmp", DetectOptions{ + Manager: "fakepkg", + RequireCLI: true, + }) + if err == nil { + t.Fatal("expected error when binary not found") + } + var cliErr ErrCLINotFound + if !isErrCLINotFound(err, &cliErr) { + t.Fatalf("expected ErrCLINotFound, got: %v", err) + } + }) + + t.Run("no CLI required succeeds without binary", func(t *testing.T) { + mgr, err := detector.Detect("/tmp", DetectOptions{ + Manager: "fakepkg", + RequireCLI: false, + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if mgr == nil { + t.Fatal("expected manager, got nil") + } + }) +} + +func isErrCLINotFound(err error, target *ErrCLINotFound) bool { + e, ok := err.(ErrCLINotFound) + if ok { + *target = e + } + return ok +}