groovyclosuresgradleantbuilder

Reduce code repetition in Groovy closures


In a piece of Gradle build script, the amount of code i'm repeating is increasing. All tasks have a big part in common, except for a few lines:

task copyZipFile() {
    doLast {
        def remoteBuildProperties = getRemoteBuildProperties(project)
        ant {
            taskdef(name: 'ftp',
                    classname: 'org.apache.tools.ant.taskdefs.optional.net.FTP',
                    classpath: configurations.ftpAntTask.asPath)

            ftp(server: remoteBuildProperties['host.name'],
                    userid: remoteBuildProperties['username'],
                    password: remoteBuildProperties['password'],
                    remotedir: 'some-folder', // This value differs from call to call
                    passive: 'true') {
                // The next two lines also are different per case, and might be less or more lines
                fileset(dir: rootProject.buildDir) { include(name: 'build.zip') }
                fileset(dir: rootProject.projectDir) { include(name: 'build.properties') }
            }
        }
    }
}

I don't like to repeat myself, so I'd like to reduce this code to a new helper method that does this trick, and a simple caller, something like:

task copyZipFile() {
    doLast {
        def remoteBuildProperties = getRemoteBuildProperties(project)
        upload(remoteBuildProperties, 'some-folder') {
            fileset(dir: rootProject.buildDir) { include(name: 'build.zip') }
            fileset(dir: rootProject.projectDir) { include(name: 'build.properties') }
        }
    }
}

How would I achieve this?


Solution

  • You can pass the inner closure to your upload method as the final parameter. Set the delegate to the original builder delegate so the inner closure calls get handled properly. For example:

    def upload(remoteBuildProperties, folder, body) {
        ant {
            taskdef(name: 'ftp',
                    classname: 'org.apache.tools.ant.taskdefs.optional.net.FTP',
                    classpath: configurations.ftpAntTask.asPath)
    
            ftp(server: remoteBuildProperties['host.name'],
                    userid: remoteBuildProperties['username'],
                    password: remoteBuildProperties['password'],
                    remotedir: folder,
                    passive: 'true') {
                body.delegate = delegate
                body()
            }
        }
    }