Skip to content
Merged
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
9 changes: 9 additions & 0 deletions cmd/jsonnet/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func usage(o io.Writer) {
fmt.Fprintln(o, " files")
fmt.Fprintln(o, " -y / --yaml-stream Write output as a YAML stream of JSON documents")
fmt.Fprintln(o, " -S / --string Expect a string, manifest as plain text")
fmt.Fprintln(o, " --no-trailing-newline Do not add a trailing newline to the output")
fmt.Fprintln(o, " -s / --max-stack <n> Number of allowed stack frames")
fmt.Fprintln(o, " -t / --max-trace <n> Max length of stack trace before cropping")
fmt.Fprintln(o, " --version Print version")
Expand Down Expand Up @@ -256,13 +257,21 @@ func processArgs(givenArgs []string, config *config, vm *jsonnet.VM) (processArg
config.evalStream = true
} else if arg == "-S" || arg == "--string" {
vm.StringOutput = true
} else if arg == "--no-trailing-newline" {
vm.OutputNewline = false
} else if len(arg) > 1 && arg[0] == '-' {
return processArgsStatusFailure, fmt.Errorf("unrecognized argument: %s", arg)
} else {
remainingArgs = append(remainingArgs, arg)
}
}

// --no-trailing-newline is meaningless when used with --yaml-stream
// so we explicitly reject it to prevent people from relying on it.
if config.evalStream && !vm.OutputNewline {
return processArgsStatusFailure, fmt.Errorf("cannot use --no-trailing-newline with --yaml-stream")
}

want := "filename"
if config.filenameIsCode {
want = "code"
Expand Down
46 changes: 13 additions & 33 deletions interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ func (i *interpreter) manifestString(buf *bytes.Buffer, v value) error {
}
}

func (i *interpreter) manifestAndSerializeMulti(v value, stringOutputMode bool) (r map[string]string, err error) {
func (i *interpreter) manifestAndSerializeMulti(v value, stringOutputMode bool, outputNewline bool) (r map[string]string, err error) {
r = make(map[string]string)
json, err := i.manifestJSON(v)
if err != nil {
Expand All @@ -911,21 +911,23 @@ func (i *interpreter) manifestAndSerializeMulti(v value, stringOutputMode bool)
switch json := json.(type) {
case map[string]interface{}:
for filename, fileJSON := range json {
var buf bytes.Buffer
if stringOutputMode {
switch val := fileJSON.(type) {
case string:
r[filename] = val
buf.WriteString(val)
default:
msg := fmt.Sprintf("multi mode: top-level object's key %s has a value of type %T, "+
"should be a string", filename, val)
return r, makeRuntimeError(msg, i.getCurrentStackTrace())
}
} else {
var buf bytes.Buffer
serializeJSON(fileJSON, true, "", &buf)
}
if outputNewline {
buf.WriteString("\n")
r[filename] = buf.String()
}
r[filename] = buf.String()
}
default:
msg := fmt.Sprintf("multi mode: top-level object was a %s, "+
Expand Down Expand Up @@ -1350,15 +1352,7 @@ func evaluateAux(i *interpreter, node ast.Node, tla vmExtMap) (value, error) {
return result, nil
}

// TODO(sbarzowski) this function takes far too many arguments - build interpreter in vm instead
func evaluate(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]*NativeFunction,
maxStack int, ic *importCache, traceOut io.Writer, stringOutputMode bool, evalHook EvalHook) (string, error) {

i, err := buildInterpreter(ext, nativeFuncs, maxStack, ic, traceOut, evalHook)
if err != nil {
return "", err
}

func evaluate(i *interpreter, node ast.Node, tla vmExtMap, stringOutputMode bool, outputNewline bool) (string, error) {
result, err := evaluateAux(i, node, tla)
if err != nil {
return "", err
Expand All @@ -1375,39 +1369,25 @@ func evaluate(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]
if err != nil {
return "", err
}
buf.WriteString("\n")
if outputNewline {
buf.WriteString("\n")
}
return buf.String(), nil
}

// TODO(sbarzowski) this function takes far too many arguments - build interpreter in vm instead
func evaluateMulti(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]*NativeFunction,
maxStack int, ic *importCache, traceOut io.Writer, stringOutputMode bool, evalHook EvalHook) (map[string]string, error) {

i, err := buildInterpreter(ext, nativeFuncs, maxStack, ic, traceOut, evalHook)
if err != nil {
return nil, err
}

func evaluateMulti(i *interpreter, node ast.Node, tla vmExtMap, stringOutputMode bool, outputNewline bool) (map[string]string, error) {
result, err := evaluateAux(i, node, tla)
if err != nil {
return nil, err
}

i.stack.setCurrentTrace(manifestationTrace())
manifested, err := i.manifestAndSerializeMulti(result, stringOutputMode)
manifested, err := i.manifestAndSerializeMulti(result, stringOutputMode, outputNewline)
i.stack.clearCurrentTrace()
return manifested, err
}

// TODO(sbarzowski) this function takes far too many arguments - build interpreter in vm instead
func evaluateStream(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]*NativeFunction,
maxStack int, ic *importCache, traceOut io.Writer, evalHook EvalHook) ([]string, error) {

i, err := buildInterpreter(ext, nativeFuncs, maxStack, ic, traceOut, evalHook)
if err != nil {
return nil, err
}

func evaluateStream(i *interpreter, node ast.Node, tla vmExtMap) ([]string, error) {
result, err := evaluateAux(i, node, tla)
if err != nil {
return nil, err
Expand Down
3 changes: 3 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ type jsonnetInput struct {
input []byte
eKind evalKind
stringOutputMode bool
noNewline bool // not nice to have a negative flag, but it gives the more relevant default
extVars map[string]string
extCode map[string]string
}
Expand All @@ -134,6 +135,7 @@ func runInternalJsonnet(i jsonnetInput) jsonnetResult {
errFormatter := termErrorFormatter{pretty: true, maxStackTraceSize: 9}

vm.StringOutput = i.stringOutputMode
vm.OutputNewline = !i.noNewline
for name, value := range i.extVars {
vm.ExtVar(name, value)
}
Expand Down Expand Up @@ -336,6 +338,7 @@ func runTest(t *testing.T, test *mainTest) {
input: input,
eKind: eKind,
stringOutputMode: strings.HasSuffix(test.golden, "_string_output.golden"),
noNewline: strings.Contains(test.golden, "_no_newline"),
extVars: test.meta.extVars,
extCode: test.meta.extCode,
})
Expand Down
55 changes: 55 additions & 0 deletions testdata/cpp-tests-override/help.golden.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Jsonnet commandline interpreter (Go implementation) v0.21.0

jsonnet {<option>} <filename>

Available options:
-h / --help This message
-e / --exec Treat filename as code
-J / --jpath <dir> Specify an additional library search dir
(right-most wins)
-o / --output-file <file> Write to the output file rather than stdout
-m / --multi <dir> Write multiple files to the directory, list files
on stdout
-c / --create-output-dirs Automatically creates all parent directories for
files
-y / --yaml-stream Write output as a YAML stream of JSON documents
-S / --string Expect a string, manifest as plain text
--no-trailing-newline Do not add a trailing newline to the output
-s / --max-stack <n> Number of allowed stack frames
-t / --max-trace <n> Max length of stack trace before cropping
--version Print version

Available options for specifying values of 'external' variables:
Provide the value as a string:
-V / --ext-str <var>[=<val>] If <val> is omitted, get from environment
var <var>
--ext-str-file <var>=<file> Read the string from the file
Provide a value as Jsonnet code:
--ext-code <var>[=<code>] If <code> is omitted, get from environment
var <var>
--ext-code-file <var>=<file> Read the code from the file

Available options for specifying values of 'top-level arguments':
Provide the value as a string:
-A / --tla-str <var>[=<val>] If <val> is omitted, get from environment
var <var>
--tla-str-file <var>=<file> Read the string from the file
Provide a value as Jsonnet code:
--tla-code <var>[=<code>] If <code> is omitted, get from environment
var <var>
--tla-code-file <var>=<file> Read the code from the file

Environment variables:
JSONNET_PATH is a colon (semicolon on Windows) separated list of directories
added in reverse order before the paths specified by --jpath (i.e. left-most
wins). E.g. these are equivalent:
JSONNET_PATH=a:b jsonnet -J c -J d
JSONNET_PATH=d:c:a:b jsonnet
jsonnet -J b -J a -J c -J d

In all cases:
<filename> can be - (stdin)
Multichar options are expanded e.g. -abc becomes -a -b -c.
The -- option suppresses option processing for subsequent arguments.
Note that since filenames and jsonnet programs can begin with -, it is
advised to use -- if the argument is unknown, e.g. jsonnet -- "$FILENAME".
57 changes: 57 additions & 0 deletions testdata/cpp-tests-override/no_args.golden.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
ERROR: must give filename

Jsonnet commandline interpreter (Go implementation) v0.21.0

jsonnet {<option>} <filename>

Available options:
-h / --help This message
-e / --exec Treat filename as code
-J / --jpath <dir> Specify an additional library search dir
(right-most wins)
-o / --output-file <file> Write to the output file rather than stdout
-m / --multi <dir> Write multiple files to the directory, list files
on stdout
-c / --create-output-dirs Automatically creates all parent directories for
files
-y / --yaml-stream Write output as a YAML stream of JSON documents
-S / --string Expect a string, manifest as plain text
--no-trailing-newline Do not add a trailing newline to the output
-s / --max-stack <n> Number of allowed stack frames
-t / --max-trace <n> Max length of stack trace before cropping
--version Print version

Available options for specifying values of 'external' variables:
Provide the value as a string:
-V / --ext-str <var>[=<val>] If <val> is omitted, get from environment
var <var>
--ext-str-file <var>=<file> Read the string from the file
Provide a value as Jsonnet code:
--ext-code <var>[=<code>] If <code> is omitted, get from environment
var <var>
--ext-code-file <var>=<file> Read the code from the file

Available options for specifying values of 'top-level arguments':
Provide the value as a string:
-A / --tla-str <var>[=<val>] If <val> is omitted, get from environment
var <var>
--tla-str-file <var>=<file> Read the string from the file
Provide a value as Jsonnet code:
--tla-code <var>[=<code>] If <code> is omitted, get from environment
var <var>
--tla-code-file <var>=<file> Read the code from the file

Environment variables:
JSONNET_PATH is a colon (semicolon on Windows) separated list of directories
added in reverse order before the paths specified by --jpath (i.e. left-most
wins). E.g. these are equivalent:
JSONNET_PATH=a:b jsonnet -J c -J d
JSONNET_PATH=d:c:a:b jsonnet
jsonnet -J b -J a -J c -J d

In all cases:
<filename> can be - (stdin)
Multichar options are expanded e.g. -abc becomes -a -b -c.
The -- option suppresses option processing for subsequent arguments.
Note that since filenames and jsonnet programs can begin with -, it is
advised to use -- if the argument is unknown, e.g. jsonnet -- "$FILENAME".
7 changes: 7 additions & 0 deletions testdata/multi_no_newline.golden/bar.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"foo": {
"bar": {
"baz": "yes"
}
}
}
4 changes: 4 additions & 0 deletions testdata/multi_no_newline.golden/foo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"baq": "27",
"baz": 3
}
13 changes: 13 additions & 0 deletions testdata/multi_no_newline.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"foo.json": {
baz: 3,
baq: "27",
},
"bar.json": {
foo: {
bar: {
baz: "yes",
},
},
},
}
Empty file.
1 change: 1 addition & 0 deletions testdata/multi_no_newline_string_output.golden/bar.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
1 change: 1 addition & 0 deletions testdata/multi_no_newline_string_output.golden/foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo.
6 changes: 6 additions & 0 deletions testdata/multi_no_newline_string_output.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"foo.txt": |||-
foo.
|||,
"bar.txt": "bar",
}
Empty file.
2 changes: 1 addition & 1 deletion testdata/multi_string_output.golden/bar.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bar
bar
2 changes: 1 addition & 1 deletion testdata/multi_string_output.jsonnet
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"foo.txt": |||
"foo.txt": |||-
foo.
|||,
"bar.txt": "bar",
Expand Down
3 changes: 3 additions & 0 deletions testdata/object_no_newline.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"x": 2
}
1 change: 1 addition & 0 deletions testdata/object_no_newline.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"x": 1+1}
Empty file.
Loading