Skip to content

Commit eb704f8

Browse files
committed
Distinguish missing playlist file from invalid format
A missing or unreadable path now fails with "Could not open playlist file: no such file" instead of the format-validation message, which was misleading for a mistyped path. Extracted openPlaylist as the shared resolve-check-sniff entry point for the print and build commands.
1 parent cae10d8 commit eb704f8

2 files changed

Lines changed: 53 additions & 6 deletions

File tree

cmd/plt.go

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package cmd
1616

1717
import (
1818
"encoding/json"
19+
"errors"
1920
"fmt"
2021
"io"
2122
"os"
@@ -49,12 +50,7 @@ offline; no media is downloaded.`,
4950
}
5051

5152
func runPltPrint(_ *coral.Command, args []string) {
52-
path := resolveInputPath(args[0])
53-
54-
arc, err := sniffPlaylist(path)
55-
if err != nil {
56-
log.Fatal().Err(err).Msgf("Not a valid purple playlist: %s", path)
57-
}
53+
arc := openPlaylist(args[0])
5854
defer func() { _ = arc.Close() }()
5955

6056
if arc.schemaVersion != verifiedSchemaVersion {
@@ -93,6 +89,35 @@ func resolveInputPath(p string) string {
9389
return p
9490
}
9591

92+
// checkPlaylistFile reports a clear, path-focused error when the file is
93+
// missing or unreadable, keeping it distinct from a format-validation failure.
94+
func checkPlaylistFile(path string) error {
95+
if _, err := os.Stat(path); err != nil {
96+
if errors.Is(err, os.ErrNotExist) {
97+
return fmt.Errorf("no such file: %s", path)
98+
}
99+
return fmt.Errorf("could not access %s: %w", path, err)
100+
}
101+
return nil
102+
}
103+
104+
// openPlaylist resolves the argument, fails fast with a distinct message when
105+
// the file is missing, then sniffs and returns the validated archive. Shared
106+
// by the print and build commands.
107+
func openPlaylist(rawPath string) *archive {
108+
path := resolveInputPath(rawPath)
109+
110+
if err := checkPlaylistFile(path); err != nil {
111+
log.Fatal().Err(err).Msg("Could not open playlist file")
112+
}
113+
114+
arc, err := sniffPlaylist(path)
115+
if err != nil {
116+
log.Fatal().Err(err).Msgf("Not a valid purple playlist: %s", path)
117+
}
118+
return arc
119+
}
120+
96121
// printView is the offline summary rendered by plt print, shared by the text
97122
// and JSON outputs so both show the same data.
98123
type printView struct {

cmd/plt_print_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package cmd
1717
import (
1818
"encoding/json"
1919
"math"
20+
"os"
2021
"path/filepath"
2122
"strings"
2223
"testing"
@@ -49,6 +50,27 @@ func TestResolveInputPath(t *testing.T) {
4950
})
5051
}
5152

53+
func TestCheckPlaylistFile(t *testing.T) {
54+
dir := t.TempDir()
55+
56+
present := filepath.Join(dir, "present.playlist")
57+
if err := os.WriteFile(present, []byte("data"), 0o600); err != nil {
58+
t.Fatalf("write fixture: %v", err)
59+
}
60+
if err := checkPlaylistFile(present); err != nil {
61+
t.Errorf("existing file should pass, got: %v", err)
62+
}
63+
64+
missing := filepath.Join(dir, "missing.playlist")
65+
err := checkPlaylistFile(missing)
66+
if err == nil {
67+
t.Fatal("missing file should error")
68+
}
69+
if !strings.Contains(err.Error(), "no such file") {
70+
t.Errorf("error %q should mention 'no such file'", err.Error())
71+
}
72+
}
73+
5274
func TestDescribeSource(t *testing.T) {
5375
cases := []struct {
5476
name string

0 commit comments

Comments
 (0)