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

Revert "Merge branch version/0-47-0-RC1 to adopt changes from PR #3531" #3538

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
89 changes: 14 additions & 75 deletions pkg/buildscript/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"strings"

"github.com/go-openapi/strfmt"
"github.com/thoas/go-funk"

"github.com/ActiveState/cli/internal/errs"
"github.com/ActiveState/cli/pkg/platform/api/buildplanner/types"
Expand All @@ -13,7 +12,6 @@ import (
const (
solveFuncName = "solve"
solveLegacyFuncName = "solve_legacy"
srcKey = "src"
requirementsKey = "requirements"
platformsKey = "platforms"
)
Expand Down Expand Up @@ -45,10 +43,8 @@ type UnknownRequirement struct {

func (r UnknownRequirement) IsRequirement() {}

// Returns the requirements for the given target.
// If no target is given, uses the default target (i.e. the name assigned to 'main').
func (b *BuildScript) Requirements(targets ...string) ([]Requirement, error) {
requirementsNode, err := b.getRequirementsNode(targets...)
func (b *BuildScript) Requirements() ([]Requirement, error) {
requirementsNode, err := b.getRequirementsNode()
if err != nil {
return nil, errs.Wrap(err, "Could not get requirements node")
}
Expand Down Expand Up @@ -99,8 +95,8 @@ func (b *BuildScript) Requirements(targets ...string) ([]Requirement, error) {
// DependencyRequirements is identical to Requirements except that it only considers dependency type requirements,
// which are the most common.
// ONLY use this when you know you only need to care about dependencies.
func (b *BuildScript) DependencyRequirements(targets ...string) ([]types.Requirement, error) {
reqs, err := b.Requirements(targets...)
func (b *BuildScript) DependencyRequirements() ([]types.Requirement, error) {
reqs, err := b.Requirements()
if err != nil {
return nil, errs.Wrap(err, "Could not get requirements")
}
Expand All @@ -113,8 +109,8 @@ func (b *BuildScript) DependencyRequirements(targets ...string) ([]types.Require
return deps, nil
}

func (b *BuildScript) getRequirementsNode(targets ...string) (*Value, error) {
node, err := b.getSolveNode(targets...)
func (b *BuildScript) getRequirementsNode() (*Value, error) {
node, err := b.getSolveNode()
if err != nil {
return nil, errs.Wrap(err, "Could not get solve node")
}
Expand Down Expand Up @@ -151,23 +147,7 @@ func getVersionRequirements(v *Value) []types.VersionRequirement {
return reqs
}

func isSolveFuncName(name string) bool {
return name == solveFuncName || name == solveLegacyFuncName
}

func (b *BuildScript) getTargetSolveNode(targets ...string) (*Value, error) {
if len(targets) == 0 {
for _, assignment := range b.raw.Assignments {
if assignment.Key != mainKey {
continue
}
if assignment.Value.Ident != nil && *assignment.Value.Ident != "" {
targets = []string{*assignment.Value.Ident}
break
}
}
}

func (b *BuildScript) getSolveNode() (*Value, error) {
var search func([]*Assignment) *Value
search = func(assignments []*Assignment) *Value {
var nextLet []*Assignment
Expand All @@ -177,13 +157,7 @@ func (b *BuildScript) getTargetSolveNode(targets ...string) (*Value, error) {
continue
}

if funk.Contains(targets, a.Key) && a.Value.FuncCall != nil {
return a.Value
}

if f := a.Value.FuncCall; len(targets) == 0 && f != nil && isSolveFuncName(f.Name) {
// This is coming from a complex build expression with no straightforward way to determine
// a default target. Fall back on a top-level solve node.
if f := a.Value.FuncCall; f != nil && (f.Name == solveFuncName || f.Name == solveLegacyFuncName) {
return a.Value
}
}
Expand All @@ -195,50 +169,15 @@ func (b *BuildScript) getTargetSolveNode(targets ...string) (*Value, error) {

return nil
}

if node := search(b.raw.Assignments); node != nil {
return node, nil
}
return nil, errNodeNotFound
}

func (b *BuildScript) getSolveNode(targets ...string) (*Value, error) {
node, err := b.getTargetSolveNode(targets...)
if err != nil {
return nil, errs.Wrap(err, "Could not get target node")
}

// If the target is the solve function, we're done.
if isSolveFuncName(node.FuncCall.Name) {
return node, nil
}

// Otherwise, the "src" key contains a reference to the solve node.
// For example:
//
// runtime = state_tool_artifacts_v1(src = sources)
// sources = solve(at_time = ..., platforms = [...], requirements = [...], ...)
//
// Look over the build expression again for that referenced node.
for _, arg := range node.FuncCall.Arguments {
if arg.Assignment == nil {
continue
}
a := arg.Assignment
if a.Key == srcKey && a.Value.Ident != nil {
node, err := b.getSolveNode(*a.Value.Ident)
if err != nil {
return nil, errs.Wrap(err, "Could not get solve node from target")
}
return node, nil
}
}

return nil, errNodeNotFound
}

func (b *BuildScript) getSolveAtTimeValue(targets ...string) (*Value, error) {
node, err := b.getSolveNode(targets...)
func (b *BuildScript) getSolveAtTimeValue() (*Value, error) {
node, err := b.getSolveNode()
if err != nil {
return nil, errs.Wrap(err, "Could not get solve node")
}
Expand All @@ -252,8 +191,8 @@ func (b *BuildScript) getSolveAtTimeValue(targets ...string) (*Value, error) {
return nil, errValueNotFound
}

func (b *BuildScript) Platforms(targets ...string) ([]strfmt.UUID, error) {
node, err := b.getPlatformsNode(targets...)
func (b *BuildScript) Platforms() ([]strfmt.UUID, error) {
node, err := b.getPlatformsNode()
if err != nil {
return nil, errs.Wrap(err, "Could not get platform node")
}
Expand All @@ -265,8 +204,8 @@ func (b *BuildScript) Platforms(targets ...string) ([]strfmt.UUID, error) {
return list, nil
}

func (b *BuildScript) getPlatformsNode(targets ...string) (*Value, error) {
node, err := b.getSolveNode(targets...)
func (b *BuildScript) getPlatformsNode() (*Value, error) {
node, err := b.getSolveNode()
if err != nil {
return nil, errs.Wrap(err, "Could not get solve node")
}
Expand Down
10 changes: 0 additions & 10 deletions pkg/buildscript/unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,5 @@ func Unmarshal(data []byte) (*BuildScript, error) {
break
}

// Verify there are no duplicate key assignments.
// This is primarily to catch duplicate solve nodes for a given target.
seen := make(map[string]bool)
for _, assignment := range raw.Assignments {
if _, exists := seen[assignment.Key]; exists {
return nil, locale.NewInputError(locale.Tl("err_buildscript_duplicate_keys", "Build script has duplicate '{{.V0}}' assignments", assignment.Key))
}
seen[assignment.Key] = true
}

return &BuildScript{raw}, nil
}
19 changes: 12 additions & 7 deletions pkg/buildscript/unmarshal_buildexpression.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ func UnmarshalBuildExpression(data []byte, atTime *time.Time) (*BuildScript, err
script.raw.AtTime = atTime
}

// If the requirements are in legacy object form, e.g.
// requirements = [{"name": "<name>", "namespace": "<name>"}, {...}, ...]
// then transform them into function call form for the AScript format, e.g.
// requirements = [Req(name = "<name>", namespace = "<name>"), Req(...), ...]
requirements, err := script.getRequirementsNode()
if err != nil {
return nil, errs.Wrap(err, "Could not get requirements node")
}
if isLegacyRequirementsList(requirements) {
requirements.List = transformRequirements(requirements).List
}

return script, nil
}

Expand Down Expand Up @@ -258,13 +270,6 @@ func unmarshalFuncCall(path []string, m map[string]interface{}) (*FuncCall, erro
if err != nil {
return nil, errs.Wrap(err, "Could not parse '%s' function's argument '%s': %v", name, key, valueInterface)
}
if key == requirementsKey && isSolveFuncName(name) && isLegacyRequirementsList(value) {
// If the requirements are in legacy object form, e.g.
// requirements = [{"name": "<name>", "namespace": "<name>"}, {...}, ...]
// then transform them into function call form for the AScript format, e.g.
// requirements = [Req(name = "<name>", namespace = "<name>"), Req(...), ...]
value.List = transformRequirements(value).List
}
args = append(args, &Value{Assignment: &Assignment{key, value}})
}
sort.SliceStable(args, func(i, j int) bool { return args[i].Assignment.Key < args[j].Assignment.Key })
Expand Down
Loading