fix(orphans): honor --db flag for cross-repo orphan detection (#1200)
* fix(orphans): honor --db flag for cross-repo orphan detection Problem: - `bd orphans --db /path` ignored the --db flag entirely - FindOrphanedIssues() hardcoded local .beads/ directory Solution: - Introduce IssueProvider interface for abstract issue lookup - Add StorageProvider adapter wrapping Storage instances - Update FindOrphanedIssues to accept provider instead of path - Wire orphans command to create provider from --db flag Closes: steveyegge/beads#1196 * test(orphans): add cross-repo and provider tests for --db flag fix - Add TestFindOrphanedIssues_WithMockProvider (table-driven, UT-01 through UT-09) - Add TestFindOrphanedIssues_CrossRepo (validates --db flag honored) - Add TestFindOrphanedIssues_LocalProvider (backward compat RT-01) - Add TestFindOrphanedIssues_ProviderError (error handling UT-07) - Add TestFindOrphanedIssues_IntegrationCrossRepo (IT-02 full) - Add TestLocalProvider_* unit tests Coverage for IssueProvider interface and cross-repo orphan detection. * docs: add bd orphans command to CLI reference Document the orphan detection command including the cross-repo workflow enabled by the --db flag fix in this PR.
This commit is contained in:
committed by
GitHub
parent
a0dac11e42
commit
c11fa799be
59
internal/storage/provider.go
Normal file
59
internal/storage/provider.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// Package storage defines the interface for issue storage backends.
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
)
|
||||
|
||||
// StorageProvider wraps a Storage interface to provide IssueProvider functionality.
|
||||
// This adapts the full Storage interface to the minimal IssueProvider interface
|
||||
// needed for orphan detection.
|
||||
type StorageProvider struct {
|
||||
storage Storage
|
||||
prefix string // Cached prefix (empty = not cached yet)
|
||||
}
|
||||
|
||||
// NewStorageProvider creates an IssueProvider backed by a Storage instance.
|
||||
func NewStorageProvider(s Storage) *StorageProvider {
|
||||
return &StorageProvider{storage: s}
|
||||
}
|
||||
|
||||
// GetOpenIssues returns issues that are open or in_progress.
|
||||
func (p *StorageProvider) GetOpenIssues(ctx context.Context) ([]*types.Issue, error) {
|
||||
// Use SearchIssues with empty query and status filter
|
||||
// We need to search for both "open" and "in_progress" issues
|
||||
openStatus := types.StatusOpen
|
||||
openIssues, err := p.storage.SearchIssues(ctx, "", types.IssueFilter{Status: &openStatus})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inProgressStatus := types.StatusInProgress
|
||||
inProgressIssues, err := p.storage.SearchIssues(ctx, "", types.IssueFilter{Status: &inProgressStatus})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Combine results
|
||||
return append(openIssues, inProgressIssues...), nil
|
||||
}
|
||||
|
||||
// GetIssuePrefix returns the configured issue prefix.
|
||||
func (p *StorageProvider) GetIssuePrefix() string {
|
||||
// Cache the prefix on first access
|
||||
if p.prefix == "" {
|
||||
ctx := context.Background()
|
||||
prefix, err := p.storage.GetConfig(ctx, "issue_prefix")
|
||||
if err != nil || prefix == "" {
|
||||
p.prefix = "bd" // default
|
||||
} else {
|
||||
p.prefix = prefix
|
||||
}
|
||||
}
|
||||
return p.prefix
|
||||
}
|
||||
|
||||
// Ensure StorageProvider implements types.IssueProvider
|
||||
var _ types.IssueProvider = (*StorageProvider)(nil)
|
||||
Reference in New Issue
Block a user