mirror of https://github.com/sbt/sbt.git
[2.x] fix: Fixes evicted warning for version intervals (#8719)
When a dependency declares a version range (e.g. Ivy [1.3.1,2.3] or comma-separated "1.3.1,2.3" as used by Coursier), and the resolver picks a version inside that range, sbt was still reporting an eviction warning. The chosen version satisfies the range, so it should not be reported as an eviction. Example (from #6244): oauth2-oidc-sdk and nimbus-jose-jwt both depend on net.minidev:json-smart with range [1.3.1,2.3]. Resolution selects 2.3, which is within the range. Before this fix, sbt reported an eviction for json-smart even though 2.3 satisfies [1.3.1,2.3].
This commit is contained in:
parent
3e3cde19b9
commit
f47afb5b49
|
|
@ -12,7 +12,9 @@ object VersionRange {
|
|||
(revision.contains("[")) ||
|
||||
(revision.contains("]")) ||
|
||||
(revision.contains("(")) ||
|
||||
(revision.contains(")"))
|
||||
(revision.contains(")")) ||
|
||||
// Comma-separated range e.g. "1.3.1,2.3" (fixes #6244 when Coursier passes range without brackets)
|
||||
(revision.contains(",") && revision.exists(_.isDigit))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -25,6 +27,15 @@ object VersionRange {
|
|||
if (!isVersionRange(range)) {
|
||||
// Not a range, just compare directly
|
||||
version == range
|
||||
} else if (range.contains(",") && !hasMavenVersionRange(range)) {
|
||||
// Comma-separated range without brackets e.g. "1.3.1,2.3" (fixes #6244)
|
||||
val parts = range.split(",", 2)
|
||||
if (parts.length == 2) {
|
||||
val lower = parts(0).trim
|
||||
val upper = parts(1).trim
|
||||
lower.nonEmpty && upper.nonEmpty &&
|
||||
compareVersions(version, lower) >= 0 && compareVersions(version, upper) <= 0
|
||||
} else false
|
||||
} else if (range.endsWith("+")) {
|
||||
// Handle plus ranges like "1.0+" meaning >= 1.0
|
||||
val base = range.dropRight(1)
|
||||
|
|
|
|||
|
|
@ -337,15 +337,18 @@ object EvictionWarning {
|
|||
def guessCompatible(p: EvictionPair): Boolean =
|
||||
p.evicteds forall { r =>
|
||||
val winnerOpt = p.winner map { _.module }
|
||||
val evictedRev = r.module.revision
|
||||
// Same version: no eviction (fixes #6244 when resolution picks version within requested range)
|
||||
val sameVersion: Boolean = winnerOpt.exists(_.revision == evictedRev)
|
||||
// Check if the evicted module's revision is a version range and if the winner satisfies it
|
||||
// This handles cases like [4.1.0,5) where 4.2.1 would be within range (fixes #3978)
|
||||
val evictedRev = r.module.revision
|
||||
// and [1.3.1,2.3] where 2.3 is valid (fixes #6244)
|
||||
val winnerSatisfiesRange: Boolean = winnerOpt match {
|
||||
case Some(winner) if VersionRange.isVersionRange(evictedRev) =>
|
||||
VersionRange.versionSatisfiesRange(winner.revision, evictedRev)
|
||||
case _ => false
|
||||
}
|
||||
if (winnerSatisfiesRange) {
|
||||
if (sameVersion || winnerSatisfiesRange) {
|
||||
true
|
||||
} else {
|
||||
val extraAttributes = ((p.winner match {
|
||||
|
|
|
|||
|
|
@ -98,4 +98,19 @@ class VersionRangeSpec extends UnitSpec {
|
|||
assert(VersionRange.versionSatisfiesRange("1.0.0", "[1.0]") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("1.1", "[1.0]") == false)
|
||||
}
|
||||
|
||||
// Exact reproduction case from issue #6244 (net.minidev:json-smart, [1.3.1,2.3] -> 2.3 selected)
|
||||
it should "not treat 2.3 as evicted when range is [1.3.1,2.3] (fixes #6244)" in {
|
||||
assert(VersionRange.isVersionRange("[1.3.1,2.3]") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("2.3", "[1.3.1,2.3]") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("1.3.1", "[1.3.1,2.3]") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("2.4", "[1.3.1,2.3]") == false)
|
||||
}
|
||||
|
||||
it should "handle comma-separated range without brackets (fixes #6244)" in {
|
||||
assert(VersionRange.isVersionRange("1.3.1,2.3") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("2.3", "1.3.1,2.3") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("1.3.1", "1.3.1,2.3") == true)
|
||||
assert(VersionRange.versionSatisfiesRange("2.4", "1.3.1,2.3") == false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,6 +364,28 @@ object EvictionWarningSpec extends BaseIvySpecification {
|
|||
def javaLibDirectDeps = Vector(commonsIo14, commonsIo24)
|
||||
def javaLibTransitiveDeps = Vector(unfilteredUploads080, bnfparser10)
|
||||
def scalaLibTransitiveDeps = Vector(scala2104, bananaSesame04, akkaRemote234)
|
||||
|
||||
// #6244: oauth2-oidc-sdk and nimbus-jose-jwt both depend on net.minidev:json-smart [1.3.1,2.3];
|
||||
// resolution selects 2.3, which is within the range, so we must not report it as eviction.
|
||||
def oauth2OidcSdk822 =
|
||||
ModuleID("com.nimbusds", "oauth2-oidc-sdk", "8.22").withConfigurations(Some("compile"))
|
||||
def nimbusJoseJwt8201 =
|
||||
ModuleID("com.nimbusds", "nimbus-jose-jwt", "8.20.1").withConfigurations(Some("compile"))
|
||||
def versionIntervalDeps6244 = Vector(oauth2OidcSdk822, nimbusJoseJwt8201)
|
||||
|
||||
test(
|
||||
"When winner satisfies version range [1.3.1,2.3], should not report eviction for json-smart (fixes #6244)"
|
||||
) {
|
||||
val m = module(defaultModuleId, versionIntervalDeps6244, Some("2.12.12"))
|
||||
val report = ivyUpdate(m)
|
||||
val warning = EvictionWarning(m, fullOptions, report)
|
||||
val jsonSmartEviction =
|
||||
warning.reportedEvictions.find(p => p.organization == "net.minidev" && p.name == "json-smart")
|
||||
assert(
|
||||
jsonSmartEviction.isEmpty,
|
||||
s"#6244: json-smart 2.3 is within range [1.3.1,2.3], should not be reported as eviction. Got:\n${warning.lines.mkString("\n")}"
|
||||
)
|
||||
}
|
||||
def dummyScalaModuleInfo(v: String): ScalaModuleInfo =
|
||||
ScalaModuleInfo(
|
||||
scalaFullVersion = v,
|
||||
|
|
|
|||
Loading…
Reference in New Issue