resolves #394 fix gem requirements resolution

This commit is contained in:
Guillaume Grossetie 2019-12-22 18:06:42 +01:00
parent d8f1358065
commit 1545885ecf
3 changed files with 82 additions and 64 deletions

View File

@ -76,6 +76,27 @@ class JRubyPrepareGemsIntegrationSpec extends IntegrationSpecification {
new File(projectDir, "gems/rack-1.6.12").exists()
}
@IgnoreIf({ IntegrationSpecification.OFFLINE })
void "Check if selenium-webdriver version gets resolved"() {
setup:
withPreamble """repositories.ruby.gems()
jrubyPrepare.outputDir = '${pathAsUriStr(projectDir)}'.toURI()
"""
withDependencies """
gems 'rubygems:selenium-webdriver:3.142.6'
gems 'rubygems:webdrivers:4.1.3'
"""
when:
build()
then:
// since we need a version range in the setup the
// resolved version here can vary over time
new File(projectDir, "gems/selenium-webdriver-3.142.6").exists()
}
@IgnoreIf({ IntegrationSpecification.OFFLINE })
void "Check that GEM dependencies are locked"() {
setup:

View File

@ -177,7 +177,7 @@ class GemVersion implements Comparable<GemVersion> {
gemVersions.first()
} else {
gemVersions[1..-1].inject(gemVersions.first()) { range, value ->
range.union(value)
range.intersect(value)
}
}
}
@ -300,66 +300,53 @@ class GemVersion implements Comparable<GemVersion> {
* @since 2.0
*/
GemVersion intersect(GemVersion other) {
Boundary newLowBoundary
String newLow
switch (compare(low, other.low)) {
case -1:
newLow = other.low
newLowBoundary = other.lowBoundary
break
case 0:
newLowBoundary = (lowBoundary == EXCLUSIVE || other.lowBoundary == EXCLUSIVE) ? EXCLUSIVE : INCLUSIVE
newLow = low
break
case 1:
newLow = low
newLowBoundary = lowBoundary
}
Boundary newHighBoundary
String newHigh
if (!high && other.high) {
newHigh = other.high
newHighBoundary = other.highBoundary
} else if (high && !other.high) {
newHigh = high
newHighBoundary = highBoundary
} else if (!high && !other.high) {
newHigh = null
newHighBoundary = highBoundary
} else {
switch (compare(high, other.high)) {
case 1:
newHigh = other.high
newHighBoundary = other.highBoundary
break
case 0:
newHighBoundary = (highBoundary == EXCLUSIVE || other.highBoundary == EXCLUSIVE) ? EXCLUSIVE : INCLUSIVE
newHigh = high
break
case -1:
newHigh = high
newHighBoundary = highBoundary
Tuple2<String, Boundary> newLowVersionSpec = intersect(low, lowBoundary, other.low, other.lowBoundary, true)
Tuple2<String, Boundary> newHighVersionSpec = intersect(high, highBoundary, other.high, other.highBoundary, false)
GemVersion intersection = new GemVersion(newLowVersionSpec.second, newLowVersionSpec.first, newHighVersionSpec.first, newHighVersionSpec.second)
if (intersection == this) {
// is other a subset of this?
if (compare(this.low, other.low) >= 0 && compare(other.low, this.high) < 0 && compare(this.high, other.high) <= 0) {
return intersection
}
return NO_VERSION
}
return new GemVersion(newLowBoundary, newLow, newHigh, newHighBoundary)
if (intersection == other) {
// is this a subset of other?
if (compare(other.low, this.low) >= 0 && compare(this.low, other.high) < 0 && compare(other.high, this.high) <= 0) {
return intersection
}
return NO_VERSION
}
return intersection
}
/** Creates a new GEM version requirement which that the lowest of two requirements and the highest
* of those same requirement
*
* @param other Other GEM to combine with
* @return New GEM version requirement.
*
* @since 2.0
*/
GemVersion union(GemVersion other) {
List<GemVersion> pair = [this, other]
GemVersion min = pair.min()
GemVersion max = pair.max()
Tuple2<String,Boundary> intersect(String version, Boundary boundary, String otherVersion, Boundary otherBoundary, boolean low) {
Boundary newBoundary
String newVersion
if (!version && otherVersion) {
newVersion = otherVersion
newBoundary = otherBoundary
} else if (version && !otherVersion) {
newVersion = version
newBoundary = boundary
} else if (!version && !otherVersion) {
newVersion = null
newBoundary = boundary
} else {
int compareLow = low ? compare(version, otherVersion) : compare(otherVersion, version)
if (compareLow < 0) {
newVersion = otherVersion
newBoundary = otherBoundary
} else if (compareLow > 0) {
newVersion = version
newBoundary = boundary
} else {
newBoundary = (boundary == INCLUSIVE || otherBoundary == INCLUSIVE) ? INCLUSIVE : EXCLUSIVE
newVersion = version
}
}
new GemVersion(min.lowBoundary, min.low, max.high, max.highBoundary)
return new Tuple2(newVersion, newBoundary)
}
/** Allows for versions to be compared and sorted.

View File

@ -23,7 +23,6 @@
*/
package com.github.jrubygradle.api.gems
import com.github.jrubygradle.api.gems.GemVersion
import spock.lang.Specification
import spock.lang.Unroll
@ -77,7 +76,7 @@ class GemVersionSpec extends Specification {
}
@Unroll
void "Intersect: #ivyLeft ∩ #ivyRight ⇒ Gem #gemVer"() {
void "intersect: #ivyLeft ∩ #ivyRight ⇒ Gem #gemVer"() {
when:
GemVersion lhs = gemVersionFromGradleIvyRequirement(ivyLeft)
GemVersion rhs = gemVersionFromGradleIvyRequirement(ivyRight)
@ -87,10 +86,10 @@ class GemVersionSpec extends Specification {
where:
ivyLeft | ivyRight | gemVer
'[1.2.1,1.2.4]' | ']1.2.1,1.2.4[' | ']1.2.1,1.2.4['
'[1.2.1,1.2.4]' | ']1.2.1,1.2.4[' | '[1.2.1,1.2.4]'
'[1.2.0,1.2.4]' | ']1.2.1,1.2.3[' | ']1.2.1,1.2.3['
'[1.2.0,1.2.4]' | '[1.2.1,1.2.3]' | '[1.2.1,1.2.3]'
']1.2.0,1.2.4[' | '[1.2.0,1.2.4]' | ']1.2.0,1.2.4['
']1.2.0,1.2.4[' | '[1.2.0,1.2.4]' | '[1.2.0,1.2.4]'
']1.2.1,1.2.3[' | '[1.2.0,1.2.4]' | ']1.2.1,1.2.3['
'[1.2.1,1.2.3]' | '[1.2.0,1.2.4]' | '[1.2.1,1.2.3]'
'[1.2.10,1.2.14]' | '[1.2.2,1.10.14]' | '[1.2.10,1.2.14]'
@ -100,9 +99,20 @@ class GemVersionSpec extends Specification {
']2.5.1.1,99999]' | ']2.5.1.1,)' | ']2.5.1.1,99999]'
}
void 'Ivy union of < 3, >= 1.2'() {
expect:
singleGemVersionFromMultipleGemRequirements('< 3,>= 1.2').toString() == '[1.2,3['
@Unroll
void '#gemRequirements (requirements) ⇒ #gemRequirement (requirement)'() {
when:
GemVersion subject = singleGemVersionFromMultipleGemRequirements(gemRequirements)
then:
subject.toString() == gemRequirement
where:
gemRequirements | gemRequirement
'< 3,>= 1.2' | '[1.2,3['
'>= 3.0, < 4.0' | '[3.0,4.0['
'< 4.0, >= 3.0' | '[3.0,4.0['
'~> 2.2, >= 2.2.1' | '[2.2.1,3.0['
}
void "intersects with conflict"() {
@ -110,7 +120,7 @@ class GemVersionSpec extends Specification {
GemVersion subject = gemVersionFromGradleIvyRequirement('[1.2.1,1.2.3]')
expect:
subject.intersect('[1.2.4, 1.2.4]').conflict() == true
subject.intersect('[1.2.4, 1.2.4]').conflict()
}
void "finds no conflicts in non-integer version ranges"() {