Add repo-detail panel and /api/repo endpoint
New <repo-detail> component listens for repo:select and shows a repo's remotes, local branches (current + upstream), and recent commits. Backed by GET /api/repo (restricted to indexed repos) and read-only git readers LocalBranches/RecentCommits/RemoteDetails via repos.BuildDetail. <repo-list> highlights the selection; page docks the two panels left/right. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package repos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gitmanager/internal/git"
|
||||
)
|
||||
|
||||
// Detail is the enriched view of a single repository shown in the detail panel.
|
||||
// It embeds the cached State and adds data fetched on demand via the git
|
||||
// boundary (all read-only — AGENT.md §1.3).
|
||||
type Detail struct {
|
||||
State
|
||||
Branches []git.Branch `json:"branches"`
|
||||
Commits []git.Commit `json:"commits"`
|
||||
RemoteDetails []git.Remote `json:"remoteDetails"`
|
||||
}
|
||||
|
||||
// Get returns the cached State for a repo path, or false if it is not indexed.
|
||||
func (i *Index) Get(path string) (State, bool) {
|
||||
i.mu.RLock()
|
||||
defer i.mu.RUnlock()
|
||||
s, ok := i.byKey[path]
|
||||
return s, ok
|
||||
}
|
||||
|
||||
// BuildDetail enriches a cached State with branches, recent commits, and remote
|
||||
// URLs. Errors on the enriching calls are non-fatal: whatever succeeds is
|
||||
// returned, and the partial failure is recorded on Detail.Error.
|
||||
func BuildDetail(ctx context.Context, g *git.CLI, base State) Detail {
|
||||
ctx, cancel := context.WithTimeout(ctx, 20*time.Second)
|
||||
defer cancel()
|
||||
|
||||
d := Detail{State: base}
|
||||
|
||||
if branches, err := g.LocalBranches(ctx, base.Path); err == nil {
|
||||
d.Branches = branches
|
||||
} else {
|
||||
d.Error = err.Error()
|
||||
}
|
||||
|
||||
if commits, err := g.RecentCommits(ctx, base.Path, 20); err == nil {
|
||||
d.Commits = commits
|
||||
} else if d.Error == "" {
|
||||
d.Error = err.Error()
|
||||
}
|
||||
|
||||
if remotes, err := g.RemoteDetails(ctx, base.Path); err == nil {
|
||||
d.RemoteDetails = remotes
|
||||
} else if d.Error == "" {
|
||||
d.Error = err.Error()
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
Reference in New Issue
Block a user