diff --git a/internal/store/store.go b/internal/store/store.go index 7348f23..8d52c91 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -54,6 +54,11 @@ func ResolveBoard(flag string) (string, error) { if name == "" { name = os.Getenv("SHEPHERD_BOARD") } + // "default" is the label `boards` advertises for the empty-named default + // board; accept it back so a name read from that listing round-trips. + if name == "default" { + return "", nil + } if name != "" && !boardRE.MatchString(name) { return "", fmt.Errorf("invalid board name %q (use letters, digits, . _ -)", name) } @@ -185,6 +190,9 @@ func CreateBoard(name string) error { if err := ValidBoard(name); err != nil { return err } + if name == "default" { + return fmt.Errorf("board %q is reserved for the default board", name) + } p := TodoPathFor(name) if fileExists(p) { return fmt.Errorf("board %q already exists", name) diff --git a/internal/store/store_test.go b/internal/store/store_test.go index 6f3120b..fefe126 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -282,6 +282,13 @@ func TestResolveBoard(t *testing.T) { if got, err := ResolveBoard(""); err != nil || got != "" { t.Fatalf("empty -> default: %q %v", got, err) } + // "default" (the name `boards` advertises) round-trips to the empty board. + if got, err := ResolveBoard("default"); err != nil || got != "" { + t.Fatalf(`"default" -> empty: %q %v`, got, err) + } + if err := CreateBoard("default"); err == nil { + t.Fatal(`"default" should be reserved`) + } if _, err := ResolveBoard("../evil"); err == nil { t.Fatal("traversal via flag not rejected") }