diff --git a/constraints.go b/constraints.go index 8461c7e..969fd95 100644 --- a/constraints.go +++ b/constraints.go @@ -162,7 +162,7 @@ var findConstraintRegex *regexp.Regexp var validConstraintRegex *regexp.Regexp const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` + - `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-\*]+)*))?` + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` func init() { @@ -221,9 +221,10 @@ type constraint struct { origfunc string // When an x is used as part of the version (e.g., 1.x) - minorDirty bool - dirty bool - patchDirty bool + minorDirty bool + dirty bool + patchDirty bool + prereleaseDirty bool } // Check if a version meets the constraint @@ -251,20 +252,38 @@ func parseConstraint(c string) (*constraint, error) { } ver := m[2] - minorDirty := false + prereleaseDirty := false patchDirty := false + minorDirty := false dirty := false + + if len(m) > 8 && m[7] != "" && isX(strings.TrimPrefix(m[8], ".")) { + prereleaseDirty = true + } + if isX(m[3]) || m[3] == "" { - ver = fmt.Sprintf("0.0.0%s", m[6]) + if prereleaseDirty { + ver = fmt.Sprintf("0.0.0-%s.0", strings.Split(m[7], ".")[0]) + } else { + ver = fmt.Sprintf("0.0.0%s", m[6]) + } dirty = true } else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" { + if prereleaseDirty { + ver = fmt.Sprintf("%s.0.0-%s.0", m[3], strings.Split(m[7], ".")[0]) + } else { + ver = fmt.Sprintf("%s.0.0%s", m[3], m[6]) + } minorDirty = true dirty = true - ver = fmt.Sprintf("%s.0.0%s", m[3], m[6]) } else if isX(strings.TrimPrefix(m[5], ".")) || m[5] == "" { + if prereleaseDirty { + ver = fmt.Sprintf("%s%s.0-%s.0", m[3], m[4], strings.Split(m[7], ".")[0]) + } else { + ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6]) + } dirty = true patchDirty = true - ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6]) } con, err := NewVersion(ver) @@ -278,6 +297,7 @@ func parseConstraint(c string) (*constraint, error) { cs.con = con cs.minorDirty = minorDirty cs.patchDirty = patchDirty + cs.prereleaseDirty = prereleaseDirty cs.dirty = dirty return cs, nil @@ -467,6 +487,10 @@ func constraintTilde(v *Version, c *constraint) (bool, error) { return false, fmt.Errorf("%s is less than %s", v, c.orig) } + if c.prereleaseDirty && strings.Split(v.pre, ".")[0] != strings.Split(c.con.pre, ".")[0] { + return false, nil + } + // ~0.0.0 is a special case where all constraints are accepted. It's // equivalent to >= 0.0.0. if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 && diff --git a/constraints_test.go b/constraints_test.go index c720797..dcc7d10 100644 --- a/constraints_test.go +++ b/constraints_test.go @@ -125,6 +125,12 @@ func TestConstraintCheck(t *testing.T) { {"*", "4.5.6", true}, {"*", "1.2.3-alpha.1", false}, {"*-0", "1.2.3-alpha.1", true}, + {"*-alpha.*", "1.2.3-alpha.1", true}, + {"*-alpha.*", "1.2.3-beta.1", false}, + {"1.*-alpha.*", "1.2.3-alpha.1", true}, + {"2.*-alpha.*", "1.2.3-alpha.1", false}, + {"1.2.*-alpha.*", "1.2.3-alpha.1", true}, + {"1.3.*-alpha.*", "1.2.3-alpha.1", false}, {"2.*", "1", false}, {"2.*", "3.4.5", false}, {"2.*", "2.1.1", true},