@@ -123,6 +123,10 @@ type buildPlan struct {
123123 cmd * Command
124124 insts []* build.Instance
125125
126+ // instance is a pre-compiled instance, which exists if value files are
127+ // being processed, which may require a schema to decode.
128+ instance * cue.Instance
129+
126130 cfg * config
127131
128132 // If orphanFiles are mixed with CUE files and/or if placement flags are used,
@@ -149,18 +153,25 @@ type buildPlan struct {
149153 outFile * build.File
150154
151155 encConfig * encoding.Config
152- merge []* build.Instance
153156}
154157
155158// instances iterates either over a list of instances, or a list of
156159// data files. In the latter case, there must be either 0 or 1 other
157160// instance, with which the data instance may be merged.
158161func (b * buildPlan ) instances () iterator {
159162 var i iterator
160- if len (b .orphaned ) == 0 {
161- i = & instanceIterator {a : buildInstances (b .cmd , b .insts ), i : - 1 }
162- } else {
163+ switch {
164+ case len (b .orphaned ) > 0 :
163165 i = newStreamingIterator (b )
166+ case len (b .insts ) > 0 :
167+ i = & instanceIterator {
168+ inst : b .instance ,
169+ a : buildInstances (b .cmd , b .insts ),
170+ i : - 1 ,
171+ }
172+ default :
173+ i = & instanceIterator {a : []* cue.Instance {b .instance }, i : - 1 }
174+ b .instance = nil
164175 }
165176 if len (b .expressions ) > 0 {
166177 return & expressionIter {
@@ -183,33 +194,44 @@ type iterator interface {
183194}
184195
185196type instanceIterator struct {
186- a []* cue.Instance
187- i int
188- e error
197+ inst * cue.Instance
198+ a []* cue.Instance
199+ i int
200+ e error
189201}
190202
191203func (i * instanceIterator ) scan () bool {
192204 i .i ++
193205 return i .i < len (i .a ) && i .e == nil
194206}
195207
196- func (i * instanceIterator ) close () {}
197- func (i * instanceIterator ) err () error { return i .e }
198- func (i * instanceIterator ) value () cue.Value { return i .a [i .i ].Value () }
199- func (i * instanceIterator ) instance () * cue.Instance { return i .a [i .i ] }
200- func (i * instanceIterator ) file () * ast.File { return nil }
201- func (i * instanceIterator ) id () string { return i .a [i .i ].Dir }
208+ func (i * instanceIterator ) close () {}
209+ func (i * instanceIterator ) err () error { return i .e }
210+ func (i * instanceIterator ) value () cue.Value {
211+ v := i .a [i .i ].Value ()
212+ if i .inst != nil {
213+ v = v .Unify (i .inst .Value ())
214+ }
215+ return v
216+ }
217+ func (i * instanceIterator ) instance () * cue.Instance {
218+ if i .inst != nil {
219+ return nil
220+ }
221+ return i .a [i .i ]
222+ }
223+ func (i * instanceIterator ) file () * ast.File { return nil }
224+ func (i * instanceIterator ) id () string { return i .a [i .i ].Dir }
202225
203226type streamingIterator struct {
204- r * cue.Runtime
205- inst * cue.Instance
206- b * buildPlan
207- cfg * encoding.Config
208- a []* decoderInfo
209- dec * encoding.Decoder
210- v cue.Value
211- f * ast.File
212- e error
227+ r * cue.Runtime
228+ b * buildPlan
229+ cfg * encoding.Config
230+ a []* decoderInfo
231+ dec * encoding.Decoder
232+ v cue.Value
233+ f * ast.File
234+ e error
213235}
214236
215237func newStreamingIterator (b * buildPlan ) * streamingIterator {
@@ -220,28 +242,9 @@ func newStreamingIterator(b *buildPlan) *streamingIterator {
220242 }
221243
222244 // TODO: use orphanedSchema
223- switch len (b .insts ) {
224- case 0 :
225- i .r = & cue.Runtime {}
226- case 1 :
227- p := b .insts [0 ]
228- inst := buildInstances (b .cmd , []* build.Instance {p })[0 ]
229- if inst .Err != nil {
230- return & streamingIterator {e : inst .Err }
231- }
232- i .r = internal .GetRuntime (inst ).(* cue.Runtime )
233- if b .schema == nil {
234- b .encConfig .Schema = inst .Value ()
235- } else {
236- schema := inst .Eval (b .schema )
237- if err := schema .Err (); err != nil {
238- return & streamingIterator {e : err }
239- }
240- b .encConfig .Schema = schema
241- }
242- default :
243- return & streamingIterator {e : errors .Newf (token .NoPos ,
244- "cannot combine data streaming with multiple instances" )}
245+ i .r = & cue.Runtime {}
246+ if v := b .encConfig .Schema ; v .Exists () {
247+ i .r = internal .GetRuntime (v ).(* cue.Runtime )
245248 }
246249
247250 return i
@@ -252,9 +255,6 @@ func (i *streamingIterator) value() cue.Value { return i.v }
252255func (i * streamingIterator ) instance () * cue.Instance { return nil }
253256
254257func (i * streamingIterator ) id () string {
255- if i .inst != nil {
256- return i .inst .Dir
257- }
258258 return ""
259259}
260260
@@ -510,10 +510,6 @@ func parseArgs(cmd *Command, args []string, cfg *config) (p *buildPlan, err erro
510510 return nil , err
511511 }
512512
513- // TODO(v0.4.0): what to do:
514- // - when there is already a single instance
515- // - when we are importing and there are schemas and values.
516-
517513 if values == nil {
518514 values , schemas = schemas , values
519515 }
@@ -530,42 +526,63 @@ func parseArgs(cmd *Command, args []string, cfg *config) (p *buildPlan, err erro
530526 }
531527 }
532528
533- // TODO(v0.4.0): if schema is specified and data format is JSON, YAML or
534- // Protobuf, reinterpret with schema.
529+ if len (p .insts ) > 1 && p .schema != nil {
530+ return nil , errors .Newf (token .NoPos ,
531+ "cannot use --schema/-d with flag more than one schema" )
532+ }
535533
536- switch {
537- case p .usePlacement () || p .importing :
538- if err = p .placeOrphans (b , values ); err != nil {
539- return nil , err
534+ var schema * build.Instance
535+ switch n := len (p .insts ); n {
536+ default :
537+ return nil , errors .Newf (token .NoPos ,
538+ "too many packages defined (%d) in combination with files" , n )
539+ case 1 :
540+ if len (schemas ) > 0 {
541+ return nil , errors .Newf (token .NoPos ,
542+ "cannot combine packages with individual schema files" )
540543 }
544+ schema = p .insts [0 ]
545+ p .insts = nil
546+
547+ case 0 :
548+ bb := * b
549+ schema = & bb
550+ b .BuildFiles = nil
551+ b .Files = nil
552+ }
541553
542- case ! p . mergeData || p . schema != nil :
543- p . orphaned = values
554+ if schema != nil && len ( schema . Files ) > 0 {
555+ inst := buildInstances ( p . cmd , [] * build. Instance { schema })[ 0 ]
544556
545- default :
546- for _ , di := range values {
547- d := di .dec (p )
548- for ; ! d .Done (); d .Next () {
549- if err := b .AddSyntax (d .File ()); err != nil {
550- return nil , err
551- }
552- }
553- if err := d .Err (); err != nil {
557+ if inst .Err != nil {
558+ return nil , err
559+ }
560+ p .instance = inst
561+ p .encConfig .Schema = inst .Value ()
562+ if p .schema != nil {
563+ v := inst .Eval (p .schema )
564+ if err := v .Err (); err != nil {
554565 return nil , err
555566 }
567+ p .encConfig .Schema = v
556568 }
557569 }
558570
571+ switch {
572+ case p .mergeData , p .usePlacement (), p .importing :
573+ if err = p .placeOrphans (b , values ); err != nil {
574+ return nil , err
575+ }
576+
577+ default :
578+ p .orphaned = values
579+ }
580+
559581 if len (b .Files ) > 0 {
560582 p .insts = append (p .insts , b )
561583 }
562584 }
563585
564- if len (p .insts ) > 1 && p .schema != nil {
565- return nil , errors .Newf (token .NoPos ,
566- "cannot use --schema/-d flag more than one schema" )
567- }
568-
569586 if len (p .expressions ) > 1 {
570587 p .encConfig .Stream = true
571588 }
0 commit comments