Skip to content

Commit 1e8906a

Browse files
committed
cmd/cue/cmd: move injection mechanism to cue/load
Less cmd/cue-specific code and prepares for build tag support. Change-Id: Ie9e6397b5c046de601d48cf876dac1ae662bdc69 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7063 Reviewed-by: CUE cueckoo <[email protected]> Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent 4cce6c4 commit 1e8906a

File tree

4 files changed

+82
-28
lines changed

4 files changed

+82
-28
lines changed

cmd/cue/cmd/common.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,12 @@ func parseArgs(cmd *Command, args []string, cfg *config) (p *buildPlan, err erro
376376
return nil, err
377377
}
378378

379+
cfg.loadCfg.Tags = flagInject.StringArray(cmd)
380+
379381
builds := loadFromArgs(cmd, args, cfg.loadCfg)
380382
if builds == nil {
381383
return nil, errors.Newf(token.NoPos, "invalid args")
382384
}
383-
decorateInstances(cmd, flagInject.StringArray(cmd), builds)
384385

385386
for _, b := range builds {
386387
if b.Err != nil {
@@ -571,7 +572,12 @@ func buildToolInstances(cmd *Command, binst []*build.Instance) ([]*cue.Instance,
571572
}
572573

573574
func buildTools(cmd *Command, tags, args []string) (*cue.Instance, error) {
574-
binst := loadFromArgs(cmd, args, &load.Config{Tools: true})
575+
576+
cfg := &load.Config{
577+
Tags: tags,
578+
Tools: true,
579+
}
580+
binst := loadFromArgs(cmd, args, cfg)
575581
if len(binst) == 0 {
576582
return nil, nil
577583
}
@@ -593,7 +599,6 @@ func buildTools(cmd *Command, tags, args []string) (*cue.Instance, error) {
593599
}
594600
inst.Files = inst.Files[:k]
595601
}
596-
decorateInstances(cmd, tags, append(binst, ti))
597602

598603
insts, err := buildToolInstances(cmd, binst)
599604
if err != nil {

cue/load/config.go

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,62 @@ type Config struct {
150150
// If Dir is empty, the tool is run in the current directory.
151151
Dir string
152152

153-
// The build and release tags specify build constraints that should be
154-
// considered satisfied when processing +build lines. Clients creating a new
155-
// context may customize BuildTags, which defaults to empty, but it is
156-
// usually an error to customize ReleaseTags, which defaults to the list of
157-
// CUE releases the current release is compatible with.
153+
// Tags defines boolean tags or key-value pairs to select files to build
154+
// or be injected as values in fields.
155+
//
156+
// Each string is of the form
157+
//
158+
// key [ "=" value ]
159+
//
160+
// where key is a valid CUE identifier and value valid CUE scalar.
161+
//
162+
// The Tags values are used to both select which files get included in a
163+
// build and to inject values into the AST.
164+
//
165+
//
166+
// Value injection
167+
//
168+
// The Tags values are also used to inject values into fields with a
169+
// @tag attribute.
170+
//
171+
// For any field of the form
172+
//
173+
// field: x @tag(key)
174+
//
175+
// and Tags value for which the name matches key, the field will be
176+
// modified to
177+
//
178+
// field: x & "value"
179+
//
180+
// By default, the injected value is treated as a string. Alternatively, a
181+
// "type" option of the @tag attribute allows a value to be interpreted as
182+
// an int, number, or bool. For instance, for a field
183+
//
184+
// field: x @tag(key,type=int)
185+
//
186+
// an entry "key=2" modifies the field to
187+
//
188+
// field: x & 2
189+
//
190+
// Valid values for type are "int", "number", "bool", and "string".
191+
//
192+
// A @tag attribute can also define shorthand values, which can be injected
193+
// into the fields without having to specify the key. For instance, for
194+
//
195+
// environment: string @tag(env,short=prod|staging)
196+
//
197+
// the Tags entry "prod" sets the environment field to the value "prod".
198+
// This is equivalent to a Tags entry of "env=prod".
199+
//
200+
// The use of @tag does not preclude using any of the usual CUE constraints
201+
// to limit the possible values of a field. For instance
202+
//
203+
// environment: "prod" | "staging" @tag(env,short=prod|staging)
204+
//
205+
// ensures the user may only specify "prod" or "staging".
206+
Tags []string
207+
208+
// Deprecated: use Tags
158209
BuildTags []string
159210
releaseTags []string
160211

cue/load/loader.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ func Instances(args []string, c *Config) []*build.Instance {
8484
a = append(a, l.cueFilesPackage(files))
8585
}
8686

87+
// TODO(api): have API call that returns an error which is the aggregate
88+
// of all build errors. Certain errors, like these, hold across builds.
89+
if err := injectTags(c.Tags, l.tags); err != nil {
90+
for _, p := range a {
91+
p.ReportError(err)
92+
}
93+
}
94+
8795
return a
8896
}
8997

@@ -102,8 +110,9 @@ const (
102110
)
103111

104112
type loader struct {
105-
cfg *Config
106-
stk importStack
113+
cfg *Config
114+
stk importStack
115+
tags []tag // tags found in files
107116
}
108117

109118
func (l *loader) abs(filename string) string {
@@ -195,6 +204,11 @@ func (l *loader) addFiles(dir string, p *build.Instance) {
195204
}
196205
d.Close()
197206
}
207+
tags, err := findTags(p)
208+
if err != nil {
209+
p.ReportError(err)
210+
}
211+
l.tags = append(l.tags, tags...)
198212
}
199213

200214
func cleanImport(path string) string {

cmd/cue/cmd/tags.go renamed to cue/load/tags.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
package cmd
15+
package load
1616

1717
import (
1818
"strings"
@@ -26,13 +26,6 @@ import (
2626
"cuelang.org/go/internal/cli"
2727
)
2828

29-
func decorateInstances(cmd *Command, tags []string, a []*build.Instance) {
30-
if len(tags) == 0 {
31-
return
32-
}
33-
exitOnErr(cmd, injectTags(tags, a), true)
34-
}
35-
3629
// A tag binds an identifier to a field to allow passing command-line values.
3730
//
3831
// A tag is of the form
@@ -145,16 +138,7 @@ func findTags(b *build.Instance) (tags []tag, errs errors.Error) {
145138
return tags, errs
146139
}
147140

148-
func injectTags(tags []string, b []*build.Instance) errors.Error {
149-
var a []tag
150-
for _, p := range b {
151-
x, err := findTags(p)
152-
if err != nil {
153-
return err
154-
}
155-
a = append(a, x...)
156-
}
157-
141+
func injectTags(tags []string, a []tag) errors.Error {
158142
// Parses command line args
159143
for _, s := range tags {
160144
p := strings.Index(s, "=")

0 commit comments

Comments
 (0)