fix(tui): allow empty json smoke
This commit is contained in:
parent
401bda3ec1
commit
f760523ca0
@ -1083,23 +1083,35 @@ func (a *App) runTUI(ctx context.Context, args []string) error {
|
||||
rt, err = a.openLocalRuntimeReadOnly(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
if !interactive && errors.Is(err, os.ErrNotExist) {
|
||||
cfg := config.Default()
|
||||
if cfgErr := cfg.Normalize(); cfgErr != nil {
|
||||
return cfgErr
|
||||
}
|
||||
sort, sortErr := resolveTUISort(*sortMode, cfg)
|
||||
if sortErr != nil {
|
||||
return sortErr
|
||||
}
|
||||
return a.writeOutput("tui", emptyClusterBrowserPayload(ctx, cfg, cfg.DBPath, sort, minSize, limit, *hideClosed), true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer rt.Store.Close()
|
||||
|
||||
repo, inferred, err := a.resolveOptionalRepository(ctx, rt, fs.Args())
|
||||
if err != nil {
|
||||
if !interactive && len(fs.Args()) == 0 && strings.Contains(err.Error(), "no local repositories found") {
|
||||
sort, sortErr := resolveTUISort(*sortMode, rt.Config)
|
||||
if sortErr != nil {
|
||||
return sortErr
|
||||
}
|
||||
return a.writeOutput("tui", emptyClusterBrowserPayload(ctx, rt.Config, rt.SourceDBPath, sort, minSize, limit, *hideClosed), true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
sort := strings.TrimSpace(*sortMode)
|
||||
if sort == "" {
|
||||
sort = strings.TrimSpace(rt.Config.TUI.DefaultSort)
|
||||
}
|
||||
if sort == "" {
|
||||
sort = "size"
|
||||
}
|
||||
if sort != "recent" && sort != "oldest" && sort != "size" {
|
||||
return usageErr(fmt.Errorf("unsupported sort %q", sort))
|
||||
sort, err := resolveTUISort(*sortMode, rt.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
showClosed := !*hideClosed || *includeClosed
|
||||
|
||||
@ -1154,6 +1166,38 @@ func (a *App) runTUI(ctx context.Context, args []string) error {
|
||||
return a.runInteractiveTUI(ctx, rt.Store, repo.ID, payload)
|
||||
}
|
||||
|
||||
func resolveTUISort(raw string, cfg config.Config) (string, error) {
|
||||
sort := strings.TrimSpace(raw)
|
||||
if sort == "" {
|
||||
sort = strings.TrimSpace(cfg.TUI.DefaultSort)
|
||||
}
|
||||
if sort == "" {
|
||||
sort = "size"
|
||||
}
|
||||
if sort != "recent" && sort != "oldest" && sort != "size" {
|
||||
return "", usageErr(fmt.Errorf("unsupported sort %q", sort))
|
||||
}
|
||||
return sort, nil
|
||||
}
|
||||
|
||||
func emptyClusterBrowserPayload(ctx context.Context, cfg config.Config, sourceDBPath, sort string, minSize, limit int, hideClosed bool) clusterBrowserPayload {
|
||||
if strings.TrimSpace(sourceDBPath) == "" {
|
||||
sourceDBPath = cfg.DBPath
|
||||
}
|
||||
return clusterBrowserPayload{
|
||||
Mode: "cluster-browser",
|
||||
DBSource: databaseSourceKind(sourceDBPath),
|
||||
DBLocation: databaseSourceLocation(ctx, sourceDBPath),
|
||||
Sort: sort,
|
||||
MinSize: minSize,
|
||||
Limit: limit,
|
||||
HideClosed: hideClosed,
|
||||
EmbedModel: cfg.OpenAI.EmbedModel,
|
||||
EmbeddingBasis: cfg.EmbeddingBasis,
|
||||
Clusters: []store.ClusterSummary{},
|
||||
}
|
||||
}
|
||||
|
||||
func databaseSourceKind(dbPath string) string {
|
||||
if _, ok := portableStoreRoot(dbPath); ok {
|
||||
return "remote"
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -1022,6 +1023,60 @@ func TestTUIInfersRepository(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTUIJSONUsesDefaultsWhenConfigMissing(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dir := t.TempDir()
|
||||
configPath := filepath.Join(dir, "missing.toml")
|
||||
t.Setenv("GITCRAWL_DB_PATH", filepath.Join(dir, "missing.db"))
|
||||
|
||||
run := New()
|
||||
var stdout bytes.Buffer
|
||||
run.Stdout = &stdout
|
||||
if err := run.Run(ctx, []string{"--config", configPath, "tui", "--json"}); err != nil {
|
||||
t.Fatalf("tui: %v", err)
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(stdout.Bytes(), &payload); err != nil {
|
||||
t.Fatalf("decode tui payload: %v\n%s", err, stdout.String())
|
||||
}
|
||||
if payload["mode"] != "cluster-browser" {
|
||||
t.Fatalf("mode = %#v", payload["mode"])
|
||||
}
|
||||
clusters, ok := payload["clusters"].([]any)
|
||||
if !ok || len(clusters) != 0 {
|
||||
t.Fatalf("clusters = %#v", payload["clusters"])
|
||||
}
|
||||
if _, err := os.Stat(configPath); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("config file should not be created, stat err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTUIJSONHandlesEmptyStoreWithoutRepository(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dir := t.TempDir()
|
||||
configPath := filepath.Join(dir, "config.toml")
|
||||
dbPath := filepath.Join(dir, "gitcrawl.db")
|
||||
app := New()
|
||||
if err := app.Run(ctx, []string{"--config", configPath, "init", "--db", dbPath}); err != nil {
|
||||
t.Fatalf("init: %v", err)
|
||||
}
|
||||
|
||||
run := New()
|
||||
var stdout bytes.Buffer
|
||||
run.Stdout = &stdout
|
||||
if err := run.Run(ctx, []string{"--config", configPath, "tui", "--json"}); err != nil {
|
||||
t.Fatalf("tui: %v", err)
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(stdout.Bytes(), &payload); err != nil {
|
||||
t.Fatalf("decode tui payload: %v\n%s", err, stdout.String())
|
||||
}
|
||||
clusters, ok := payload["clusters"].([]any)
|
||||
if !ok || len(clusters) != 0 {
|
||||
t.Fatalf("clusters = %#v", payload["clusters"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestTUIRequiresInteractiveTerminalByDefault(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dir := t.TempDir()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user