this repo has no description
0
fork

Configure Feed

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

cmd/cue: rewrite `exp writefs` with internal/filetypes and internal/encoding

This means that we automatically support all output filetypes that
cmd/cue supports via e.g. `cue export --out`,
as well as all the filename extension detection.

No change in behavior to existing features, other than the "text" form
now adding a newline at the end of the contents,
again matching cmd/cue's behavior.
This makes sense to me too, as writing a text file without a trailing
newline is generally considered to be an anti-pattern.

The only other noteworthy change is that we used to always fall back
to "text" as the encoding when one could not be derived from a
filename extension. We keep that for cases where there is no extension,
but for any case where there is an unknown extension, we drop that
as we want the user to use the upcoming `encoding: "text"` field.
Otherwise, adding a new encoding like xml would silently break users,
as writing a file like

"foo.xml": contents: "some string"

would suddenly switch from writing the string as text
to writing the string as an XML value without a warning.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: Ia2880a36478b025f356d594f6106cb6a4a61125f
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1232053
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.io>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+28 -31
+26 -29
cmd/cue/cmd/exp.go
··· 22 22 "path/filepath" 23 23 "time" 24 24 25 + "cuelang.org/go/cue/build" 25 26 "cuelang.org/go/cue/cuecontext" 26 27 "cuelang.org/go/cue/load" 27 - cuetoml "cuelang.org/go/encoding/toml" 28 - cueyaml "cuelang.org/go/encoding/yaml" 28 + "cuelang.org/go/internal/encoding" 29 29 "cuelang.org/go/internal/encoding/gotypes" 30 + "cuelang.org/go/internal/filetypes" 30 31 31 32 "github.com/spf13/cobra" 32 33 ) ··· 239 240 return fmt.Errorf("failed to symlink %s -> %s: %v", fp, target, err) 240 241 } 241 242 case "file", "": // empty if omitted, as it's the default 242 - v := ctx.CompileBytes(f.Contents) 243 + fenc := "" 244 + if filepath.Ext(fp) == "" { 245 + // Fall back to text when there is no extension, which is a useful default 246 + // without causing issues when we add more encodings with extensions in the future. 247 + fenc = "text" 248 + } 249 + bfile, err := filetypes.ParseFileAndType(fp, fenc, filetypes.Export) 250 + if err != nil { 251 + return fmt.Errorf("failed to infer filetype: %v", err) 252 + } 253 + 243 254 var buf bytes.Buffer 244 - ext := filepath.Ext(fp) 245 - 246 255 // Gross: hack in a "code generated by" header for filetypes that support comments 247 256 // 248 257 // TODO: replace this gross hack once we can encode comments. 249 - switch ext { 250 - case ".yaml", ".toml": 258 + switch bfile.Encoding { 259 + case build.YAML, build.TOML: 251 260 fmt.Fprintf(&buf, "# Code generated %s; DO NOT EDIT.\n\n", todo.Tool) 252 261 } 253 262 254 - // TODO: more principled checking of whether this filetype is known to CUE. 255 - // Note that cuelang.org/play has a similar situation going on. 256 - var err error 257 - switch ext := filepath.Ext(fp); ext { 258 - case ".json": 259 - // Note that we marshal again, to ensure good formatting. 260 - var p []byte 261 - p, err = json.MarshalIndent(v, "", " ") 262 - p = append(p, '\n') 263 - buf.Write(p) 264 - case ".yaml": 265 - var p []byte 266 - p, err = cueyaml.Encode(v) 267 - buf.Write(p) 268 - case ".toml": 269 - err = cuetoml.NewEncoder(&buf).Encode(v) 270 - default: // Must be string 271 - var str string 272 - str, err = v.String() 273 - buf.WriteString(str) 263 + enc, err := encoding.NewEncoder(cmd.ctx, bfile, &encoding.Config{Out: &buf}) 264 + if err != nil { 265 + return fmt.Errorf("failed to create encoder: %v", err) 266 + } 267 + 268 + v := ctx.CompileBytes(f.Contents) 269 + if err := enc.Encode(v); err != nil { 270 + return fmt.Errorf("failed to encode file: %v", err) 274 271 } 275 - if err != nil { 276 - return fmt.Errorf("failed to encode: %w", err) 272 + if err := enc.Close(); err != nil { 273 + return fmt.Errorf("failed to encode file: %v", err) 277 274 } 278 275 if err := os.WriteFile(fp, buf.Bytes(), 0o666); err != nil { 279 276 return fmt.Errorf("failed to write file %s: %v", fp, err)
+2 -2
cmd/cue/cmd/testdata/script/exp_writefs.txtar
··· 36 36 "out/foo.yaml": {contents: foo: "as yaml"} 37 37 "out/foo.json": {contents: foo: "as json"} 38 38 "out/foo.toml": {contents: foo: "as toml"} 39 - "out/foo.txt": {contents: "plain text\n"} 40 - "out/foo-noext": {contents: "plain text\n"} 39 + "out/foo.txt": {contents: "plain text"} 40 + "out/foo-noext": {contents: "plain text"} 41 41 "out/link.yaml": {type: "symlink", contents: "foo.yaml"} 42 42 "out/sub/dir/foo.yaml": {type: "file", contents: foo: "in nested dir"} 43 43 }