@@ -12,6 +12,7 @@ import (
1212// checked against.
1313type Constraints struct {
1414 constraints [][]* constraint
15+ containsPre []bool
1516}
1617
1718// NewConstraint returns a Constraints instance that a Version instance can
@@ -22,11 +23,10 @@ func NewConstraint(c string) (*Constraints, error) {
2223 c = rewriteRange (c )
2324
2425 ors := strings .Split (c , "||" )
25- or := make ([][]* constraint , len (ors ))
26+ lenors := len (ors )
27+ or := make ([][]* constraint , lenors )
28+ hasPre := make ([]bool , lenors )
2629 for k , v := range ors {
27-
28- // TODO: Find a way to validate and fetch all the constraints in a simpler form
29-
3030 // Validate the segment
3131 if ! validConstraintRegex .MatchString (v ) {
3232 return nil , fmt .Errorf ("improper constraint: %s" , v )
@@ -43,12 +43,22 @@ func NewConstraint(c string) (*Constraints, error) {
4343 return nil , err
4444 }
4545
46+ // If one of the constraints has a prerelease record this.
47+ // This information is used when checking all in an "and"
48+ // group to ensure they all check for prereleases.
49+ if pc .con .pre != "" {
50+ hasPre [k ] = true
51+ }
52+
4653 result [i ] = pc
4754 }
4855 or [k ] = result
4956 }
5057
51- o := & Constraints {constraints : or }
58+ o := & Constraints {
59+ constraints : or ,
60+ containsPre : hasPre ,
61+ }
5262 return o , nil
5363}
5464
@@ -57,10 +67,10 @@ func (cs Constraints) Check(v *Version) bool {
5767 // TODO(mattfarina): For v4 of this library consolidate the Check and Validate
5868 // functions as the underlying functions make that possible now.
5969 // loop over the ORs and check the inner ANDs
60- for _ , o := range cs .constraints {
70+ for i , o := range cs .constraints {
6171 joy := true
6272 for _ , c := range o {
63- if check , _ := c .check (v ); ! check {
73+ if check , _ := c .check (v , cs . containsPre [ i ] ); ! check {
6474 joy = false
6575 break
6676 }
@@ -83,12 +93,12 @@ func (cs Constraints) Validate(v *Version) (bool, []error) {
8393 // Capture the prerelease message only once. When it happens the first time
8494 // this var is marked
8595 var prerelesase bool
86- for _ , o := range cs .constraints {
96+ for i , o := range cs .constraints {
8797 joy := true
8898 for _ , c := range o {
8999 // Before running the check handle the case there the version is
90100 // a prerelease and the check is not searching for prereleases.
91- if c . con . pre == "" && v .pre != "" {
101+ if ! cs . containsPre [ i ] && v .pre != "" {
92102 if ! prerelesase {
93103 em := fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
94104 e = append (e , em )
@@ -98,7 +108,7 @@ func (cs Constraints) Validate(v *Version) (bool, []error) {
98108
99109 } else {
100110
101- if _ , err := c .check (v ); err != nil {
111+ if _ , err := c .check (v , cs . containsPre [ i ] ); err != nil {
102112 e = append (e , err )
103113 joy = false
104114 }
@@ -227,16 +237,16 @@ type constraint struct {
227237}
228238
229239// Check if a version meets the constraint
230- func (c * constraint ) check (v * Version ) (bool , error ) {
231- return constraintOps [c.origfunc ](v , c )
240+ func (c * constraint ) check (v * Version , includePre bool ) (bool , error ) {
241+ return constraintOps [c.origfunc ](v , c , includePre )
232242}
233243
234244// String prints an individual constraint into a string
235245func (c * constraint ) string () string {
236246 return c .origfunc + c .orig
237247}
238248
239- type cfunc func (v * Version , c * constraint ) (bool , error )
249+ type cfunc func (v * Version , c * constraint , includePre bool ) (bool , error )
240250
241251func parseConstraint (c string ) (* constraint , error ) {
242252 if len (c ) > 0 {
@@ -305,16 +315,14 @@ func parseConstraint(c string) (*constraint, error) {
305315}
306316
307317// Constraint functions
308- func constraintNotEqual (v * Version , c * constraint ) (bool , error ) {
309- if c .dirty {
310-
311- // If there is a pre-release on the version but the constraint isn't looking
312- // for them assume that pre-releases are not compatible. See issue 21 for
313- // more details.
314- if v .Prerelease () != "" && c .con .Prerelease () == "" {
315- return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
316- }
318+ func constraintNotEqual (v * Version , c * constraint , includePre bool ) (bool , error ) {
319+ // The existence of prereleases is checked at the group level and passed in.
320+ // Exit early if the version has a prerelease but those are to be ignored.
321+ if v .Prerelease () != "" && ! includePre {
322+ return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
323+ }
317324
325+ if c .dirty {
318326 if c .con .Major () != v .Major () {
319327 return true , nil
320328 }
@@ -345,12 +353,11 @@ func constraintNotEqual(v *Version, c *constraint) (bool, error) {
345353 return true , nil
346354}
347355
348- func constraintGreaterThan (v * Version , c * constraint ) (bool , error ) {
356+ func constraintGreaterThan (v * Version , c * constraint , includePre bool ) (bool , error ) {
349357
350- // If there is a pre-release on the version but the constraint isn't looking
351- // for them assume that pre-releases are not compatible. See issue 21 for
352- // more details.
353- if v .Prerelease () != "" && c .con .Prerelease () == "" {
358+ // The existence of prereleases is checked at the group level and passed in.
359+ // Exit early if the version has a prerelease but those are to be ignored.
360+ if v .Prerelease () != "" && ! includePre {
354361 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
355362 }
356363
@@ -391,11 +398,10 @@ func constraintGreaterThan(v *Version, c *constraint) (bool, error) {
391398 return false , fmt .Errorf ("%s is less than or equal to %s" , v , c .orig )
392399}
393400
394- func constraintLessThan (v * Version , c * constraint ) (bool , error ) {
395- // If there is a pre-release on the version but the constraint isn't looking
396- // for them assume that pre-releases are not compatible. See issue 21 for
397- // more details.
398- if v .Prerelease () != "" && c .con .Prerelease () == "" {
401+ func constraintLessThan (v * Version , c * constraint , includePre bool ) (bool , error ) {
402+ // The existence of prereleases is checked at the group level and passed in.
403+ // Exit early if the version has a prerelease but those are to be ignored.
404+ if v .Prerelease () != "" && ! includePre {
399405 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
400406 }
401407
@@ -406,12 +412,11 @@ func constraintLessThan(v *Version, c *constraint) (bool, error) {
406412 return false , fmt .Errorf ("%s is greater than or equal to %s" , v , c .orig )
407413}
408414
409- func constraintGreaterThanEqual (v * Version , c * constraint ) (bool , error ) {
415+ func constraintGreaterThanEqual (v * Version , c * constraint , includePre bool ) (bool , error ) {
410416
411- // If there is a pre-release on the version but the constraint isn't looking
412- // for them assume that pre-releases are not compatible. See issue 21 for
413- // more details.
414- if v .Prerelease () != "" && c .con .Prerelease () == "" {
417+ // The existence of prereleases is checked at the group level and passed in.
418+ // Exit early if the version has a prerelease but those are to be ignored.
419+ if v .Prerelease () != "" && ! includePre {
415420 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
416421 }
417422
@@ -422,11 +427,10 @@ func constraintGreaterThanEqual(v *Version, c *constraint) (bool, error) {
422427 return false , fmt .Errorf ("%s is less than %s" , v , c .orig )
423428}
424429
425- func constraintLessThanEqual (v * Version , c * constraint ) (bool , error ) {
426- // If there is a pre-release on the version but the constraint isn't looking
427- // for them assume that pre-releases are not compatible. See issue 21 for
428- // more details.
429- if v .Prerelease () != "" && c .con .Prerelease () == "" {
430+ func constraintLessThanEqual (v * Version , c * constraint , includePre bool ) (bool , error ) {
431+ // The existence of prereleases is checked at the group level and passed in.
432+ // Exit early if the version has a prerelease but those are to be ignored.
433+ if v .Prerelease () != "" && ! includePre {
430434 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
431435 }
432436
@@ -455,11 +459,10 @@ func constraintLessThanEqual(v *Version, c *constraint) (bool, error) {
455459// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
456460// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
457461// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
458- func constraintTilde (v * Version , c * constraint ) (bool , error ) {
459- // If there is a pre-release on the version but the constraint isn't looking
460- // for them assume that pre-releases are not compatible. See issue 21 for
461- // more details.
462- if v .Prerelease () != "" && c .con .Prerelease () == "" {
462+ func constraintTilde (v * Version , c * constraint , includePre bool ) (bool , error ) {
463+ // The existence of prereleases is checked at the group level and passed in.
464+ // Exit early if the version has a prerelease but those are to be ignored.
465+ if v .Prerelease () != "" && ! includePre {
463466 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
464467 }
465468
@@ -487,16 +490,15 @@ func constraintTilde(v *Version, c *constraint) (bool, error) {
487490
488491// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
489492// it's a straight =
490- func constraintTildeOrEqual (v * Version , c * constraint ) (bool , error ) {
491- // If there is a pre-release on the version but the constraint isn't looking
492- // for them assume that pre-releases are not compatible. See issue 21 for
493- // more details.
494- if v .Prerelease () != "" && c .con .Prerelease () == "" {
493+ func constraintTildeOrEqual (v * Version , c * constraint , includePre bool ) (bool , error ) {
494+ // The existence of prereleases is checked at the group level and passed in.
495+ // Exit early if the version has a prerelease but those are to be ignored.
496+ if v .Prerelease () != "" && ! includePre {
495497 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
496498 }
497499
498500 if c .dirty {
499- return constraintTilde (v , c )
501+ return constraintTilde (v , c , includePre )
500502 }
501503
502504 eq := v .Equal (c .con )
@@ -516,11 +518,10 @@ func constraintTildeOrEqual(v *Version, c *constraint) (bool, error) {
516518// ^0.0.3 --> >=0.0.3 <0.0.4
517519// ^0.0 --> >=0.0.0 <0.1.0
518520// ^0 --> >=0.0.0 <1.0.0
519- func constraintCaret (v * Version , c * constraint ) (bool , error ) {
520- // If there is a pre-release on the version but the constraint isn't looking
521- // for them assume that pre-releases are not compatible. See issue 21 for
522- // more details.
523- if v .Prerelease () != "" && c .con .Prerelease () == "" {
521+ func constraintCaret (v * Version , c * constraint , includePre bool ) (bool , error ) {
522+ // The existence of prereleases is checked at the group level and passed in.
523+ // Exit early if the version has a prerelease but those are to be ignored.
524+ if v .Prerelease () != "" && ! includePre {
524525 return false , fmt .Errorf ("%s is a prerelease version and the constraint is only looking for release versions" , v )
525526 }
526527
0 commit comments