From 735885cb291d503c47356a059dfe51462ed96a27 Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 30 Sep 2026 20:41:50 +0200 Subject: [PATCH] CLI: refuse a folder without its parent before any request decrypt creates the folder of a format 3 capsule at step 17, after the release is requested. With a missing parent it failed only then, from the Sink, reported with ERR_INTEGRITY as any failure of the output is. It now checks the parent right after the prelude, with a message of its own and no request. Co-Authored-By: Claude Opus 5.5 --- cmd/datekeys/main.go | 6 ++++++ cmd/datekeys/main_test.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/cmd/datekeys/main.go b/cmd/datekeys/main.go index 9f0ec20..f64a05c 100644 --- a/cmd/datekeys/main.go +++ b/cmd/datekeys/main.go @@ -25,6 +25,7 @@ import ( "fmt" "io" "os" + "path/filepath" "runtime" "strings" "time" @@ -283,6 +284,11 @@ func decrypt(args []string, stdout, stderr io.Writer, now func() time.Time) erro if err := checkNew(*out); err != nil { return err } + // The folder is created at step 17, after the release is requested: + // its parent must be a folder before then. + if info, err := os.Stat(filepath.Dir(*out)); err != nil || !info.IsDir() { + return fmt.Errorf("decrypt: %s cannot be created: %s is not a folder", *out, filepath.Dir(*out)) + } opts.Sink = &dirSink{dir: *out} if opened, err = capsule.Open(ctx, nil, src, opts); err != nil { return err diff --git a/cmd/datekeys/main_test.go b/cmd/datekeys/main_test.go index b032270..1b49bd9 100644 --- a/cmd/datekeys/main_test.go +++ b/cmd/datekeys/main_test.go @@ -358,6 +358,12 @@ func TestDecryptFormat3LeavesNothing(t *testing.T) { if _, err := os.Lstat(out); !errors.Is(err, os.ErrNotExist) { t.Fatalf("the folder of a failed capsule remains: %v", err) } + // A folder whose parent does not exist fails before any request: the + // relay cannot be reached. + missing := filepath.Join(dir, "missing", "out") + if _, _, err := cli(t, later, "decrypt", "-in", dkc, "-out", missing, "-relay", "http://127.0.0.1:1"); err == nil || !strings.Contains(err.Error(), "is not a folder") { + t.Fatalf("a folder without its parent: %v", err) + } stdout, stderr, err := cli(t, later, "decrypt", "-in", note, "-out", out, "-relay", relay(t)) if err != nil || !strings.Contains(stdout, "│ Solo un comentario") || !strings.Contains(stderr, "no files") { t.Fatalf("%v\n%s\n%s", err, stdout, stderr)