[GRADLE-2439] strange behaviour with recursive method calls Created: 20/Aug/12  Updated: 10/Feb/17  Resolved: 10/Feb/17

Status: Resolved
Project: Gradle
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug
Reporter: Björn Kautler Assignee: Unassigned
Resolution: Won't Fix Votes: 0


If I have the following code:

void generateChecksums(def files, def destination) {
   println files.getClass().name
   def checksums = [
         [suffix: 'md5', checksum: MessageDigest.getInstance("MD5")],
         [suffix: 'sha1', checksum: MessageDigest.getInstance("SHA-1")]
   def generateChecksums = {
      file ->
      def writeChecksum = {
         def checksumDigest = it.checksum.digest()
         def checksumFile = new File(destination, "${file.name}.$it.suffix")
         checksumFile.withPrintWriter { it.printf("${'%02x' * checksumDigest.size()} $file.name\n", checksumDigest) }

      checksums.each writeChecksum

   switch (files) {
      case { File.isCase(it) && it.file }:
         generateChecksums files

      case { File.isCase(it) && it.directory }:
         files.eachFileRecurse FILES, generateChecksums

      case TaskOutputs:
         generateChecksums files.files, destination

         files.each { generateChecksums it, destination }

it doesn't work if I feed in a TaskOutputs instance or something that matches default case. e. g. called like

   task dist(dependsOn: 'ear', type: Copy) {
      def destination = ...
      from ear
      into destination
      doLast {
         generateChecksums ear.outputs, destination

it doesn't work. While I'd assume that on the first call the TaskOutputs case matches and calls again with its files property, it strangely gets called again with the TaskOutputs instance while files.files yields the correct expected result.

If I add the method

private void generateChecksumsWrapper(def files, def destination) {
   generateChecksums(files, destination)

and exchange both recursive calls with calls to the wrapper, everything works like expected.
I think this is a Gradle and not a Groovy bug as doing the following in Groovy works just fine:

def test(def x, def y) {
   println x
   if (x.length() < 6) {
      test("$x$x", y)
test('x', 'y')

Comment by Björn Kautler [ 20/Aug/12 ]

Please ignore the first line of the last code example, that was wrongly copied.

Comment by Björn Kautler [ 02/Jun/14 ]

Hm, I think this was just error by me. I cannot reprodue that it is called multiple times with the same input, but instead the local generateChecksums closure shadowed the generateChecksums method, even though the method takes 2 arguments and the closure one. If I change the name of the local closure to generateFileChecksums it works fine. So please close this as invalid.

Comment by Benjamin Muschko [ 15/Nov/16 ]

As announced on the Gradle blog we are planning to completely migrate issues from JIRA to GitHub.

We intend to prioritize issues that are actionable and impactful while working more closely with the community. Many of our JIRA issues are inactionable or irrelevant. We would like to request your help to ensure we can appropriately prioritize JIRA issues you’ve contributed to.

Please confirm that you still advocate for your JIRA issue before December 10th, 2016 by:

  • Checking that your issues contain requisite context, impact, behaviors, and examples as described in our published guidelines.
  • Leave a comment on the JIRA issue or open a new GitHub issue confirming that the above is complete.

We look forward to collaborating with you more closely on GitHub. Thank you for your contribution to Gradle!

Comment by Benjamin Muschko [ 10/Feb/17 ]

Thanks again for reporting this issue. We haven't heard back from you after our inquiry from November 15th. We are closing this issue now. Please create an issue on GitHub if you still feel passionate about getting it resolved.

Generated at Wed Jun 30 12:21:57 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.