A virtual jailed shell environment for Go apps backed by an io/fs#FS.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(cat): accept -u no-op and surface real errno

Adds POSIX -u (write-without-delay) as a documented no-op
since Go writes are already unbuffered. Replaces hardcoded
"No such file or directory" diagnostics with the real
underlying error so EISDIR/EACCES are reported correctly.
Adds tests for -u, -- terminator with dash-prefixed names,
double-dash stdin consumption, and directory diagnostics.

Refs: docs/posix2018/CONFORMANCE.md
Assisted-by: Claude Opus 4.7 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>

+43 -4
+6 -3
command/internal/cat/cat.go
··· 37 37 fmt.Fprint(stderr, "Usage: cat [OPTION]... [FILE]...\n") 38 38 fmt.Fprint(stderr, "Concatenate FILE(s) to standard output.\n\n") 39 39 fmt.Fprint(stderr, " -n, --number number all output lines\n") 40 + fmt.Fprint(stderr, " -u (ignored; Go writes are unbuffered)\n") 40 41 fmt.Fprint(stderr, " --help display this help and exit\n") 41 42 } 42 43 set.SetUsage(usage) 43 44 44 45 number := set.BoolLong("number", 'n', "number all output lines") 46 + _ = set.Bool('u', "(ignored; Go writes are unbuffered)") 45 47 help := set.BoolLong("help", 0, "display this help and exit") 46 48 47 49 if err := set.Getopt(append([]string{"cat"}, args...), nil); err != nil { ··· 91 93 return io.ReadAll(ec.Stdin) 92 94 } 93 95 if ec.FS == nil { 94 - fmt.Fprintf(stderr, "cat: %s: No such file or directory\n", file) 95 - return nil, errors.New("no filesystem") 96 + err := errors.New("no filesystem") 97 + fmt.Fprintf(stderr, "cat: %s: %s\n", file, err) 98 + return nil, err 96 99 } 97 100 full := resolvePath(ec, file) 98 101 f, err := ec.FS.Open(full) 99 102 if err != nil { 100 - fmt.Fprintf(stderr, "cat: %s: No such file or directory\n", file) 103 + fmt.Fprintf(stderr, "cat: %s: %s\n", file, err) 101 104 return nil, err 102 105 } 103 106 defer f.Close()
+37 -1
command/internal/cat/cat_test.go
··· 27 27 write("two.txt", []byte("world\n")) 28 28 write("noeol.txt", []byte("noeol")) 29 29 write("multi.txt", []byte("one\ntwo\nthree\n")) 30 + write("-file", []byte("dashfile\n")) 31 + if err := fs.MkdirAll("subdir", 0o755); err != nil { 32 + t.Fatal(err) 33 + } 30 34 return fs 31 35 } 32 36 ··· 122 126 name: "missing file reports error and continues", 123 127 args: []string{"nope.txt", "hello.txt"}, 124 128 wantStdout: "hello\n", 125 - wantErrSub: "No such file or directory", 129 + wantErrSub: "cat: nope.txt:", 126 130 wantErr: true, 127 131 }, 128 132 { ··· 131 135 wantStdout: "hello\n", 132 136 }, 133 137 { 138 + name: "double dash allows dash-prefixed filename", 139 + args: []string{"--", "-file"}, 140 + wantStdout: "dashfile\n", 141 + }, 142 + { 143 + name: "u flag accepted as no-op", 144 + args: []string{"-u", "hello.txt"}, 145 + wantStdout: "hello\n", 146 + }, 147 + { 148 + name: "two dashes consume stdin once", 149 + args: []string{"-", "-"}, 150 + stdin: "foo", 151 + wantStdout: "foo", 152 + }, 153 + { 134 154 name: "unknown flag", 135 155 args: []string{"--no-such-flag"}, 136 156 wantErr: true, ··· 154 174 t.Errorf("stderr = %q, want substring %q", stderr, tt.wantErrSub) 155 175 } 156 176 }) 177 + } 178 + } 179 + 180 + func TestCatDirectoryDiagnostic(t *testing.T) { 181 + stdout, stderr, err := run(t, []string{"subdir"}, "", newFS(t)) 182 + if err == nil { 183 + t.Fatalf("expected error, got nil; stdout=%q stderr=%q", stdout, stderr) 184 + } 185 + if stdout != "" { 186 + t.Errorf("expected empty stdout, got %q", stdout) 187 + } 188 + if !strings.HasPrefix(stderr, "cat: subdir: ") { 189 + t.Errorf("stderr should start with %q, got %q", "cat: subdir: ", stderr) 190 + } 191 + if strings.Contains(stderr, "No such file or directory") { 192 + t.Errorf("stderr should not hardcode 'No such file or directory'; got %q", stderr) 157 193 } 158 194 } 159 195