Hi,

I've made a few changes to how you implement tasks over the last month or so. Here's a bit of a summary, with some questions at the end.

1. You don't need to provide a constructor any more.

We now inject the project and name around the side directly into AbstractTask. This means we can also inject other things, such as the OutputHandler, without exposing this to the task implementations.

2. You can mark the 'main' method of a task with the @TaskAction annotation. It automatically gets added as a task action.

3. There's some documentation: http://gradle.org/latest/docs/userguide/custom_tasks.html

4. You can mark the input and output properties of a task using annotations:

@InputFile
public File getConfigFile()

@InputDirectory
public File getTestClassesDir()

@InputFiles
public Iterable<File> getSourceDirs()

@OutputFile
public File getReportFile()

@OutputDirectory
public File getDestinationDir()

Currently, we use these annotations to apply some validation to the task properties. The validation is added as a task action, so it is performed just before the task is executed:

@InputFile/@InputDirectory: Check the property is not null, and the specified file exists and is a file/directory
@InputFiles: Check the property is not null.
@OutputFile/@OutputDirectory: Check the property is not null, and that the specified file can be created as a file/directory. Also create the parent dir if it does not exist.

There's also an @Optional annotation, which switches off the not-null check, and a @SkipWhenEmpty, which skips the task if the associated @InputFiles property is an empty FileCollection.

I'd like to use these annotations to also:

- Wire up dependencies. For example, we know that build/classes/main is an output file of both the compileTest and processTestResources tasks, and an input file of the test task, so we could automatically add the these as dependencies of the test task. We also know that the classpath of the test task is actually the testRuntime configuration, so we could automatically add its buildDependencies to the test task.

That is,

task intTests(type: Test) {
testClassesDir = source.intTests.classesDir // auto add compileIntTest and processIntTestResources classpath = configurations.testRuntime // auto add testRuntime.buildDependencies
}

- Apply optimisation. For example, we know that build/classes/main and testRuntime are input files of the test task, and that build/reports/test is an output dir of the test task. We can skip test if its input files have not changed since it last executed successfully and if its output dir exists and is not empty. We can decide whether its input files have changed by hashing them, or using their timestamps, or the last successful execution time of the tasks which produce those files.

One question I have is how to apply this to task actions which are added to the task as closures:

task intTests(type: Test)
intTests.doFirst {
   .. some setup ..
}

or

task explodedDistBase << {
  .. copy some stuff ..
}

One option is to allow you to declare the input and output files of a task:

task explodedDistBase(inputDirs: source.main.groovySrcDirs, outputDir: distDir) << {
   copy { from inputDirs; into outputDir }
}

where 'inputFile', 'inputDirs', 'inputFiles', 'outputDir', etc correspond to the @InputFile annotation, etc, and are added as properties of the task.

Another question is what other annotations we should add.

Thoughts?


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email


Reply via email to