-
Notifications
You must be signed in to change notification settings - Fork 928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maven version range should translate to a fixed lower bound in Ivy #2954
Comments
Previously, when the dependency resolver (Ivy) encountered a Maven version range such as `[1.3.0,)` it would go out to the Internet to find the latest version. This would result to a surprising behavior where the eventual version keeps changing over time *even when there's a version of the library that satisfies the range condition*. This changes to some Maven version ranges would be replaced with its lower bound so that when a satisfactory version is found in the dependency graph it will be used. You can disable this behavior using the JVM flag `-Dsbt.modversionrange=false`. Fixes sbt#2954 Ref sbt#2291 / sbt#2953
Previously, when the dependency resolver (Ivy) encountered a Maven version range such as `[1.3.0,)` it would go out to the Internet to find the latest version. This would result to a surprising behavior where the eventual version keeps changing over time *even when there's a version of the library that satisfies the range condition*. This changes to some Maven version ranges would be replaced with its lower bound so that when a satisfactory version is found in the dependency graph it will be used. You can disable this behavior using the JVM flag `-Dsbt.modversionrange=false`. Fixes sbt#2954 Ref sbt#2291 / sbt#2953
Previously, when the dependency resolver (Ivy) encountered a Maven version range such as `[1.3.0,)` it would go out to the Internet to find the latest version. This would result to a surprising behavior where the eventual version keeps changing over time *even when there's a version of the library that satisfies the range condition*. This changes to some Maven version ranges would be replaced with its lower bound so that when a satisfactory version is found in the dependency graph it will be used. You can disable this behavior using the JVM flag `-Dsbt.modversionrange=false`. Fixes sbt#2954 Ref sbt#2291 / sbt#2953
I've been trying to wrap my head around what the correct behaviour should be, and it's hugely puzzling. Generally, the java ecosystem both resolves and publishes maven artefacts using maven from/to maven repositories. While, generally, the scala ecosystem (ignoring sbt plugins, that use ivy repositories) both resolves and publishes maven artefacts using sbt/ivy (sbt's fork of ivy) from/to maven repositories. So, using ivy, how should we reconcile different version ranges? Which semantics should we use? Ivy's? Maven's? What even are Maven's semantics? On http://maven.apache.org/components/enforcer/enforcer-rules/versionRanges.html it says about the version range:
while on https://cwiki.apache.org/confluence/display/MAVENOLD/Dependency+Mediation+and+Conflict+Resolution it says:
And what happens when you have multiple version ranges? On https://cwiki.apache.org/confluence/display/MAVENOLD/Dependency+Mediation+and+Conflict+Resolution it says:
while on https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN402 it says:
And that's just Maven. I haven't even begun to understand Ivy, where in http://ant.apache.org/ivy/history/latest-milestone/ivyfile/dependency.html it speaks about how there isn't just one "version" field (which they call "revision" typically) but of there being both a "rev" and a "revConstraint" field, and then:
Clearly there is a lot going on and I'm personally not convinced (yet) that it's surprising that 1.5.0-beta.2, that it's "expected" to pick 1.4.7, or that the correct course of action is to simply "translate it to the lower bound 1.3.0". This needs further study, in my opinion. |
We use the combination of both. Ivy is used as the implementation but it tries to emulate Maven semantics via the In my opinion, the version range is a clear case that Ivy's implementation is broken. We can view dependency graph resolution to be a variant of constraint satisfaction problem where Also from the practical point of view, go-to-Internet behavior is detrimental to the core tenet of Repeatable Build. Say the author Alice publishes version 1 in 2015, and later someone tries to build the build, and here we assume zero SNAPSHOTs. The current behavior of go-to-Internet could still make the build impossible to reproduce if in 2017 the dependent library bumps up, or worse breaks bincompat. Using the lower bound will still satisfy the original constraint, and still do the right thing. As per timing, I'm very much convinced that we have to do this pre-1.0. |
What about Coursier? |
This is spawn from #2291 (comment)
Upon a dependency conflict (multiple version candidates are found for the same module), by default Ivy uses latest-wins, and Maven uses nearest-wins logic to pick the winner. Given that most people use this default, it might make sense to simply use the lower bound instead of trying to translate Maven's version range to Ivy's dynamic revision.
case study
See for example: #2291
angular-bootstrap requires:
If we translate Maven's
[1.3.0,)
to Ivy's dynamic revision, Ivy will go out to the Internet and find1.5.0-beta.2
. This is surprising because the user has already specified1.4.7
in the graph that satisfies the condition.If instead as I propose here we translated it to the lower bound
1.3.0
, Ivy will evict it and pick1.4.7
as expected.The text was updated successfully, but these errors were encountered: