Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions range.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
var expandedParts [][]string
for _, p := range parts {
var newParts []string
// Track != wildcard expansions that need OR logic
var neqOrParts [][]string
for _, ap := range p {
if strings.Contains(ap, "x") {
opStr, vStr, err := splitComparatorVersion(ap)
Expand Down Expand Up @@ -354,9 +356,17 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
resultOperator = "<"
shouldIncrementVersion = true
case "!=", "!":
newParts = append(newParts, "<"+flatVersion)
resultOperator = ">="
shouldIncrementVersion = true
// != with wildcard means "outside this range", which requires OR:
// <flatVersion OR >=incrementedVersion
var incrementedVersion string
switch versionWildcardType {
case patchWildcard:
incrementedVersion, _ = incrementMinorVersion(flatVersion)
case minorWildcard:
incrementedVersion, _ = incrementMajorVersion(flatVersion)
}
neqOrParts = append(neqOrParts, []string{"<" + flatVersion}, []string{">=" + incrementedVersion})
continue
}

var resultVersion string
Expand All @@ -375,7 +385,15 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
}
newParts = append(newParts, ap)
}
expandedParts = append(expandedParts, newParts)
if len(neqOrParts) == 0 {
expandedParts = append(expandedParts, newParts)
} else {
// Each != wildcard produces OR branches. Combine with remaining AND parts.
for _, neqPart := range neqOrParts {
combined := append(append([]string{}, newParts...), neqPart...)
expandedParts = append(expandedParts, combined)
}
}
}

return expandedParts, nil
Expand Down
20 changes: 18 additions & 2 deletions range_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,12 @@ func TestExpandWildcardVersion(t *testing.T) {
{[][]string{{"<=1.2.x"}}, [][]string{{"<1.3.0"}}},
{[][]string{{">1.2.x"}}, [][]string{{">=1.3.0"}}},
{[][]string{{"<1.2.x"}}, [][]string{{"<1.2.0"}}},
{[][]string{{"!=1.2.x"}}, [][]string{{"<1.2.0", ">=1.3.0"}}},
{[][]string{{"!=1.2.x"}}, [][]string{{"<1.2.0"}, {">=1.3.0"}}},
{[][]string{{">=1.x"}}, [][]string{{">=1.0.0"}}},
{[][]string{{"<=1.x"}}, [][]string{{"<2.0.0"}}},
{[][]string{{">1.x"}}, [][]string{{">=2.0.0"}}},
{[][]string{{"<1.x"}}, [][]string{{"<1.0.0"}}},
{[][]string{{"!=1.x"}}, [][]string{{"<1.0.0", ">=2.0.0"}}},
{[][]string{{"!=1.x"}}, [][]string{{"<1.0.0"}, {">=2.0.0"}}},
{[][]string{{"1.2.x"}}, [][]string{{">=1.2.0", "<1.3.0"}}},
{[][]string{{"1.x"}}, [][]string{{">=1.0.0", "<2.0.0"}}},
}
Expand Down Expand Up @@ -461,6 +461,22 @@ func TestParseRange(t *testing.T) {
{"1.2.6", false},
{"1.3.0", true},
}},
// Regression test for issue #80: !=1.0.x should use OR, not AND
{"!=1.0.x", []tv{
{"0.9.0", true},
{"1.0.0", false},
{"1.0.5", false},
{"1.0.99", false},
{"1.1.0", true},
{"1.1.1", true},
{"2.0.0", true},
}},
{"!=1.x", []tv{
{"0.9.0", true},
{"1.0.0", false},
{"1.5.0", false},
{"2.0.0", true},
}},
// Combined Expressions
{">1.2.2 <1.2.4 || >=2.0.0", []tv{
{"1.2.2", false},
Expand Down
26 changes: 22 additions & 4 deletions v4/range.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
var expandedParts [][]string
for _, p := range parts {
var newParts []string
// Track != wildcard expansions that need OR logic
var neqOrParts [][]string
for _, ap := range p {
if strings.Contains(ap, "x") {
opStr, vStr, err := splitComparatorVersion(ap)
Expand Down Expand Up @@ -354,9 +356,17 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
resultOperator = "<"
shouldIncrementVersion = true
case "!=", "!":
newParts = append(newParts, "<"+flatVersion)
resultOperator = ">="
shouldIncrementVersion = true
// != with wildcard means "outside this range", which requires OR:
// <flatVersion OR >=incrementedVersion
var incrementedVersion string
switch versionWildcardType {
case patchWildcard:
incrementedVersion, _ = incrementMinorVersion(flatVersion)
case minorWildcard:
incrementedVersion, _ = incrementMajorVersion(flatVersion)
}
neqOrParts = append(neqOrParts, []string{"<" + flatVersion}, []string{">=" + incrementedVersion})
continue
}

var resultVersion string
Expand All @@ -375,7 +385,15 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
}
newParts = append(newParts, ap)
}
expandedParts = append(expandedParts, newParts)
if len(neqOrParts) == 0 {
expandedParts = append(expandedParts, newParts)
} else {
// Each != wildcard produces OR branches. Combine with remaining AND parts.
for _, neqPart := range neqOrParts {
combined := append(append([]string{}, newParts...), neqPart...)
expandedParts = append(expandedParts, combined)
}
}
}

return expandedParts, nil
Expand Down
20 changes: 18 additions & 2 deletions v4/range_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,12 @@ func TestExpandWildcardVersion(t *testing.T) {
{[][]string{{"<=1.2.x"}}, [][]string{{"<1.3.0"}}},
{[][]string{{">1.2.x"}}, [][]string{{">=1.3.0"}}},
{[][]string{{"<1.2.x"}}, [][]string{{"<1.2.0"}}},
{[][]string{{"!=1.2.x"}}, [][]string{{"<1.2.0", ">=1.3.0"}}},
{[][]string{{"!=1.2.x"}}, [][]string{{"<1.2.0"}, {">=1.3.0"}}},
{[][]string{{">=1.x"}}, [][]string{{">=1.0.0"}}},
{[][]string{{"<=1.x"}}, [][]string{{"<2.0.0"}}},
{[][]string{{">1.x"}}, [][]string{{">=2.0.0"}}},
{[][]string{{"<1.x"}}, [][]string{{"<1.0.0"}}},
{[][]string{{"!=1.x"}}, [][]string{{"<1.0.0", ">=2.0.0"}}},
{[][]string{{"!=1.x"}}, [][]string{{"<1.0.0"}, {">=2.0.0"}}},
{[][]string{{"1.2.x"}}, [][]string{{">=1.2.0", "<1.3.0"}}},
{[][]string{{"1.x"}}, [][]string{{">=1.0.0", "<2.0.0"}}},
}
Expand Down Expand Up @@ -461,6 +461,22 @@ func TestParseRange(t *testing.T) {
{"1.2.6", false},
{"1.3.0", true},
}},
// Regression test for issue #80: !=1.0.x should use OR, not AND
{"!=1.0.x", []tv{
{"0.9.0", true},
{"1.0.0", false},
{"1.0.5", false},
{"1.0.99", false},
{"1.1.0", true},
{"1.1.1", true},
{"2.0.0", true},
}},
{"!=1.x", []tv{
{"0.9.0", true},
{"1.0.0", false},
{"1.5.0", false},
{"2.0.0", true},
}},
// Combined Expressions
{">1.2.2 <1.2.4 || >=2.0.0", []tv{
{"1.2.2", false},
Expand Down