Difference between Copy task and copy {}?


(Klaus Grønbæk) #1

Some times you assemble an archive from many different location, and you end up with lots of small Copy tasks. This is harder to read and pollutes the task list in my IDE (intelliJ). Instead of creating a Copy task you can create a type-less task and use copy with closure, at the expense of automatic up-to-date-check, but what exactly is copy in this case, and where do I find the documentation. The reason for asking is that I tried this with Delete vs delete {} and and I was surprised by the result

task debug(type: Delete) {
    delete fileTree(dir: 'build/help')
}

Defining a delete task works as expected.

task debug() << {
    delete {
        delete fileTree(dir: 'build/help')
    }
}

This does nothing except print the following to the console: Converting class java.lang.Boolean to File using toString() method has been deprecated and is scheduled to be removed in Gradle 2.0. Please use java.io.File, java.lang.String, java.net.URL, or java.net.URI instead.


(Peter Niederwieser) #2

General rule: Always prefer task over method, unless there is a concrete (and valid) reason not to.

Some times you assemble an archive from many different location, and you end up with lots of small Copy tasks.

This can be done with a single ‘Copy’ task, and doesn’t require the use of the ‘project.copy’ method.

This does nothing except print the following to the console:

It’s ‘delete fileTree(…)’, not ‘delete { delete fileTree(…) }’.

For documentation, see the Gradle Build Language Reference and the Gradle User Guide (try browser full-text search on the latter).

As for difference between task and method, the former gives you all the advantages of tasks (up-to-date checks etc.), the latter gives you more flexibility when you need it (e.g. you can call the method from your own task implementation).


(Klaus Grønbæk) #3

Thanks for the explanation Peter. However I don’t see how the Copy task can have multiple into? My script is constructing the distribution folder, that will later be tar.gz for a Linux ‘instalation’. My file tree looks something like this ├── API ├── Icons ├── lib │ ├── jdbc │ ├── patch │ ├── thirdparty │ │ └── extra │ └── tomcat ├── nativelib │ ├── 782 │ │ └── linux-x64 │ │

├── imageformats │ │

└── platforms │ ├── 789 │ │ └── linux-x32 │ │

├── imageformats │ │

└── platforms │ └── 801 │

└── windows-x32 │

├── imageformats │

└── platforms ├── Plugins ├── Resources └── WebApps


(Peter Niederwieser) #4
task createDistribution(type: Sync) {
  into "$buildDir/distribution"
  from "somewhere/top-level-file"
  into("lib") {
    from ...
    include ...
    into("thirdparty") {
      from ...
    }
    ...
  }
  into("Plugins") {
    from ...
    ...
  }
  ...
}

If you need to create a Tar, the recommended practice is not to go through an intermediate distribution directory, but to create the Tar in one go (replace ‘Sync’ with ‘Tar’ in the above, and remove the top-level ‘into’). If necessary, you can still keep the ‘Sync’ task for creating an exploded distribution. The commonalities between the two tasks can be configured together, e.g. using ‘configure(task1, task2) { … }’ or using a copy spec (see Gradle User Guide for details).


(Klaus Grønbæk) #5

Thanks a bunch, that example was just what I was looking for. As a Java developer with no groovy experience, the use of nested closures is unfamiliar, and far more easy to get from an example than reading the documentation. Now I know to look for methods with the CopySourceSpec argument =)