Gradle
  1. Gradle
  2. GRADLE-1109

Dependencies within multiple configurations, containing classifiers, fail to resolve and fail to show an error when attempting to copy the files

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Resolution: Fixed
    • Affects Version/s: 0.9
    • Fix Version/s: 1.0-milestone-5

      Description

      This problem didn't occur in 0.9-preview-3 but is present in 0.9-rc1. The problem is trying to copy dependencies that have multiple configurations. My specific example has a classifier and was a zip file but I've also reproduced it with jars. The file wouldn't copy but the task finished without error. However, closer examination of the debugging log indicated that it couldn't resolve the file. I'm attaching a testcase that illustrates the issue (task is copyFail).

      Note that in the log below the filename doesn't include the classifier and thus doesn't properly resolve (which is obvious when looking at the log, but again, it doesn't indicate to the end user that there was an error in retrieving the file):

      09:30:08.271 [main] INFO org.gradle.logging.IvyLoggingAdaper - :: resolution report :: resolve 118ms :: artifacts dl 0ms
      09:30:08.271 [main] INFO org.gradle.logging.IvyLoggingAdaper - ---------------------------------------------------------------------
      09:30:08.271 [main] INFO org.gradle.logging.IvyLoggingAdaper - | | modules || artifacts |
      09:30:08.271 [main] INFO org.gradle.logging.IvyLoggingAdaper - | conf | number| search|dwnlded|evicted|| number|dwnlded|
      09:30:08.272 [main] INFO org.gradle.logging.IvyLoggingAdaper - ---------------------------------------------------------------------
      09:30:08.272 [main] INFO org.gradle.logging.IvyLoggingAdaper - | deptester | 1 | 0 | 0 | 0 || 0 | 0 |
      09:30:08.272 [main] INFO org.gradle.logging.IvyLoggingAdaper - ---------------------------------------------------------------------
      09:30:08.272 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - Nbr of module to sort : 1
      09:30:08.272 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - Sort dependencies of : org.testng#testng;4.7 / Number of dependencies = 3
      09:30:08.273 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - Sort done for : org.testng#testng;4.7
      09:30:08.273 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - report for #gradle_dep_issue;unspecified deptester produced in /Users/russ/.gradle/cache/-gradle_dep_issue-deptester.xml
      09:30:08.273 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - resolve done (118ms resolve - 0ms download)
      09:30:08.274 [main] DEBUG o.g.a.i.a.i.DefaultIvyDependencyResolver - Timing: Ivy resolve took 0.124 secs
      09:30:08.282 [main] DEBUG o.g.a.i.a.i.DefaultIvyReportConverter - Timing: Translating report for configuration configuration ':deptester' took 0.0040 secs
      09:30:08.287 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - clientModule: no namespace defined: using system
      09:30:08.288 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - MavenRepo: no namespace defined: using system
      09:30:08.289 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - trying http://repo1.maven.org/maven2/org/testng/testng/4.7/testng-4.7.jar
      09:30:08.290 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - tried http://repo1.maven.org/maven2/org/testng/testng/4.7/testng-4.7.jar
      09:30:08.822 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - HTTP response status: 404 url=http://repo1.maven.org/maven2/org/testng/testng/4.7/testng-4.7.jar
      09:30:08.823 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - CLIENT ERROR: Not Found url=http://repo1.maven.org/maven2/org/testng/testng/4.7/testng-4.7.jar
      09:30:08.823 [main] DEBUG org.gradle.logging.IvyLoggingAdaper - MavenRepo: resource not reachable for org/testng#testng;4.7: res=http://repo1.maven.org/maven2/org/testng/testng/4.7/testng-4.7.jar
      09:30:08.824 [main] DEBUG o.g.a.i.a.i.DefaultIvyDependencyResolver - Resolved artifact org.testng:testng:4.7;default;testng contains a null value.

        Activity

        Hide
        Hans Dockter added a comment -

        I can reproduce this problem. The following snippet exposes this as well:

        apply plugin: 'groovy'
        apply plugin: 'maven'
        
        repositories {
          mavenCentral()
        }
        
        configurations {
           compile.transitive = false
           deptester.transitive = false
        }
        
        dependencies {
          compile group:"org.testng", name:"testng", version:"4.7", classifier:"jdk15"
          deptester group:"org.testng", name:"testng", version:"4.7", classifier:"jdk15"
        }
          
        task show << {
           configurations.compile.each { println it }
           println '-----------'
           configurations.deptester.each { println it }
        }
        

        The show task will show the correct transitive dependencies but does not resolve the actual testng artifact for the deptester configuration. If you choose a different testng version in deptester (e.g. 5.7) everything works as expected. As soon as I have time (I'm on holidays right now) I will look into this.

        Some comments related to your example script but not to the bug.

        • If you do from(config.files) the configuration is resolved during configuration time. This means it will be resolved whether copyFails will be executed or not. Instead you can do: from(config)
        • Independent of the bug Gradle forces you to do a lot of boiler plate code to achieve a simple thing. The 1.0-M1 milestone will focus on making the dependency DSL more powerful. For example to make it very easy to work with anonymous configurations that derive from declared ones. Something like: {{from(configurations.compile.with { transitive = false }

          )}}

        Workaround

        An ugly workaround that might work for you is:

        task copyFail(type: Copy) {
          doFirst {
             from(configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.collect { dep ->
                dep.moduleArtifacts.collect { it.file }
             })
          } 
          def tempDir = new File("${projectDir}/temp")
          tempDir.mkdirs()
          into(tempDir)
            
        }
        

        This only copies the artifacts of the dependencies you have declared into the temp directory. Transitive dependencies are ignored. The from is only executed at execution time to avoid unnecessary resolving (e.g. when doing a clean). Even resolving from cache takes some time with Ivy (0.x secs). Having configuration statement in actions is something we usually try to avoid. It hides configurations information from other task that might be interested in that information at configuration time.

        Show
        Hans Dockter added a comment - I can reproduce this problem. The following snippet exposes this as well: apply plugin: 'groovy' apply plugin: 'maven' repositories { mavenCentral() } configurations { compile.transitive = false deptester.transitive = false } dependencies { compile group:"org.testng", name:"testng", version:"4.7", classifier:"jdk15" deptester group:"org.testng", name:"testng", version:"4.7", classifier:"jdk15" } task show << { configurations.compile.each { println it } println '-----------' configurations.deptester.each { println it } } The show task will show the correct transitive dependencies but does not resolve the actual testng artifact for the deptester configuration. If you choose a different testng version in deptester (e.g. 5.7) everything works as expected. As soon as I have time (I'm on holidays right now) I will look into this. Some comments related to your example script but not to the bug. If you do from(config.files) the configuration is resolved during configuration time. This means it will be resolved whether copyFails will be executed or not. Instead you can do: from(config) Independent of the bug Gradle forces you to do a lot of boiler plate code to achieve a simple thing. The 1.0-M1 milestone will focus on making the dependency DSL more powerful. For example to make it very easy to work with anonymous configurations that derive from declared ones. Something like: {{from(configurations.compile.with { transitive = false } )}} Workaround An ugly workaround that might work for you is: task copyFail(type: Copy) { doFirst { from(configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.collect { dep -> dep.moduleArtifacts.collect { it.file } }) } def tempDir = new File("${projectDir}/temp") tempDir.mkdirs() into(tempDir) } This only copies the artifacts of the dependencies you have declared into the temp directory. Transitive dependencies are ignored. The from is only executed at execution time to avoid unnecessary resolving (e.g. when doing a clean). Even resolving from cache takes some time with Ivy (0.x secs). Having configuration statement in actions is something we usually try to avoid. It hides configurations information from other task that might be interested in that information at configuration time.
        Hide
        Luke Daley added a comment -

        Daz, assigning to you in case this relates to the classifier work you are doing. If not, just unassign it again.

        Show
        Luke Daley added a comment - Daz, assigning to you in case this relates to the classifier work you are doing. If not, just unassign it again.

          People

          • Assignee:
            Daz DeBoer
            Reporter:
            Russ Rollins
          • Votes:
            2 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development