diff --git a/cmd/cue/cmd/exp.go b/cmd/cue/cmd/exp.go index 3831a9c16..ff698878d 100644 --- a/cmd/cue/cmd/exp.go +++ b/cmd/cue/cmd/exp.go @@ -158,9 +158,11 @@ writefs takes JSON via stdin in the form of } | *{ type: "file" - // If filepath has a supported file extension, such as .yaml or .json, - // this is an arbitrary concrete value written in that encoding. - // Otherwise, this is a string written as-is. + // encoding can be set to a filetype like "text", "json", or "yaml" + // to control how the arbitrary concrete value in contents is encoded. + // When unset, the filepath extension is used to infer an encoding, + // with a fallback to "text" for filepaths with no extension. + encoding?: string contents!: _ } @@ -186,6 +188,7 @@ For example, this tool can be used via "cue cmd" as follows: type writefsFile struct { Type string `json:"type"` + Encoding string `json:"encoding"` Contents json.RawMessage `json:"contents"` } @@ -240,9 +243,9 @@ func runExpWritefs(cmd *Command, args []string) error { return fmt.Errorf("failed to symlink %s -> %s: %v", fp, target, err) } case "file", "": // empty if omitted, as it's the default - fenc := "" - if filepath.Ext(fp) == "" { - // Fall back to text when there is no extension, which is a useful default + fenc := f.Encoding + if fenc == "" && filepath.Ext(fp) == "" { + // Fall back to text when there is no encoding nor extension, which is a useful default // without causing issues when we add more encodings with extensions in the future. fenc = "text" } diff --git a/cmd/cue/cmd/testdata/script/exp_writefs.txtar b/cmd/cue/cmd/testdata/script/exp_writefs.txtar index d7816fd99..5ff58ccd0 100644 --- a/cmd/cue/cmd/testdata/script/exp_writefs.txtar +++ b/cmd/cue/cmd/testdata/script/exp_writefs.txtar @@ -11,6 +11,7 @@ cmp out/foo.json expect-json cmp out/foo.toml expect-toml cmp out/foo.txt expect-txt cmp out/foo-noext expect-txt +cmp out/foo.custom expect-yaml cmp out/link.yaml expect-yaml cmp out/sub/dir/foo.yaml expect-nested-yaml @@ -38,6 +39,7 @@ command: gen: exec.Run & { "out/foo.toml": {contents: foo: "as toml"} "out/foo.txt": {contents: "plain text"} "out/foo-noext": {contents: "plain text"} + "out/foo.custom": {encoding: "yaml", contents: foo: "as yaml"} "out/link.yaml": {type: "symlink", contents: "foo.yaml"} "out/sub/dir/foo.yaml": {type: "file", contents: foo: "in nested dir"} } diff --git a/internal/ci/base/write.cue b/internal/ci/base/write.cue index 9edb44bdd..b93abdbb8 100644 --- a/internal/ci/base/write.cue +++ b/internal/ci/base/write.cue @@ -64,9 +64,11 @@ uniqueWorkflowNames: self={ // and this carries forward the semantics we've had in a few repos for a while. type: "file" - // If filepath has a supported file extension, such as .yaml or .json, - // this is an arbitrary concrete value written in that encoding. - // Otherwise, this is a string written as-is. + // encoding can be set to a filetype like "text", "json", or "yaml" + // to control how the arbitrary concrete value in contents is encoded. + // When unset, the filepath extension is used to infer an encoding, + // with a fallback to "text" for filepaths with no extension. + encoding?: string contents!: _ } }