Mikyjpeg
Mikyjpeg

Reputation: 1219

How to dynamically create a task in gradle plugin?

I'm developing a gradle plugin and I'm facing with a problem while I try to dynamically create tasks.

Here is my code snippet:

apply plugin: BootstrapPlugin

bootstrapConfig {
    basedir = "C:/temp/unzip"
    componentList = [
        [
            zipName: "test1",
            zipVersion: "_2",
            zipNetworkLocation: "temp",
            zipUnpackLocation: "${basedir}"
        ],
        [
            zipName: "test2",
            zipVersion: "_1",
            zipNetworkLocation: "temp",
            zipUnpackLocation: "${basedir}"
        ]
    ]
}

class BootstrapPlugin implements Plugin<Project> {
    void apply(Project project){
        project.extensions.create("bootstrapConfig",BootstrapConfigPluginExtension)
        project.task("unzipAll", dependsOn: project.tasks.matching { Task task -> task.name.startsWith("unzipSingle")}){
           println "DOIT!"
        }

        project.bootstrapConfig.componentList.each { element ->
            project.task "unzipSingle${element.zipName}" (type: Copy)   {
                def artifactFile = new File(project.bootstrapConfig.shareUrl + "/" + element.zipNetworkLocation + "/" + element.zipName + element.zipVersion + ".zip")
                def pathDestination = element.zipUnpackLocation + "/" + element.zipName + element.zipVersion
                def touchFileName = pathDestination + "/" + element.zipName + element.zipVersion + ".pid"
                from project.zipTree(artifactFile)
                into pathDestination
            }
        }
    }
}

class BootstrapConfigPluginExtension {
    String basedir
    def componentList = []
}

When I try to run it the problem is that no one of the tasks I'm trying to create exists. Running unzipAll it only run that task as it depends from no others.

What I'm doing wrong?

Upvotes: 2

Views: 2061

Answers (1)

Opal
Opal

Reputation: 84784

Here's how it goes:

  1. All script statements are parsed in order they're declared.
  2. apply plugin: BootstrapPlugin is executed.
  3. At the time BootstrapPlugin is applied bootstrapConfig closure wasn't parsed yet. Since it wasn't parsed BootstrapPlugin knows nothing about the config and iterates over empty collection.
  4. bootstrapConfig closure is parsed now when it's useless.

The solution is to create dynamic tasks in afterEvaluate block:

apply plugin: BootstrapPlugin

bootstrapConfig {
    basedir = 'C:/temp/unzip'
    shareUrl = 'http://lol.com'
    componentList = [
        [
            zipName: "test1",
            zipVersion: "_2",
            zipNetworkLocation: "temp",
            zipUnpackLocation: "${basedir}",
        ],
        [
            zipName: "test2",
            zipVersion: "_1",
            zipNetworkLocation: "temp",
            zipUnpackLocation: "${basedir}",
        ],
    ]
}

class BootstrapPlugin implements Plugin<Project> {
  void apply(Project project){
    project.extensions.create('bootstrapConfig', BootstrapConfigPluginExtension)
    project.afterEvaluate {
      project.task("unzipAll", dependsOn: project.tasks.matching { Task task -> task.name.startsWith("unzipSingle")}){
        println "DOIT!"
      }

      project.bootstrapConfig.componentList.each { element ->
        project.task("unzipSingle${element.zipName}",type: Copy) {
          def artifactFile = new File(project.bootstrapConfig.shareUrl + "/" + element.zipNetworkLocation + "/" + element.zipName + element.zipVersion + ".zip")
          def pathDestination = element.zipUnpackLocation + "/" + element.zipName + element.zipVersion
          def touchFileName = pathDestination + "/" + element.zipName + element.zipVersion + ".pid"
          from project.zipTree(artifactFile)
          into pathDestination
        }
      }
    }
  }
}

class BootstrapConfigPluginExtension {
    String basedir
    String shareUrl
    def componentList = []
}

Now the tasks do exist and can be run, however they won't be listed with gradle tasks.

Here is the demo.

Upvotes: 9

Related Questions