Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify asy conditionals and variables data structure #2494

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9ae2dd3
Start unification of vars in conds and tmpls
daved Apr 1, 2023
26a9616
Fix constraints conditional from value construction
daved Apr 12, 2023
904cd4c
Remove unused var tag constant from constraints pkg
daved Apr 12, 2023
96452f4
Start use of reflect in project expander
daved Apr 13, 2023
8a3be7b
Handle func fields in project expander
daved Apr 14, 2023
aa91df0
Fix err handling in project registry funcs
daved Apr 14, 2023
332425c
Merge branch 'version/0-38-0-RC1' into green/fix_cond_vars.DX-1661
daved Apr 14, 2023
ee6ec96
Fix state main imports
daved Apr 14, 2023
35da0fa
Handle asy var func notation
daved Apr 14, 2023
84be8d2
Fix project pkg expander tests
daved Apr 14, 2023
8d1dcb1
Ensure paths are bashified in expansions
daved Apr 14, 2023
44d72ff
Fix expander unit test and usage in parallelize
daved Apr 14, 2023
b6e9c5a
Rename isFunc project expander tag opt to asFunc
daved Apr 14, 2023
ab10a47
Fix project expander unit test for windows
daved Apr 14, 2023
700c073
Add project update callback to keep expander projectvars updated
daved Apr 17, 2023
4e02840
Fix call to primer construction in svc
daved Apr 17, 2023
ca01cfe
Fix call to primer construction in installer
daved Apr 17, 2023
7f2188d
Fix call to primer construction in remote installer
daved Apr 17, 2023
4e898b4
Guard projectfile call in project setupdatecallback
daved Apr 18, 2023
3e6d333
Move project/vars setup to own pkg
daved Apr 18, 2023
9fd0e07
Fix project pkg expander tests
daved Apr 18, 2023
c1b3063
Return nil project when no projectfile provided
daved Apr 18, 2023
5add2d3
Add vars pkg comment
daved Apr 18, 2023
95fe631
Clarify var naming in and add comments to vars work
daved Apr 19, 2023
ad8ca67
Improve more var names and comments for projectfile vars handling
daved Apr 19, 2023
dc47076
Trial direct registration of top level expanders
daved Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/state-installer/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func main() {
"state-installer",
"",
"Installs or updates the State Tool",
primer.New(nil, out, nil, nil, nil, nil, cfg, nil, nil, an),
primer.New(nil, out, nil, nil, nil, cfg, nil, nil, an),
[]*captain.Flag{ // The naming of these flags is slightly inconsistent due to backwards compatibility requirements
{
Name: "command",
Expand Down
2 changes: 1 addition & 1 deletion cmd/state-remote-installer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func main() {
"state-installer",
"",
"Installs or updates the State Tool",
primer.New(nil, out, nil, nil, nil, nil, cfg, nil, nil, an),
primer.New(nil, out, nil, nil, nil, cfg, nil, nil, an),
[]*captain.Flag{ // The naming of these flags is slightly inconsistent due to backwards compatibility requirements
{
Name: "channel",
Expand Down
2 changes: 1 addition & 1 deletion cmd/state-svc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func run(cfg *config.Instance) error {
return runStart(out, "svc-start:mouse")
}

p := primer.New(nil, out, nil, nil, nil, nil, cfg, nil, nil, an)
p := primer.New(nil, out, nil, nil, nil, cfg, nil, nil, an)

cmd := captain.NewCommand(
path.Base(os.Args[0]), "", "", p, nil, nil,
Expand Down
41 changes: 10 additions & 31 deletions cmd/state/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ import (
"strings"
"time"

"github.com/ActiveState/cli/internal/captain"

"github.com/ActiveState/cli/cmd/state/internal/cmdtree"
anAsync "github.com/ActiveState/cli/internal/analytics/client/async"
"github.com/ActiveState/cli/internal/captain"
"github.com/ActiveState/cli/internal/config"
"github.com/ActiveState/cli/internal/constants"
"github.com/ActiveState/cli/internal/constraints"
"github.com/ActiveState/cli/internal/errs"
"github.com/ActiveState/cli/internal/events"
"github.com/ActiveState/cli/internal/installation"
Expand All @@ -39,7 +37,7 @@ import (
"github.com/ActiveState/cli/pkg/platform/authentication"
"github.com/ActiveState/cli/pkg/platform/model"
"github.com/ActiveState/cli/pkg/project"
"github.com/ActiveState/cli/pkg/projectfile"
"github.com/ActiveState/cli/pkg/projget"
)

func main() {
Expand Down Expand Up @@ -171,34 +169,21 @@ func run(args []string, isInteractive bool, cfg *config.Instance, out output.Out
return logData
})

// Retrieve project file
pjPath, err := projectfile.GetProjectFilePath()
if err != nil && errs.Matches(err, &projectfile.ErrorNoProjectFromEnv{}) {
// Fail if we are meant to inherit the projectfile from the environment, but the file doesn't exist
return err
}
auth := authentication.New(cfg)
defer events.Close("auth", auth.Close)

// Set up project (if we have a valid path)
var pj *project.Project
if pjPath != "" {
pjf, err := projectfile.FromPath(pjPath)
if err != nil {
return err
}
pj, err = project.New(pjf, out)
if err != nil {
return err
}
sshell := subshell.New(cfg)

pj, err := projget.NewProject(out, auth, sshell.Shell())
if err != nil {
return err
}

pjNamespace := ""
if pj != nil {
pjNamespace = pj.Namespace().String()
}

auth := authentication.New(cfg)
defer events.Close("auth", auth.Close)

if err := auth.Sync(); err != nil {
logging.Warning("Could not sync authenticated state: %s", err.Error())
}
Expand All @@ -213,16 +198,10 @@ func run(args []string, isInteractive bool, cfg *config.Instance, out output.Out
// Set up prompter
prompter := prompt.New(isInteractive, an)

// Set up conditional, which accesses a lot of primer data
sshell := subshell.New(cfg)

conditional := constraints.NewPrimeConditional(auth, pj, sshell.Shell())
project.RegisterConditional(conditional)
project.RegisterExpander("mixin", project.NewMixin(auth).Expander)
project.RegisterExpander("secrets", project.NewSecretPromptingExpander(secretsapi.Get(), prompter, cfg, auth))

// Run the actual command
cmds := cmdtree.New(primer.New(pj, out, auth, prompter, sshell, conditional, cfg, ipcClient, svcmodel, an), args...)
cmds := cmdtree.New(primer.New(pj, out, auth, prompter, sshell, cfg, ipcClient, svcmodel, an), args...)

childCmd, err := cmds.Command().Find(args[1:])
if err != nil {
Expand Down
112 changes: 28 additions & 84 deletions internal/constraints/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package constraints
import (
"bytes"
"fmt"
"path/filepath"
"reflect"
"regexp"
"sort"
"strings"
Expand All @@ -12,27 +12,10 @@ import (
"github.com/ActiveState/cli/internal/locale"
"github.com/ActiveState/cli/internal/logging"
"github.com/ActiveState/cli/internal/multilog"
"github.com/ActiveState/cli/internal/rtutils/p"
"github.com/ActiveState/cli/pkg/platform/authentication"
"github.com/ActiveState/cli/pkg/projectfile"
"github.com/ActiveState/cli/pkg/sysinfo"
"github.com/thoas/go-funk"
)

var cache = make(map[string]interface{})

func getCache(key string, getter func() (interface{}, error)) (interface{}, error) {
if v, ok := cache[key]; ok {
return v, nil
}
v, err := getter()
if err != nil {
return nil, err
}
cache[key] = v
return v, err
}

// For testing.
var osOverride, osVersionOverride, archOverride, libcOverride, compilerOverride string

Expand All @@ -41,22 +24,9 @@ type Conditional struct {
funcs template.FuncMap
}

func NewConditional(a *authentication.Auth) *Conditional {
func NewConditional() *Conditional {
c := &Conditional{map[string]interface{}{}, map[string]interface{}{}}

c.RegisterFunc("Mixin", func() map[string]interface{} {
res := map[string]string{
"Name": "",
"Email": "",
}
if a.Authenticated() {
res["Name"] = a.WhoAmI()
res["Email"] = a.Email()
}
return map[string]interface{}{
"User": res,
}
})
c.RegisterFunc("Contains", funk.Contains)
c.RegisterFunc("HasPrefix", strings.HasPrefix)
c.RegisterFunc("HasSuffix", strings.HasSuffix)
Expand All @@ -72,62 +42,36 @@ func NewConditional(a *authentication.Auth) *Conditional {
return c
}

type projectable interface {
Owner() string
Name() string
NamespaceString() string
CommitID() string
BranchName() string
Path() string
URL() string
}
func NewPrimeConditional(structure interface{}) *Conditional {
c := NewConditional()

func NewPrimeConditional(auth *authentication.Auth, pj projectable, subshellName string) *Conditional {
var (
pjOwner string
pjName string
pjNamespace string
pjURL string
pjCommit string
pjBranch string
pjPath string
)
if !p.IsNil(pj) {
pjOwner = pj.Owner()
pjName = pj.Name()
pjNamespace = pj.NamespaceString()
pjURL = pj.URL()
pjCommit = pj.CommitID()
pjBranch = pj.BranchName()
pjPath = pj.Path()
if pjPath != "" {
pjPath = filepath.Dir(pjPath)
}
v := reflect.ValueOf(structure)
// deref if needed
if v.Kind() == reflect.Ptr {
v = v.Elem()
}

c := NewConditional(auth)
c.RegisterParam("Project", map[string]string{
"Owner": pjOwner,
"Name": pjName,
"Namespace": pjNamespace,
"Url": pjURL,
"Commit": pjCommit,
"Branch": pjBranch,
"Path": pjPath,

// Legacy
"NamespacePrefix": pjNamespace,
})
osVersion, err := sysinfo.OSVersion()
if err != nil {
multilog.Error("Could not detect OSVersion: %v", err)
fields := reflect.VisibleFields(v.Type())

// Work at depth 1: Vars.[Struct].Struct.Simple
for _, f := range fields {
d1Val := v.FieldByIndex(f.Index)
if d1Val.Kind() == reflect.Ptr {
d1Val = d1Val.Elem()
}

// Only nodes at depth 1 need to be registered since the generic type
// handling within the templating package will do the rest. If function
// registration is needed at greater depths, this will need to be
// reworked (and may not be possible without expansive refactoring).
switch d1Val.Type().Kind() {
case reflect.Func:
c.RegisterFunc(f.Name, d1Val.Interface())

default:
c.RegisterParam(f.Name, d1Val.Interface())
}
}
c.RegisterParam("OS", map[string]interface{}{
"Name": sysinfo.OS().String(),
"Version": osVersion,
"Architecture": sysinfo.Architecture().String(),
})
c.RegisterParam("Shell", subshellName)

return c
}
Expand Down
29 changes: 9 additions & 20 deletions internal/primer/primer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package primer
import (
"github.com/ActiveState/cli/internal/analytics"
"github.com/ActiveState/cli/internal/config"
"github.com/ActiveState/cli/internal/constraints"
"github.com/ActiveState/cli/internal/output"
"github.com/ActiveState/cli/internal/prompt"
"github.com/ActiveState/cli/internal/subshell"
Expand All @@ -21,7 +20,6 @@ type Values struct {
auth *authentication.Auth
prompt prompt.Prompter
subshell subshell.SubShell
conditional *constraints.Conditional
config *config.Instance
ipComm svcctl.IPCommunicator
svcModel *model.SvcModel
Expand All @@ -30,19 +28,18 @@ type Values struct {

func New(
project *project.Project, output output.Outputer, auth *authentication.Auth, prompt prompt.Prompter,
subshell subshell.SubShell, conditional *constraints.Conditional, config *config.Instance,
subshell subshell.SubShell, config *config.Instance,
ipComm svcctl.IPCommunicator, svcModel *model.SvcModel, an analytics.Dispatcher) *Values {

v := &Values{
output: output,
auth: auth,
prompt: prompt,
subshell: subshell,
conditional: conditional,
config: config,
ipComm: ipComm,
svcModel: svcModel,
analytics: an,
output: output,
auth: auth,
prompt: prompt,
subshell: subshell,
config: config,
ipComm: ipComm,
svcModel: svcModel,
analytics: an,
}
if project != nil {
v.project = project
Expand Down Expand Up @@ -91,10 +88,6 @@ type Subsheller interface {
Subshell() subshell.SubShell
}

type Conditioner interface {
Conditional() *constraints.Conditional
}

func (v *Values) Project() *project.Project {
return v.project
}
Expand Down Expand Up @@ -127,10 +120,6 @@ func (v *Values) SvcModel() *model.SvcModel {
return v.svcModel
}

func (v *Values) Conditional() *constraints.Conditional {
return v.conditional
}

func (v *Values) Config() *config.Instance {
return v.config
}
Expand Down
Loading