Skip to content
Draft
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
22 changes: 18 additions & 4 deletions internal/snapshot/destination.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,29 @@ func ParseSource(ref, home string) (Destination, error) {
return Destination{Kind: KindLocal, Value: resolved}, nil
}

// resolveSourcePath returns the first existing path among: abs as-is, then
// abs+".snapshot", then abs+".zip" (legacy).
// resolveSourcePath returns the first existing file among: abs as-is, then
// abs+".snapshot", then abs+".zip" (legacy). A directory match is remembered but
// skipped in favor of a later file match, so a directory error only surfaces when
// no candidate resolves to an actual file.
func resolveSourcePath(abs string) (string, error) {
withSnapshot := abs + snapshotExt
withZip := abs + legacySnapshotExt
var dirHit string
for _, candidate := range []string{abs, withSnapshot, withZip} {
if _, err := os.Stat(candidate); err == nil {
return candidate, nil
info, err := os.Stat(candidate)
if err != nil {
continue
}
if info.IsDir() {
if dirHit == "" {
dirHit = candidate
}
continue
}
return candidate, nil
}
if dirHit != "" {
return "", fmt.Errorf("%q is a directory, expected a snapshot file", dirHit)
}
return "", fmt.Errorf("snapshot file not found: %q (also tried %q and %q)", abs, withSnapshot, withZip)
}
Expand Down
30 changes: 20 additions & 10 deletions internal/snapshot/destination_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ func TestParseShowable(t *testing.T) {

func TestParseSource(t *testing.T) {
t.Parallel()
wd, err := os.Getwd()
require.NoError(t, err)
// Use a temp dir as home so the test doesn't depend on the real $HOME
// (e.g. under Nix's sandboxed build, $HOME is a non-existent placeholder).
home := t.TempDir()
Expand All @@ -64,6 +62,10 @@ func TestParseSource(t *testing.T) {
require.NoError(t, os.WriteFile(existingLegacyBare+".zip", []byte("data"), 0600))
existingNoExt := filepath.Join(dir, "noext") // no extension, no fallback counterpart either
require.NoError(t, os.WriteFile(existingNoExt, []byte("data"), 0600))
plainDir := filepath.Join(dir, "some-directory")
require.NoError(t, os.Mkdir(plainDir, 0o755))
snapshotExtDir := filepath.Join(dir, "looks-like-a-snapshot.snapshot")
require.NoError(t, os.Mkdir(snapshotExtDir, 0o755))

type testCase struct {
name string
Expand Down Expand Up @@ -126,18 +128,26 @@ func TestParseSource(t *testing.T) {
wantErr: "snapshot file not found",
},
{
name: "relative path resolved via cwd",
input: ".",
wantKind: snapshot.KindLocal,
wantPath: wd,
name: "directory instead of file returns clear error",
input: plainDir,
wantErr: "is a directory",
},
{
name: "directory with .snapshot extension returns clear error",
input: snapshotExtDir,
wantErr: "is a directory",
},
{
name: "relative path resolved via cwd is a directory",
input: ".",
wantErr: "is a directory",
},

// --- tilde expansion ---
{
name: "tilde expands to home",
input: "~/.",
wantKind: snapshot.KindLocal,
wantPath: home,
name: "tilde expands to home which is a directory",
input: "~/.",
wantErr: "is a directory",
},

// --- pod sources ---
Expand Down
19 changes: 19 additions & 0 deletions test/integration/snapshot_load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ func TestSnapshotLoadFileNotFound(t *testing.T) {
assert.Contains(t, stderr, "snapshot file not found")
}

// TestSnapshotLoadPathIsDirectory ensures passing a directory instead of a
// snapshot file fails early with a clear message, instead of surfacing a
// confusing HTTP-layer error once the directory reaches the upload code path.
func TestSnapshotLoadPathIsDirectory(t *testing.T) {
t.Parallel()
ctx := testContext(t)

dir := t.TempDir()
target := filepath.Join(dir, "some-directory")
require.NoError(t, os.Mkdir(target, 0o755))

_, stderr, err := runLstk(t, ctx, t.TempDir(),
testEnvWithHome(t.TempDir(), ""),
"--non-interactive", "snapshot", "load", target,
)
requireExitCode(t, 1, err)
assert.Contains(t, stderr, "is a directory")
}

// --- Docker required ---

func TestSnapshotLoadLocalSuccess(t *testing.T) {
Expand Down
Loading