Files
beads/cmd/bd/history.go
quartz 94581ab233 feat(storage): add VersionedStorage interface with history/diff/branch operations
Extends Storage interface with Dolt-specific version control capabilities:

- New VersionedStorage interface in storage/versioned.go with:
  - History queries: History(), AsOf(), Diff()
  - Branch operations: Branch(), Merge(), CurrentBranch(), ListBranches()
  - Commit operations: Commit(), GetCurrentCommit()
  - Conflict resolution: GetConflicts(), ResolveConflicts()
  - Helper types: HistoryEntry, DiffEntry, Conflict

- DoltStore implements VersionedStorage interface

- New CLI commands:
  - bd history <id> - Show issue version history
  - bd diff <from> <to> - Show changes between commits/branches
  - bd branch [name] - List or create branches
  - bd vc merge <branch> - Merge branch to current
  - bd vc commit -m <msg> - Create a commit
  - bd vc status - Show current branch/commit

- Added --as-of flag to bd show for time-travel queries

- IsVersioned() helper for graceful SQLite backend detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 01:55:16 -08:00

96 lines
2.4 KiB
Go

package main
import (
"fmt"
"github.com/spf13/cobra"
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/ui"
)
var (
historyLimit int
)
var historyCmd = &cobra.Command{
Use: "history <id>",
GroupID: "views",
Short: "Show version history for an issue (requires Dolt backend)",
Long: `Show the complete version history of an issue, including all commits
where the issue was modified.
This command requires the Dolt storage backend. If you're using SQLite,
you'll see an error message suggesting to use Dolt for versioning features.
Examples:
bd history bd-123 # Show all history for issue bd-123
bd history bd-123 --limit 5 # Show last 5 changes`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ctx := rootCtx
issueID := args[0]
// Check if storage supports versioning
vs, ok := storage.AsVersioned(store)
if !ok {
FatalErrorRespectJSON("history requires Dolt backend (current backend does not support versioning)")
}
// Get issue history
history, err := vs.History(ctx, issueID)
if err != nil {
FatalErrorRespectJSON("failed to get history: %v", err)
}
if len(history) == 0 {
fmt.Printf("No history found for issue %s\n", issueID)
return
}
// Apply limit if specified
if historyLimit > 0 && historyLimit < len(history) {
history = history[:historyLimit]
}
if jsonOutput {
outputJSON(history)
return
}
// Display history in human-readable format
fmt.Printf("\n%s History for %s (%d entries)\n\n",
ui.RenderAccent("📜"), issueID, len(history))
for i, entry := range history {
// Commit info line
fmt.Printf("%s %s\n",
ui.RenderMuted(entry.CommitHash[:8]),
ui.RenderMuted(entry.CommitDate.Format("2006-01-02 15:04:05")))
fmt.Printf(" Author: %s\n", entry.Committer)
if entry.Issue != nil {
// Show issue state at this commit
statusIcon := ui.GetStatusIcon(string(entry.Issue.Status))
fmt.Printf(" %s %s: %s [P%d - %s]\n",
statusIcon,
entry.Issue.ID,
entry.Issue.Title,
entry.Issue.Priority,
entry.Issue.Status)
}
// Separator between entries
if i < len(history)-1 {
fmt.Println()
}
}
fmt.Println()
},
}
func init() {
historyCmd.Flags().IntVar(&historyLimit, "limit", 0, "Limit number of history entries (0 = all)")
historyCmd.ValidArgsFunction = issueIDCompletion
rootCmd.AddCommand(historyCmd)
}