Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
cue/cmd/cue: hoist placement logic from import
Browse files Browse the repository at this point in the history
Change-Id: I81e5a9881f5883c38f77b72a454010dbb5f191d7
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5026
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Feb 28, 2020
1 parent eb7c51d commit 33c7705
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 125 deletions.
125 changes: 117 additions & 8 deletions cmd/cue/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ package cmd

import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strings"
"testing"

Expand Down Expand Up @@ -120,9 +123,14 @@ type buildPlan struct {

// If orphanFiles are mixed with CUE files and/or if placement flags are used,
// the instance is also included in insts.
orphanedData []*build.File
orphanedSchema []*build.File
orphanInstance *build.Instance
forceOrphanProcessing bool
orphanedData []*build.File
orphanedSchema []*build.File
orphanInstance *build.Instance
// imported files are files that were orphaned in the build instance, but
// were placed in the instance by using one the --files, --list or --path
// flags.
imported []*ast.File

expressions []ast.Expr // only evaluate these expressions within results
schema ast.Expr // selects schema in instance for orphaned values
Expand All @@ -138,7 +146,7 @@ func (b *buildPlan) instances() []*cue.Instance {
return buildInstances(b.cmd, b.insts)
}

func parseArgs(cmd *Command, args []string, cfg *load.Config) (*buildPlan, error) {
func parseArgs(cmd *Command, args []string, cfg *load.Config) (p *buildPlan, err error) {
if cfg == nil {
cfg = defaultConfig
}
Expand All @@ -148,21 +156,30 @@ func parseArgs(cmd *Command, args []string, cfg *load.Config) (*buildPlan, error
}
decorateInstances(cmd, flagTags.StringArray(cmd), builds)

p := &buildPlan{cmd: cmd}
p = &buildPlan{cmd: cmd, forceOrphanProcessing: cfg.DataFiles}

if err := p.parseFlags(); err != nil {
return nil, err
}

for _, b := range builds {
var ok bool
if b.User || p.forceOrphanProcessing {
ok, err = p.placeOrphans(b)
if err != nil {
return nil, err
}
}
if !b.User {
p.insts = append(p.insts, b)
continue
}

if len(b.BuildFiles) > 0 {
p.insts = append(p.insts, b)
}
if ok {
continue
}

if len(b.OrphanedFiles) > 0 {
if p.orphanInstance != nil {
Expand Down Expand Up @@ -215,6 +232,100 @@ func (b *buildPlan) parseFlags() (err error) {
return nil
}

func (b *buildPlan) placeOrphans(i *build.Instance) (ok bool, err error) {
var (
perFile = flagFiles.Bool(b.cmd)
useList = flagList.Bool(b.cmd)
path = flagPath.StringArray(b.cmd)
useContext = flagWithContext.Bool(b.cmd)
pkg = flagPackage.String(b.cmd)
match = flagGlob.String(b.cmd)
)
if !b.forceOrphanProcessing && !perFile && !useList && len(path) == 0 {
if useContext {
return false, fmt.Errorf(
"flag %q must be used with at least one of flag %q, %q, or %q",
flagWithContext, flagPath, flagList, flagFiles,
)
}
return false, err
}

if pkg == "" {
pkg = i.PkgName
} else if pkg != "" && i.PkgName != pkg && !flagForce.Bool(b.cmd) {
return false, fmt.Errorf(
"%q flag clashes with existing package name (%s vs %s)",
flagPackage, pkg, i.PkgName,
)
}

var files []*ast.File

re, err := regexp.Compile(match)
if err != nil {
return false, err
}

for _, f := range i.OrphanedFiles {
if !re.MatchString(filepath.Base(f.Filename)) {
return false, nil
}

d := encoding.NewDecoder(f, b.encConfig)
defer d.Close()

var objs []ast.Expr

for ; !d.Done(); d.Next() {
if expr := d.Expr(); expr != nil {
objs = append(objs, expr)
continue
}
f := d.File()
f.Filename = newName(d.Filename(), d.Index())
files = append(files, f)
}

if perFile {
for i, obj := range objs {
f, err := placeOrphans(b.cmd, d.Filename(), pkg, obj)
if err != nil {
return false, err
}
f.Filename = newName(d.Filename(), i)
files = append(files, f)
}
continue
}
if len(objs) > 1 && len(path) == 0 && useList {
return false, fmt.Errorf(
"%s, %s, or %s flag needed to handle multiple objects in file %s",
flagPath, flagList, flagFiles, f.Filename)
}

f, err := placeOrphans(b.cmd, d.Filename(), pkg, objs...)
if err != nil {
return false, err
}
f.Filename = newName(d.Filename(), 0)
files = append(files, f)
}

b.imported = append(b.imported, files...)
for _, f := range files {
if err := i.AddSyntax(f); err != nil {
return false, err
}
i.BuildFiles = append(i.BuildFiles, &build.File{
Filename: f.Filename,
Encoding: build.CUE,
Source: f,
})
}
return true, nil
}

func (b *buildPlan) singleInstance() *cue.Instance {
var p *build.Instance
switch len(b.insts) {
Expand All @@ -241,8 +352,6 @@ func buildInstances(cmd *Command, binst []*build.Instance) []*cue.Instance {
exitIfErr(cmd, inst, inst.Err, true)
}

decorateInstances(cmd, flagTags.StringArray(cmd), binst)

if flagIgnore.Bool(cmd) {
return instances
}
Expand Down
Loading

0 comments on commit 33c7705

Please sign in to comment.