cmd/cue/cmd: simplify usage of --path flag
Closes #176
Issue #193
Change-Id: I95609cec93b0429470f1d7342ab12d45fd9207c7
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4905
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/import.go b/cmd/cue/cmd/import.go
index ec6f45a..e79ae38 100644
--- a/cmd/cue/cmd/import.go
+++ b/cmd/cue/cmd/import.go
@@ -29,11 +29,9 @@
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
- "cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/ast/astutil"
"cuelang.org/go/cue/encoding"
- "cuelang.org/go/cue/errors"
"cuelang.org/go/cue/format"
"cuelang.org/go/cue/literal"
"cuelang.org/go/cue/load"
@@ -125,13 +123,13 @@
}
# include the parsed file at the root of the CUE file:
- $ cue import -f -l "" foo.yaml
+ $ cue import -f foo.yaml
$ cat foo.cue
kind: Service
name: booster
# include the import config at the mystuff path
- $ cue import -f -l mystuff foo.yaml
+ $ cue import -f -l '"mystuff"' foo.yaml
$ cat foo.cue
myStuff: {
kind: Service
@@ -145,8 +143,8 @@
name: booster
replicas: 1
- # base the path values on th input
- $ cue import -f -l '"\(strings.ToLower(kind))" "\(x.name)"' foo.yaml
+ # base the path values on the input
+ $ cue import -f -l 'strings.ToLower(kind)' -l name foo.yaml
$ cat foo.cue
service: booster: {
kind: "Service"
@@ -154,7 +152,7 @@
}
# base the path values on the input and file name
- $ cue import -f --with-context -l '"\(path.Base(filename))" "\(data.kind)"' foo.yaml
+ $ cue import -f --with-context -l 'path.Base(filename)' -l data.kind foo.yaml
$ cat foo.cue
"foo.yaml": Service: {
kind: "Service"
@@ -167,7 +165,7 @@
replicas: 1
}
- # base the path values on th input
+ # include all files as list elements
$ cue import -f -list -foo.yaml
$ cat foo.cue
[{
@@ -179,8 +177,8 @@
replicas: 1
}]
- # base the path values on th input
- $ cue import -f -list -l '"\(strings.ToLower(kind))"' foo.yaml
+ # collate files with the same path into a list
+ $ cue import -f -list -l 'strings.ToLower(kind)' foo.yaml
$ cat foo.cue
service: [{
kind: "Service"
@@ -230,7 +228,7 @@
cmd.Flags().BoolP(string(flagForce), "f", false, "force overwriting existing files")
cmd.Flags().Bool(string(flagDryrun), false, "only run simulation")
- cmd.Flags().StringP(string(flagPath), "l", "", "path to include root")
+ cmd.Flags().StringArrayP(string(flagPath), "l", nil, "CUE expression for single path component")
cmd.Flags().Bool(string(flagList), false, "concatenate multiple objects into a list")
cmd.Flags().Bool(string(flagFiles), false, "split multiple entries into different files")
cmd.Flags().BoolP(string(flagRecursive), "R", false, "recursively parse string values")
@@ -397,7 +395,7 @@
}
return nil
} else if len(objs) > 1 {
- if !flagList.Bool(cmd) && flagPath.String(cmd) == "" && !flagFiles.Bool(cmd) {
+ if !flagList.Bool(cmd) && len(flagPath.StringArray(cmd)) == 0 && !flagFiles.Bool(cmd) {
return fmt.Errorf("list, flag, or files flag needed to handle multiple objects in file %q", filename)
}
}
@@ -456,7 +454,7 @@
var pathElems []ast.Label
switch {
- case flagPath.String(cmd) != "":
+ case len(flagPath.StringArray(cmd)) > 0:
expr := expr
if flagWithContext.Bool(cmd) {
expr = ast.NewStruct(
@@ -471,25 +469,17 @@
return err
}
- labels, err := parsePath(flagPath.String(cmd))
- if err != nil {
- return err
- }
- for _, l := range labels {
- switch x := l.(type) {
- case *ast.Interpolation:
- v := inst.Eval(x)
- if v.Kind() == cue.BottomKind {
- return v.Err()
- }
- pathElems = append(pathElems, v.Syntax().(ast.Label))
-
- case *ast.Ident, *ast.BasicLit:
- pathElems = append(pathElems, x)
-
- case *ast.TemplateLabel:
- return fmt.Errorf("template labels not supported in path flag")
+ for _, str := range flagPath.StringArray(cmd) {
+ l, err := parser.ParseExpr("<path flag>", str)
+ if err != nil {
+ return fmt.Errorf(`labels are of form "cue import -l foo -l 'strings.ToLower(bar)'": %v`, err)
}
+
+ str, err := inst.Eval(l).String()
+ if err != nil {
+ return fmt.Errorf("unsupported label path type: %v", err)
+ }
+ pathElems = append(pathElems, ast.NewString(str))
}
}
@@ -587,40 +577,6 @@
return idx
}
-func parsePath(exprs string) (p []ast.Label, err error) {
- f, err := parser.ParseFile("<path flag>", exprs+": _")
- if err != nil {
- return nil, fmt.Errorf("parser error in path %q: %v", exprs, err)
- }
-
- if len(f.Decls) != 1 {
- return nil, errors.New("path flag must be a space-separated sequence of labels")
- }
-
- for d := f.Decls[0]; ; {
- field, ok := d.(*ast.Field)
- if !ok {
- // This should never happen
- return nil, errors.New("%q not a sequence of labels")
- }
-
- p = append(p, field.Label)
-
- v, ok := field.Value.(*ast.StructLit)
- if !ok {
- break
- }
-
- if len(v.Elts) != 1 {
- // This should never happen
- return nil, errors.New("path value may not contain a struct")
- }
-
- d = v.Elts[0]
- }
- return p, nil
-}
-
func newName(filename string, i int) string {
ext := filepath.Ext(filename)
filename = filename[:len(filename)-len(ext)]
diff --git a/cmd/cue/cmd/testdata/script/import_context.txt b/cmd/cue/cmd/testdata/script/import_context.txt
index b2a3802..34860ca 100644
--- a/cmd/cue/cmd/testdata/script/import_context.txt
+++ b/cmd/cue/cmd/testdata/script/import_context.txt
@@ -1,4 +1,4 @@
-cue import -o - -f --with-context -l '"\(path.Ext(filename)):\(index+1)/\(recordCount)" "\(data["@name"])"' ./import
+cue import -o - -f --with-context -l '"\(path.Ext(filename)):\(index+1)/\(recordCount)"' -l 'data["@name"]' ./import
cmp stdout expect-stdout
-- expect-stdout --
".jsonl:1/3": elem1: {
diff --git a/cmd/cue/cmd/testdata/script/import_hoiststr.txt b/cmd/cue/cmd/testdata/script/import_hoiststr.txt
index e8fda16..e0f50f6 100644
--- a/cmd/cue/cmd/testdata/script/import_hoiststr.txt
+++ b/cmd/cue/cmd/testdata/script/import_hoiststr.txt
@@ -1,4 +1,4 @@
-cue import -o - -f --list -l '"\(strings.ToLower(kind))" "\(name)"' --recursive ./import
+cue import -o - -f --list -l 'strings.ToLower(kind)' -l name --recursive ./import
cmp stdout expect-stdout
-- expect-stdout --
import json656e63 "encoding/json"
diff --git a/cmd/cue/cmd/testdata/script/import_path.txt b/cmd/cue/cmd/testdata/script/import_path.txt
index 18aacdb..90ddb12 100644
--- a/cmd/cue/cmd/testdata/script/import_path.txt
+++ b/cmd/cue/cmd/testdata/script/import_path.txt
@@ -1,4 +1,4 @@
-cue import -o - -f -l '"\(strings.ToLower(kind))" "\(name)"' ./import
+cue import -o - -f -l 'strings.ToLower(kind)' -l name ./import
cmp stdout expect-stdout
-- expect-stdout --
service: booster: {
diff --git a/doc/tutorial/kubernetes/README.md b/doc/tutorial/kubernetes/README.md
index 368eaed..8ad05ce 100644
--- a/doc/tutorial/kubernetes/README.md
+++ b/doc/tutorial/kubernetes/README.md
@@ -109,7 +109,7 @@
tree at the path with the "kind" as first element and "name" as second.
```
-$ cue import ./... -p kube -l '"\(strings.ToCamel(kind))": "\(metadata.name)"' -f
+$ cue import ./... -p kube -l 'strings.ToCamel(kind)' -l metadata.name -f
```
The added `-l` flag defines the labels for each object, based on values from
@@ -165,7 +165,7 @@
<-- TODO: update import label format -->
```
-$ cue import ./... -p kube -l '"\(strings.ToCamel(kind))": "\(metadata.name)"' -f -R
+$ cue import ./... -p kube -l 'strings.ToCamel(kind)' -l metadata.name -f -R
```
Now the file looks like: