diff --git a/cmd/harness-sync/main.go b/cmd/harness-sync/main.go index 28516f0..a946d6a 100644 --- a/cmd/harness-sync/main.go +++ b/cmd/harness-sync/main.go @@ -4,13 +4,33 @@ import ( "fmt" "os" + "github.com/lukaszraczylo/harness-sync/internal/adapter" + "github.com/lukaszraczylo/harness-sync/internal/adapters/cagent" + "github.com/lukaszraczylo/harness-sync/internal/adapters/claudecode" + "github.com/lukaszraczylo/harness-sync/internal/adapters/crush" + "github.com/lukaszraczylo/harness-sync/internal/adapters/goose" + "github.com/lukaszraczylo/harness-sync/internal/adapters/kilo" + "github.com/lukaszraczylo/harness-sync/internal/adapters/opencode" + "github.com/lukaszraczylo/harness-sync/internal/adapters/zed" "github.com/lukaszraczylo/harness-sync/internal/cli" ) var version = "dev" func main() { - if err := cli.NewRoot(version).Execute(); err != nil { + reg := adapter.NewRegistry() + reg.Register(claudecode.New()) + reg.Register(crush.New()) + reg.Register(kilo.New()) + reg.Register(opencode.New()) + reg.Register(goose.New()) + reg.Register(cagent.New()) + reg.Register(zed.New()) + + root := cli.NewRoot(version) + root.AddCommand(cli.NewDetect(reg)) + + if err := root.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } diff --git a/internal/cli/detect.go b/internal/cli/detect.go new file mode 100644 index 0000000..8523856 --- /dev/null +++ b/internal/cli/detect.go @@ -0,0 +1,30 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/lukaszraczylo/harness-sync/internal/adapter" +) + +// NewDetect returns the `detect` subcommand. It prints each registered +// adapter with whether the underlying harness is installed on this machine. +func NewDetect(reg *adapter.Registry) *cobra.Command { + return &cobra.Command{ + Use: "detect", + Short: "List adapters and whether each harness is present on this machine", + RunE: func(cmd *cobra.Command, _ []string) error { + for _, a := range reg.All() { + status := "not detected" + if a.Detect() { + status = "detected" + } + if _, err := fmt.Fprintf(cmd.OutOrStdout(), "%-14s %s\n", a.Name(), status); err != nil { + return err + } + } + return nil + }, + } +} diff --git a/internal/cli/detect_test.go b/internal/cli/detect_test.go new file mode 100644 index 0000000..5b17326 --- /dev/null +++ b/internal/cli/detect_test.go @@ -0,0 +1,43 @@ +package cli + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/lukaszraczylo/harness-sync/internal/adapter" + "github.com/lukaszraczylo/harness-sync/internal/canonical" +) + +type detectableAdapter struct { + name string + detect bool +} + +func (d *detectableAdapter) Name() string { return d.name } +func (d *detectableAdapter) Detect() bool { return d.detect } +func (d *detectableAdapter) Render(_ *canonical.Bundle) (*adapter.FileSet, error) { + return adapter.NewFileSet(), nil +} +func (d *detectableAdapter) Import(_ string) (*adapter.ImportResult, error) { + return &adapter.ImportResult{}, nil +} + +func TestDetectCommandPrintsList(t *testing.T) { + reg := adapter.NewRegistry() + reg.Register(&detectableAdapter{name: "yes", detect: true}) + reg.Register(&detectableAdapter{name: "no", detect: false}) + + var buf bytes.Buffer + cmd := NewDetect(reg) + cmd.SetOut(&buf) + require.NoError(t, cmd.Execute()) + + out := buf.String() + assert.Contains(t, out, "yes") + assert.Contains(t, out, "no") + assert.Contains(t, out, "detected") + assert.Contains(t, out, "not detected") +}