internal: Suppress duplicate version constraints
A set of version constraints can contain duplicates. This can happen if multiple identical constraints are specified throughout a configuration. When rendering the set, it is confusing to display redundant constraints. This commit changes the string renderer to only show the first instance of a given constraint, and adds unit tests for this function to cover this change. This also fixes a bug with the locks file generation: previously, a configuration with redundant constraints would result in this error on second init: Error: Invalid provider version constraints on .terraform.lock.hcl line 6: (source code not available) The recorded version constraints for provider registry.terraform.io/hashicorp/random must be written in normalized form: "3.0.0".
This commit is contained in:
parent
bc1a841d65
commit
fe9a9fadfb
|
@ -395,8 +395,16 @@ func VersionConstraintsString(spec VersionConstraints) string {
|
||||||
// lock files. Therefore the canonical forms produced here are a compatibility
|
// lock files. Therefore the canonical forms produced here are a compatibility
|
||||||
// constraint for the dependency lock file parser.
|
// constraint for the dependency lock file parser.
|
||||||
|
|
||||||
|
// Keep track of selection specifications which have been seen, so that we
|
||||||
|
// don't repeat the same constraint multiple times.
|
||||||
|
rendered := make(map[constraints.SelectionSpec]struct{})
|
||||||
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
for i, sel := range spec {
|
for i, sel := range spec {
|
||||||
|
// If we've already rendered this selection spec, skip it.
|
||||||
|
if _, exists := rendered[sel]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b.WriteString(", ")
|
b.WriteString(", ")
|
||||||
}
|
}
|
||||||
|
@ -451,6 +459,9 @@ func VersionConstraintsString(spec VersionConstraints) string {
|
||||||
if sel.Boundary.Metadata != "" {
|
if sel.Boundary.Metadata != "" {
|
||||||
b.WriteString("+" + boundary.Metadata)
|
b.WriteString("+" + boundary.Metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark this selection spec as rendered.
|
||||||
|
rendered[sel] = struct{}{}
|
||||||
}
|
}
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package getproviders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVersionConstraintsString(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
spec VersionConstraints
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
"exact": {
|
||||||
|
MustParseVersionConstraints("1.2.3"),
|
||||||
|
"1.2.3",
|
||||||
|
},
|
||||||
|
"prerelease": {
|
||||||
|
MustParseVersionConstraints("1.2.3-beta"),
|
||||||
|
"1.2.3-beta",
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
MustParseVersionConstraints("1.2.3+foo.bar"),
|
||||||
|
"1.2.3+foo.bar",
|
||||||
|
},
|
||||||
|
"prerelease and metadata": {
|
||||||
|
MustParseVersionConstraints("1.2.3-beta+foo.bar"),
|
||||||
|
"1.2.3-beta+foo.bar",
|
||||||
|
},
|
||||||
|
"major only": {
|
||||||
|
MustParseVersionConstraints(">= 3"),
|
||||||
|
">= 3.0.0",
|
||||||
|
},
|
||||||
|
"major only with pessimistic operator": {
|
||||||
|
MustParseVersionConstraints("~> 3"),
|
||||||
|
"~> 3.0",
|
||||||
|
},
|
||||||
|
"pessimistic minor": {
|
||||||
|
MustParseVersionConstraints("~> 3.0"),
|
||||||
|
"~> 3.0",
|
||||||
|
},
|
||||||
|
"pessimistic patch": {
|
||||||
|
MustParseVersionConstraints("~> 3.0.0"),
|
||||||
|
"~> 3.0.0",
|
||||||
|
},
|
||||||
|
"other operators": {
|
||||||
|
MustParseVersionConstraints("> 1.0.0, < 1.0.0, >= 1.0.0, <= 1.0.0, != 1.0.0"),
|
||||||
|
"> 1.0.0, < 1.0.0, >= 1.0.0, <= 1.0.0, != 1.0.0",
|
||||||
|
},
|
||||||
|
"multiple": {
|
||||||
|
MustParseVersionConstraints(">= 3.0, < 4.0"),
|
||||||
|
">= 3.0.0, < 4.0.0",
|
||||||
|
},
|
||||||
|
"duplicates removed": {
|
||||||
|
MustParseVersionConstraints(">= 1.2.3, 1.2.3, ~> 1.2, 1.2.3"),
|
||||||
|
">= 1.2.3, 1.2.3, ~> 1.2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
got := VersionConstraintsString(tc.spec)
|
||||||
|
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("wrong\n got: %q\nwant: %q", got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue