Add --show-all-paths flag to bd dep tree

Implements bd-9: Allow users to view all paths through diamond dependencies
without deduplication. Useful for debugging complex dependency structures.

Changes:
- Added --show-all-paths flag to bd dep tree command
- Updated GetDependencyTree interface to accept showAllPaths parameter
- Modified deduplication logic to be conditional on flag
- Updated tests to pass new parameter

Amp-Thread-ID: https://ampcode.com/threads/T-43807dd5-8732-49ad-a839-cdb5dae70c35
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-18 11:52:57 -07:00
parent f44fc34761
commit d2e34b863b
5 changed files with 26 additions and 20 deletions

View File

@@ -450,10 +450,11 @@ func (s *SQLiteStorage) GetAllDependencyRecords(ctx context.Context) (map[string
return depsMap, nil
}
// GetDependencyTree returns the full dependency tree with deduplication
// When multiple paths lead to the same node (diamond dependencies), the node
// appears only once at its shallowest depth in the tree.
func (s *SQLiteStorage) GetDependencyTree(ctx context.Context, issueID string, maxDepth int) ([]*types.TreeNode, error) {
// GetDependencyTree returns the full dependency tree with optional deduplication
// When showAllPaths is false (default), nodes appearing via multiple paths (diamond dependencies)
// appear only once at their shallowest depth in the tree.
// When showAllPaths is true, all paths are shown with duplicate nodes at different depths.
func (s *SQLiteStorage) GetDependencyTree(ctx context.Context, issueID string, maxDepth int, showAllPaths bool) ([]*types.TreeNode, error) {
if maxDepth <= 0 {
maxDepth = 50
}
@@ -542,17 +543,20 @@ func (s *SQLiteStorage) GetDependencyTree(ctx context.Context, issueID string, m
node.Truncated = node.Depth == maxDepth
// Deduplicate: only include a node the first time we see it (shallowest depth)
// Since we ORDER BY depth, priority, id - the first occurrence is at minimum depth
if prevDepth, exists := seen[node.ID]; exists {
// We've seen this node before at depth prevDepth
// Skip this duplicate occurrence
_ = prevDepth // Avoid unused variable warning
continue
}
// Deduplicate only if showAllPaths is false
if !showAllPaths {
// Only include a node the first time we see it (shallowest depth)
// Since we ORDER BY depth, priority, id - the first occurrence is at minimum depth
if prevDepth, exists := seen[node.ID]; exists {
// We've seen this node before at depth prevDepth
// Skip this duplicate occurrence
_ = prevDepth // Avoid unused variable warning
continue
}
// Mark this node as seen at this depth
seen[node.ID] = node.Depth
// Mark this node as seen at this depth
seen[node.ID] = node.Depth
}
nodes = append(nodes, &node)
}

View File

@@ -206,7 +206,7 @@ func TestGetDependencyTree(t *testing.T) {
store.AddDependency(ctx, &types.Dependency{IssueID: issue3.ID, DependsOnID: issue2.ID, Type: types.DepBlocks}, "test-user")
// Get tree starting from issue3
tree, err := store.GetDependencyTree(ctx, issue3.ID, 10)
tree, err := store.GetDependencyTree(ctx, issue3.ID, 10, false)
if err != nil {
t.Fatalf("GetDependencyTree failed: %v", err)
}