What is the difference between a Gradle configuration dependency and a Gradle configuration incoming dependency?

Viewed 559

Gradle configurations have two properties known as dependencies and incoming. Based on my understanding, we can add a dependency to a configuration through a Gradle dependency block like the following:

dependencies {
    testCompile "junit:junit:4.12"
}

I expect that after the above block of code is executed, testCompile.dependencies will return a collection containing at least 1 object representing the JUnit dependency.

I am unsure what testCompile.incoming will represent, however.

What is the relationship between a configuration's dependencies and incoming properties? What is an example of using the incoming property?

1 Answers

I think I figured it out with some experimentation. I started by creating a dummy project using Gradle. I have the following Gradle script to try out different properties of the testCompile configuration's properties.

group 'com.example'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

task("dummyFileGenerator") {
    outputs.file '/tmp'
}

// configurations.testCompile.transitive false

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile files('/tmp')

}

println "Printing dependencies"
configurations.testCompile.dependencies.all {
    println(it)
}
println "======="

println "Printing all dependencies"
configurations.testCompile.allDependencies.all {
    println it
}
println '======='

println "printing incoming dependencies"
configurations.testCompile.incoming.dependencies.all {
    println(it)
}
println "======="

println "printing files of incoming dependencies"
configurations.testCompile.incoming.files.forEach {
    println it
}
println "======="

println "printing artifacts of incoming dependencies"
configurations.testCompile.incoming.artifacts.forEach {
    println it
}
println "======="

println "printing files of incoming dependencies (again)"
configurations.testCompile.incoming.files.forEach {
    println it
}
println "======="

task("blecgh") {
    doLast {
        println "Hello!"
    }
}

A sample output from this script is:

Printing dependencies
DefaultExternalModuleDependency{group='junit', name='junit', version='4.12', configuration='default'}
org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency_Decorated@433edba9
=======
Printing all dependencies
DefaultExternalModuleDependency{group='junit', name='junit', version='4.12', configuration='default'}
org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency_Decorated@433edba9
=======
printing incoming dependencies
DefaultExternalModuleDependency{group='junit', name='junit', version='4.12', configuration='default'}
org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency_Decorated@433edba9
=======
printing files of incoming dependencies
/tmp
/usr/local/google/home/afwang/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973d150c0dc1fefe998f834810d68f278ea58ec/junit-4.12.jar
/usr/local/google/home/afwang/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar
=======
printing artifacts of incoming dependencies
tmp
junit.jar (junit:junit:4.12)
hamcrest-core.jar (org.hamcrest:hamcrest-core:1.3)
=======
printing files of incoming dependencies (again)
/tmp
/usr/local/google/home/afwang/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973d150c0dc1fefe998f834810d68f278ea58ec/junit-4.12.jar
/usr/local/google/home/afwang/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar
=======
:blecgh
Hello!

BUILD SUCCESSFUL

Total time: 0.621 secs

Interesting bits to note are that incoming.files and incoming.artifacts contain a representation for the Hamcrest dependency. This suggests that a configuration's incoming property includes the artifacts of the configuration's transitive dependencies in addition to the artifacts of the configuration's direct dependencies. This seems to be related to the configuration's transitive property. If the transitive property is set to false, the incoming property will not include the configuration's transitive dependencies' artifacts; only the direct dependencies' artifacts will be contained.

Note that the configuration's allDependencies property does not include transitive dependencies. Instead, the allDependencies property includes inherited dependencies from the super configuration.

Here's a graph to help explain what I believe these configuration properties represent:

configParent -- depParent
|
|
configChild -- depA
            \- depB -- depB1 -- depB2

configParent and configChild are configurations. configParent has a direct dependency on depParent. configParent is the super configuration for configChild. configChild has direct dependencies depA and depB. depB has a dependency on depB1, and depB1 has a dependency on depB2.

configChild.dependencies will contain only depA and depB. configChild.allDependencies will contain only depParent, depA, and depB. configChild.incoming.artifacts will contain the artifacts of dependencies depParent, depA, depB, depB1, and depB2. Similarly, configChild.incoming.files will contain the files of dependencies depParent, depA, depB, depB1, and depB2.

I'd summarize by saying that a configuration's incoming property is the resolution of all of its dependencies, including inherited dependencies form super configurations.

Related