Is the default configuration leaking into independent configurations?

Hi guys,

I would like a clarification about configurations. I was expecting configurations that do not inherit from other configurations to be independent, but it doesn’t seem to be the case. First a bit of context, I’m using Gradle 2.0, and I am working on a plugin for japicmp, a binary compatibility checker. I managed to make it compare two jars, but I would like to propose an alternate task where you would compare two “dependencies”. The idea would be to compare the current output of the project with a previous reference version. For example, in Groovy, compare master, which is 2.4.0-SNAPSHOT, with 2.3.6.

To test that idea, I added this in the build.gradle file:

configurations {
    japicmp {
        transitive = false
    }
}
dependencies {
    japicmp('org.codehaus.groovy:groovy:2.3.6')
}

Then in my japi task:

task japicmp(type: me.champeau.gradle.JapicmpTask) {
    oldArchive = configurations.japicmp.files[0]
    newArchive = jar.archivePath
    outputOnlyModifications = true
    txtOutputFile = file("$buildDir/reports/japi.txt")
    doFirst {
        logger.lifecycle("Old: $oldArchive ${configurations.japicmp.asPath}")
    }
}

And surprise, “oldArchive” is resolved to 2.4.0-SNAPSHOT. Since I expected the japicmp configuration to be independent, it really surprised me, because it seems that the fact our project corresponds to the ‘org.codehaus.groovy:groovy’ artifact participates in the dependency resolution for the ‘japicmp’ configuration. Is this right?

In the end, I don’t want to expose that kind of configuration at use site, but transparently do it in the plugin. Is it doable?

Thanks!

A little more details: dependencyInsight tells me the dependency is overriden by the project:

:dependencyInsight
project :
  org.codehaus.groovy:groovy:2.3.6 -> project :
\--- project : (*)
  (*) - dependencies omitted (listed previously)

I tried several tweaks, like:

dependencyResolution {
   force 'org.codehaus.groovy:groovy:2.3.6'
}

or

dependencyResolution {
   forcedModules = [ 'org.codehaus.groovy:groovy:2.3.6']
}

or

resolutionStrategy{
   eachDependency { DependencyResolveDetails details ->
      if (details.requested.name=='groovy') {
            details.useVersion '2.3.6'
      }
   }
}

All without success.

Try using a detached configuration like this one

https://github.com/griffon/griffon/blob/development/subprojects/gradle-griffon-plugin/src/main/groovy/org/codehaus/griffon/gradle/GriffonPluginResolutionStrategy.groovy#L89-L91

File bomFile = project.configurations.detachedConfiguration(
    project.dependencies.create(bomDependency)
).singleFile

In your case you’d want to grab a JAR file instead of course :slight_smile:

The gradle-clirr plugin follows a similar approach like yours but I can’t tell if it’s successful or not as it keeps failing on me on every project I try it out https://github.com/trnl/clirr-gradle-plugin

Thanks Andrés. I tried it but it fails with:

Module version org.codehaus.groovy:groovy:2.4.0-SNAPSHOT, configuration ‘detachedConfiguration2’ declares a dependency on configuration ‘default’ which is not declared in the module descriptor for org.codehaus.groovy:groovy:2.4.0-SNAPSHOT

Does this error tell you something?

So I managed to have something working but it looks very hackish:

private File computeDependency(Object module) {
        def oldGroup = project.group
        def result = null
        try {
            project.group = 'virtual_group_for_japicmp'
            // convenience wrapping for single file
            def depModule = module instanceof File ? project.files(module) : module
            def configuration = project.configurations.detachedConfiguration(
                    project.dependencies.create(depModule) {
                        if (hasProperty('transitive')) {
                            transitive = false
                        }
                    }
            )
              result = configuration.singleFile
        } finally {
            project.group = oldGroup
        }
        result
    }

Note how I am forced to change the group of the project. Now it allows me to write:

task japicmp(type: me.champeau.gradle.ArtifactJapicmpTask) {
    baseline = 'org.codehaus.groovy:groovy:2.3.5'
    to = 'org.codehaus.groovy:groovy:2.3.6'
    // ...
}

or:

task japicmp(type: me.champeau.gradle.ArtifactJapicmpTask) {
    baseline = 'org.codehaus.groovy:groovy:2.3.5'
    to = jar.archivePath
}

But (and I’m not sure if it is relevant), this will fail:

task japicmp(type: me.champeau.gradle.ArtifactJapicmpTask) {
    baseline = 'org.codehaus.groovy:groovy:2.3.5'
    to = project
}

Error is: Module version virtual_group_for_japicmp:groovy:2.4.0-SNAPSHOT, configuration ‘detachedConfiguration3’ declares a dependency on configuration ‘default’ which is not declared in the module descriptor for virtual_group_for_japicmp:groovy:2.4.0-SNAPSHOT