Files
steampipe/pkg/steampipeconfig/modconfig/mod_version_constraint.go

115 lines
3.1 KiB
Go

package modconfig
import (
"fmt"
"strings"
"github.com/hashicorp/hcl/v2"
"github.com/turbot/go-kit/helpers"
"github.com/turbot/steampipe/pkg/versionhelpers"
"github.com/zclconf/go-cty/cty"
)
const filePrefix = "file:"
type VersionConstrainCollection []*ModVersionConstraint
type ModVersionConstraint struct {
// the fully qualified mod name, e.g. github.com/turbot/mod1
Name string `cty:"name" hcl:"name,label"`
VersionString string `cty:"version" hcl:"version"`
// variable values to be set on the dependency mod
Args map[string]cty.Value `cty:"args" hcl:"args,optional"`
// only one of Constraint, Branch and FilePath will be set
Constraint *versionhelpers.Constraints
// the local file location to use
FilePath string
DeclRange hcl.Range
}
// NewModVersionConstraint creates a new ModVersionConstraint - this is called when installing a mod
func NewModVersionConstraint(modFullName string) (*ModVersionConstraint, error) {
m := &ModVersionConstraint{
Args: make(map[string]cty.Value),
}
// if name has `file:` prefix, just set the name and ignore version
if strings.HasPrefix(modFullName, filePrefix) {
m.Name = modFullName
} else {
// otherwise try to extract version from name
segments := strings.Split(modFullName, "@")
if len(segments) > 2 {
return nil, fmt.Errorf("invalid mod name %s", modFullName)
}
m.Name = segments[0]
if len(segments) == 2 {
m.VersionString = segments[1]
}
}
// try to convert version into a semver constraint
if err := m.Initialise(nil); err != nil {
return nil, err
}
return m, nil
}
// Initialise parses the version and name properties
func (m *ModVersionConstraint) Initialise(block *hcl.Block) hcl.Diagnostics {
if block != nil {
m.DeclRange = block.DefRange
}
if strings.HasPrefix(m.Name, filePrefix) {
m.setFilePath()
return nil
}
// now default the version string to latest
if m.VersionString == "" || m.VersionString == "latest" {
m.VersionString = "*"
}
// does the version parse as a semver version
if c, err := versionhelpers.NewConstraint(m.VersionString); err == nil {
// no error
m.Constraint = c
return nil
}
// so there was an error
return hcl.Diagnostics{&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: fmt.Sprintf("invalid mod version %s", m.VersionString),
Subject: &m.DeclRange,
}}
}
func (m *ModVersionConstraint) DependencyPath() string {
if m.HasVersion() {
return fmt.Sprintf("%s@%s", m.Name, m.VersionString)
}
return m.Name
}
// HasVersion returns whether the mod has a version specified, or is the latest
// if no version is specified, or the version is "latest", this is the latest version
func (m *ModVersionConstraint) HasVersion() bool {
return !helpers.StringSliceContains([]string{"", "latest", "*"}, m.VersionString)
}
func (m *ModVersionConstraint) String() string {
return m.DependencyPath()
}
func (m *ModVersionConstraint) setFilePath() {
m.FilePath = strings.TrimPrefix(m.FilePath, filePrefix)
}
func (m *ModVersionConstraint) Equals(other *ModVersionConstraint) bool {
// just check the hcl properties
return m.Name == other.Name && m.VersionString == other.VersionString
}