]>
Commit | Line | Data |
---|---|---|
1 | package discovery | |
2 | ||
3 | import ( | |
4 | "sort" | |
5 | ||
6 | version "github.com/hashicorp/go-version" | |
7 | ) | |
8 | ||
9 | // A ConstraintStr is a string containing a possibly-invalid representation | |
10 | // of a version constraint provided in configuration. Call Parse on it to | |
11 | // obtain a real Constraint object, or discover that it is invalid. | |
12 | type ConstraintStr string | |
13 | ||
14 | // Parse transforms a ConstraintStr into a Constraints if it is | |
15 | // syntactically valid. If it isn't then an error is returned instead. | |
16 | func (s ConstraintStr) Parse() (Constraints, error) { | |
17 | raw, err := version.NewConstraint(string(s)) | |
18 | if err != nil { | |
19 | return Constraints{}, err | |
20 | } | |
21 | return Constraints{raw}, nil | |
22 | } | |
23 | ||
24 | // MustParse is like Parse but it panics if the constraint string is invalid. | |
25 | func (s ConstraintStr) MustParse() Constraints { | |
26 | ret, err := s.Parse() | |
27 | if err != nil { | |
28 | panic(err) | |
29 | } | |
30 | return ret | |
31 | } | |
32 | ||
33 | // Constraints represents a set of versions which any given Version is either | |
34 | // a member of or not. | |
35 | type Constraints struct { | |
36 | raw version.Constraints | |
37 | } | |
38 | ||
39 | // NewConstraints creates a Constraints based on a version.Constraints. | |
40 | func NewConstraints(c version.Constraints) Constraints { | |
41 | return Constraints{c} | |
42 | } | |
43 | ||
44 | // AllVersions is a Constraints containing all versions | |
45 | var AllVersions Constraints | |
46 | ||
47 | func init() { | |
48 | AllVersions = Constraints{ | |
49 | raw: make(version.Constraints, 0), | |
50 | } | |
51 | } | |
52 | ||
53 | // Allows returns true if the given version permitted by the receiving | |
54 | // constraints set. | |
55 | func (s Constraints) Allows(v Version) bool { | |
56 | return s.raw.Check(v.raw) | |
57 | } | |
58 | ||
59 | // Append combines the receiving set with the given other set to produce | |
60 | // a set that is the intersection of both sets, which is to say that resulting | |
61 | // constraints contain only the versions that are members of both. | |
62 | func (s Constraints) Append(other Constraints) Constraints { | |
63 | raw := make(version.Constraints, 0, len(s.raw)+len(other.raw)) | |
64 | ||
65 | // Since "raw" is a list of constraints that remove versions from the set, | |
66 | // "Intersection" is implemented by concatenating together those lists, | |
67 | // thus leaving behind only the versions not removed by either list. | |
68 | raw = append(raw, s.raw...) | |
69 | raw = append(raw, other.raw...) | |
70 | ||
71 | // while the set is unordered, we sort these lexically for consistent output | |
72 | sort.Slice(raw, func(i, j int) bool { | |
73 | return raw[i].String() < raw[j].String() | |
74 | }) | |
75 | ||
76 | return Constraints{raw} | |
77 | } | |
78 | ||
79 | // String returns a string representation of the set members as a set | |
80 | // of range constraints. | |
81 | func (s Constraints) String() string { | |
82 | return s.raw.String() | |
83 | } | |
84 | ||
85 | // Unconstrained returns true if and only if the receiver is an empty | |
86 | // constraint set. | |
87 | func (s Constraints) Unconstrained() bool { | |
88 | return len(s.raw) == 0 | |
89 | } |