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>
This commit is contained in:
quartz
2026-01-17 01:54:55 -08:00
committed by gastown/crew/dennis
parent a7cd9136d8
commit 94581ab233
11 changed files with 1031 additions and 10 deletions

View File

@@ -288,8 +288,9 @@ type IssueDiff struct {
ToDescription string
}
// GetConflicts returns any merge conflicts in the current state
func (s *DoltStore) GetConflicts(ctx context.Context) ([]*Conflict, error) {
// GetInternalConflicts returns any merge conflicts in the current state (internal format).
// For the public interface, use GetConflicts which returns storage.Conflict.
func (s *DoltStore) GetInternalConflicts(ctx context.Context) ([]*TableConflict, error) {
rows, err := s.db.QueryContext(ctx, `
SELECT table_name, num_conflicts FROM dolt_conflicts
`)
@@ -298,9 +299,9 @@ func (s *DoltStore) GetConflicts(ctx context.Context) ([]*Conflict, error) {
}
defer rows.Close()
var conflicts []*Conflict
var conflicts []*TableConflict
for rows.Next() {
var c Conflict
var c TableConflict
if err := rows.Scan(&c.TableName, &c.NumConflicts); err != nil {
return nil, fmt.Errorf("failed to scan conflict: %w", err)
}
@@ -310,8 +311,8 @@ func (s *DoltStore) GetConflicts(ctx context.Context) ([]*Conflict, error) {
return conflicts, rows.Err()
}
// Conflict represents a merge conflict
type Conflict struct {
// TableConflict represents a Dolt table-level merge conflict (internal representation).
type TableConflict struct {
TableName string
NumConflicts int
}