4

I have a Gradle build script containing the following dependencies (and not much else):

dependencies {
    testCompile "com.foo:lib-foo:2.0.0-SNAPSHOT"
    testCompile "com.foo:lib-bar:2.0.2-SNAPSHOT"
}

The dependencies are resolved from a Maven repository (Sonatyp Nexus OSS). lib-bar has a dependency on lib-foo declared in its pom.xml:

<dependency>
    <groupId>com.foo</groupId>
    <artifactId>lib-foo</artifactId>
    <version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>

When I remove the dependency on lib-bar from my build script (and all code that uses it), everything compiles fine. When the I declare dependency, Gradle complains:

Could not resolve all dependencies for configuration ':testCompile'.
> Could not find any version that matches com.foo:lib-foo:[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT).
  Required by:
      :my-project:unspecified > com.foo:lib-bar:2.0.2-SNAPSHOT

The same scenario works fine with Maven.

The tutorial does not mention any limitations on Gradles ability to handle transitive dependencies or version ranges that would explain this, so I assumed this would work. Am I using it wrong? How can I make Gradle resolve that dependency?

P.S.:

When I run gradle test --info I get this:

Resource missing. [HTTP HEAD: https://nexus.foo.com/nexus/content/groups/public/com/foo/lib-foo/2.0.0-SNAPSHOT/lib-foo-2.0.0-SNAPSHOT.pom]
Resource missing. [HTTP HEAD: https://nexus.foo.com/nexus/content/groups/public/com/foo/lib-foo/2.0.0-SNAPSHOT/lib-foo-2.0.0-SNAPSHOT.jar]

These resources do indeed not exists, because the snapshots have file names with timestamps. But shouldn't Gradle use maven-metadata.xml to resolve that? And why does it work when I declare the dependency directly?

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283

2 Answers2

2

Gradle's support for version ranges is derived from Ivy's. I think what happens is that snapshots as bounds of version ranges aren't supported, and hence not recognized as such. As a consequence, Gradle tries to resolve 2.0.0-SNAPSHOT and 3.0.0-SNAPSHOT as static versions.

What's the meaning of version ranges with snapshot bounds? Will they match non-snapshot versions (e.g. 2.5)? And what's the meaning of [2.0.0, 3.0.0-SNAPSHOT) then? I haven't seen this kind of version range defined or mentioned in any Maven documentation. If this does work consistently in recent Maven versions, you may want to file an improvement request over at http://forums.gradle.org.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • Thanks for the quick response! The version range uses snapshots because `[2.0.0, 3.0.0)` would include `3.0.0-SNAPSHOT`. If only one of the versions is a snapshot, and the other a release, Maven acts as if both were releases, giving that same, incorrect behavior. We are using semantic versioning, and that relies on these version ranges. – Björn Pollex Jan 26 '14 at 22:24
  • So what exactly will `[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)` match? – Peter Niederwieser Jan 26 '14 at 22:31
  • It matches anything from `2.0.0-SNAPSHOT` (including `2.0.0` release) to `2.X.X`, excluding anything with the major version 3 or above. – Björn Pollex Jan 26 '14 at 23:32
  • So you'd use it when you want the latest version in between these bounds, whether it's a snapshot or not? – Peter Niederwieser Jan 27 '14 at 00:15
  • Yes, exactly. (fill space) – Björn Pollex Jan 27 '14 at 08:47
  • So, the I guess the answer is, it doesn't work. Is there any way to tell Gradle to ignore what is in the POM and specify the dependency manually? – Björn Pollex Jan 27 '14 at 09:19
  • Yes. See the dependency management chapter in the [Gradle User Guide](http://gradle.org/docs/current/userguide/userguide_single.html). – Peter Niederwieser Jan 27 '14 at 15:49
  • @PeterNiederwieser http://docs.codehaus.org/display/MAVEN/Dependency+Mediation+and+Conflict+Resolution#DependencyMediationandConflictResolution-DependencyVersionRanges – MariuszS Jan 27 '14 at 21:12
2

While Peter provided useful insight and the final hint (RTFM), he did not post the solution, so here it comes:

dependencies {
    testCompile "com.foo:lib-foo:2.0.0-SNAPSHOT"
    testCompile("com.foo:lib-bar:2.0.2-SNAPSHOT") {
        transitive = false
    }
}

This tells Gradle to not resolve transitive dependencies for lib-bar. This works without modifications in this case because the only transitive dependency of lib-bar is already included.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283