Skip to content

Commit

Permalink
Resolve dependency constraints.
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraaga committed Oct 8, 2019
1 parent 1e6591b commit bc38df4
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.github.benmanes.gradle.versions.updates
import groovy.transform.EqualsAndHashCode
import groovy.transform.TypeChecked
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.DependencyConstraint
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.artifacts.ModuleVersionSelector
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
Expand Down Expand Up @@ -61,6 +62,10 @@ class Coordinate implements Comparable<Coordinate> {
return new Coordinate(dependency.group, dependency.name, dependency.version)
}

static Coordinate from(DependencyConstraint dependency) {
return new Coordinate(dependency.group, dependency.name, dependency.version)
}

static Coordinate from(ModuleVersionIdentifier identifier) {
return new Coordinate(identifier.group, identifier.name, identifier.version)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.gradle.api.artifacts.ComponentMetadata
import org.gradle.api.artifacts.ComponentSelection
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.DependencyConstraint
import org.gradle.api.artifacts.ExternalDependency
import org.gradle.api.artifacts.LenientConfiguration
import org.gradle.api.artifacts.ModuleVersionIdentifier
Expand Down Expand Up @@ -117,6 +118,15 @@ class Resolver {
createQueryDependency(dependency, revision)
}

// Common use case for dependency constraints is a java-platform BOM project.
try {
configuration.dependencyConstraints.each { dependency ->
latest.add(createQueryDependency(dependency, revision))
}
} catch (MissingPropertyException e) {
// Skip if constraints not supported
}

Configuration copy = configuration.copyRecursive().setTransitive(false)
// https://github.com/ben-manes/gradle-versions-plugin/issues/127
if (copy.metaClass.respondsTo(copy, "setCanBeResolved", Boolean)) {
Expand Down Expand Up @@ -149,6 +159,19 @@ class Resolver {
}
}

/** Returns a variant of the provided dependency used for querying the latest version. */
@TypeChecked(SKIP)
private Dependency createQueryDependency(DependencyConstraint dependency, String revision) {
String versionQuery = useSelectionRules ? '+' : "latest.${revision}"

// If no version was specified then use 'none' to pass it through.
String version = dependency.version == null ? 'none' : versionQuery

return project.dependencies.create("${dependency.group}:${dependency.name}:${version}") {
transitive = false
}
}

/** Adds a revision filter by rejecting candidates using a component selection rule. */
@TypeChecked(SKIP)
private void addRevisionFilter(Configuration configuration, String revision) {
Expand Down Expand Up @@ -184,12 +207,11 @@ class Resolver {

/** Returns the coordinates for the current (declared) dependency versions. */
private Map<Coordinate.Key, Coordinate> getCurrentCoordinates(Configuration configuration) {
Map<Coordinate.Key, Coordinate> declared = configuration.dependencies.findAll { dependency ->
dependency instanceof ExternalDependency
}.collectEntries {
Coordinate coordinate = Coordinate.from(it)
return [coordinate.key, coordinate]
}
Map<Coordinate.Key, Coordinate> declared =
getResolvableDependencies(configuration).collectEntries {
return [it.key, it]
}

if (declared.isEmpty()) {
return Collections.emptyMap()
}
Expand Down Expand Up @@ -217,6 +239,15 @@ class Resolver {
coordinates.put(coordinate.key, declared.get(coordinate.key))
}

try {
for (DependencyConstraint constraint : copy.dependencyConstraints) {
Coordinate coordinate = Coordinate.from(constraint)
coordinates.put(coordinate.key, declared.get(coordinate.key))
}
} catch (MissingPropertyException e) {
// Skip if constraints not supported
}

// Ignore undeclared (hidden) dependencies that appear when resolving a configuration
coordinates.keySet().retainAll(declared.keySet())

Expand Down Expand Up @@ -333,6 +364,24 @@ class Resolver {
return null
}

private static List<Coordinate> getResolvableDependencies(Configuration configuration) {
List<Coordinate> coordinates = configuration.dependencies.findAll { dependency ->
dependency instanceof ExternalDependency
}.collect { dependency ->
Coordinate.from(dependency)
}

try {
configuration.dependencyConstraints.each {
coordinates.add(Coordinate.from(it))
}
} catch (MissingPropertyException e) {
// Skip
}

return coordinates
}

private static final class ProjectUrl {
boolean isResolved
String url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,40 @@ final class JavaLibrarySpec extends Specification {
result.output.contains('com.google.inject:guice [2.0 -> 3.1]')
result.task(':dependencyUpdates').outcome == SUCCESS
}

def "Show updates for an api dependency constraint in a java-library project"() {
given:
def mavenRepoUrl = getClass().getResource('/maven/').toURI()
buildFile = testProjectDir.newFile('build.gradle')
buildFile <<
"""
plugins {
id 'java-library'
id 'com.github.ben-manes.versions'
}
repositories {
maven {
url '${mavenRepoUrl}'
}
}
dependencies {
constraints {
api 'com.google.inject:guice:2.0'
}
}
""".stripIndent()

when:
def result = GradleRunner.create()
.withProjectDir(testProjectDir.root)
.withArguments('dependencyUpdates')
.withPluginClasspath()
.build()

then:
result.output.contains('com.google.inject:guice [2.0 -> 3.1]')
result.task(':dependencyUpdates').outcome == SUCCESS
}
}

0 comments on commit bc38df4

Please sign in to comment.