Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions internal/picker/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,11 @@ func (t theme) statusClusterOn(base lipgloss.Style, st git.Status, loaded bool)
if !loaded {
return f(t.muted, glyphLoading)
}
// A Project's .git can still fail to read, or vanish after the Picker
// opened; git's answer is then as unknown as a timeout.
// A directory with no .git is not a failure: its row shows no marker.
if st.Kind == git.NotRepo {
return ""
}
// A repository whose git call failed or timed out is unknown.
if st.Kind != git.Found {
return f(t.red, glyphUnknown)
}
Expand Down Expand Up @@ -123,6 +126,9 @@ func (t theme) statusClusterOn(base lipgloss.Style, st git.Status, loaded bool)
// statusClusterWidth is the plain (uncoloured) width of statusCluster's
// output, for column alignment.
func statusClusterWidth(st git.Status, loaded bool) int {
if loaded && st.Kind == git.NotRepo {
return 0
}
if !loaded || st.Kind != git.Found {
return 1
}
Expand Down Expand Up @@ -176,9 +182,9 @@ func previewStatusWords(t theme, st git.Status, loaded bool) string {
}
switch st.Kind {
case git.NotRepo:
return t.fg(t.red).Render(glyphUnknown + " git could not read it")
return t.muted_().Render("not a git repo")
case git.Unknown:
return t.fg(t.red).Render(glyphUnknown + " git timed out")
return t.fg(t.red).Render(glyphUnknown + " git could not read it")
}

var parts []string
Expand Down
4 changes: 2 additions & 2 deletions internal/picker/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func keyedStatus(statuses map[string]git.Status) picker.StatusFunc {
func TestModel_Update_StatusResult(t *testing.T) {
statuses := map[string]git.Status{
"/root/work/alpha": {Kind: git.Found, State: git.Dirty},
"/root/work/beta": {Kind: git.NotRepo},
"/root/work/beta": {Kind: git.Unknown},
}
m := picker.NewModel(
[]picker.Row{
Expand Down Expand Up @@ -101,7 +101,7 @@ func TestModel_Update_StatusResult(t *testing.T) {

// Feed the results through Update in reverse order: if results were
// keyed by arrival index rather than by Project path, the last row's
// status (beta, NotRepo) would land on the first row instead.
// status (beta, Unknown) would land on the first row instead.
for i := len(results) - 1; i >= 0; i-- {
next, _ = final.Update(results[i])
final = next.(picker.Model)
Expand Down
53 changes: 53 additions & 0 deletions internal/picker/view_status_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package picker_test

import (
"strings"
"testing"

tea "charm.land/bubbletea/v2"

"github.com/kryft-dev/cdd/internal/git"
"github.com/kryft-dev/cdd/internal/picker"
)

// statusView renders a one-row Picker whose status has landed as st, wide
// enough for the preview and short enough to drop the legend, so any "!" in
// the output comes from the row or the preview.
func statusView(t *testing.T, st git.Status) string {
t.Helper()
rows := []picker.Row{{Project: picker.Project{Dir: "~/work/", Name: "alpha", Path: "/root/work/alpha"}}}
m := picker.NewModel(rows, keyedStatus(map[string]git.Status{"/root/work/alpha": st}), picker.Options{})
next, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 10})
m = next.(picker.Model)
for _, c := range m.Init()().(tea.BatchMsg) {
next, _ = m.Update(c())
m = next.(picker.Model)
}
return plain(m.View().Content)
}

// TestView_NotRepoIsNeutral verifies that a Project with no .git shows no
// "!" and a plain "not a git repo" in the preview, with no branch or sync.
func TestView_NotRepoIsNeutral(t *testing.T) {
out := statusView(t, git.Status{Kind: git.NotRepo})
if strings.Contains(out, "!") {
t.Errorf("view has a !, want none for a non-git Project:\n%s", out)
}
if !strings.Contains(out, "not a git repo") {
t.Errorf("view lacks %q:\n%s", "not a git repo", out)
}
for _, word := range []string{"branch", "sync"} {
if strings.Contains(out, word) {
t.Errorf("view has %q, want it omitted for a non-git Project:\n%s", word, out)
}
}
}

// TestView_UnknownStaysRed verifies that a real git failure keeps the "!"
// in the row and its words in the preview.
func TestView_UnknownStaysRed(t *testing.T) {
out := statusView(t, git.Status{Kind: git.Unknown})
if !strings.Contains(out, "!") || !strings.Contains(out, "git could not read it") {
t.Errorf("view lacks the ! and %q for an Unknown status:\n%s", "git could not read it", out)
}
}
Loading