Skip to content

Commit

Permalink
internal/cueexperiment: parse CUE_EXPERIMENT
Browse files Browse the repository at this point in the history
This allows code the cue command to enable experimentation with new
features, and modules in particular to start with.

In the future, this API might be adapted to allow enabling
experimental features in the Go API too, but for now it's
firmly oriented towards the top level cue command.

Signed-off-by: Roger Peppe <[email protected]>
Change-Id: I76d5c9343bd791ae0ff9ef39fdf7af9dec5c2d8f
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1168930
Reviewed-by: Daniel Martí <[email protected]>
Reviewed-by: Paul Jolly <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
  • Loading branch information
rogpeppe committed Sep 26, 2023
1 parent b951b07 commit b4583de
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
5 changes: 5 additions & 0 deletions cmd/cue/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"cuelang.org/go/cue/interpreter/wasm"
"cuelang.org/go/cue/stats"
"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/cueexperiment"
"cuelang.org/go/internal/encoding"
"cuelang.org/go/internal/filetypes"
)
Expand Down Expand Up @@ -84,6 +85,10 @@ func mkRunE(c *Command, f runFunction) func(*cobra.Command, []string) error {

statsEnc := statsEncoder(c)

if err := cueexperiment.Init(); err != nil {
return err
}

err := f(c, args)

if statsEnc != nil {
Expand Down
3 changes: 3 additions & 0 deletions cmd/cue/cmd/testdata/script/experiment_unknown.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
env CUE_EXPERIMENT=xxx
! exec cue eval something
stderr 'unknown CUE_EXPERIMENT xxx'
40 changes: 40 additions & 0 deletions internal/cueexperiment/exp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cueexperiment

import (
"fmt"
"os"
"reflect"
"strings"
)

// Flags holds the set of CUE_EXPERIMENT flags. It is initialized
// by Init.
var Flags struct {
Modules bool
}

// Init initializes Flags. Note: this isn't named "init" because we
// don't always want it to be called (for example we don't want it to be
// called when running "cue help"), and also because we want the failure
// mode to be one of error not panic, which would be the only option if
// it was a top level init function
func Init() error {
exp := os.Getenv("CUE_EXPERIMENT")
if exp == "" {
return nil
}
names := make(map[string]int)
fv := reflect.ValueOf(&Flags).Elem()
ft := fv.Type()
for i := 0; i < ft.NumField(); i++ {
names[strings.ToLower(ft.Field(i).Name)] = i
}
for _, uexp := range strings.Split(exp, ",") {
index, ok := names[uexp]
if !ok {
return fmt.Errorf("unknown CUE_EXPERIMENT %s", uexp)
}
fv.Field(index).SetBool(true)
}
return nil
}
60 changes: 60 additions & 0 deletions internal/cueexperiment/exp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cueexperiment

import (
"testing"

"github.com/go-quicktest/qt"
)

var tests = []struct {
testName string
cueExperiment string
flagVal *bool
want bool
wantError string
}{{
testName: "Empty",
cueExperiment: "",
flagVal: &Flags.Modules,
want: false,
}, {
testName: "Unknown",
cueExperiment: "foo",
flagVal: &Flags.Modules,
wantError: "unknown CUE_EXPERIMENT foo",
}, {
testName: "Set",
cueExperiment: "modules",
flagVal: &Flags.Modules,
want: true,
}, {
testName: "SetTwice",
cueExperiment: "modules,modules",
flagVal: &Flags.Modules,
want: true,
}, {
testName: "SetWithUnknown",
cueExperiment: "modules,other",
flagVal: &Flags.Modules,
wantError: "unknown CUE_EXPERIMENT other",
}}

func TestInit(t *testing.T) {
for _, test := range tests {
t.Run(test.testName, func(t *testing.T) {
setZero(&Flags)
t.Setenv("CUE_EXPERIMENT", test.cueExperiment)
err := Init()
if test.wantError != "" {
qt.Assert(t, qt.ErrorMatches(err, test.wantError))
return
}
qt.Assert(t, qt.IsNil(err))
qt.Assert(t, qt.Equals(*test.flagVal, test.want))
})
}
}

func setZero[T any](x *T) {
*x = *new(T)
}

0 comments on commit b4583de

Please sign in to comment.