There is clearly some confusion concerning task creation and addition to
tasks. Both task abc, task abc {}, and task abc << {} create a task, and both
will complain if one already exists (let's ignore overwrite: true for the
moment).
Consider the below definitions
task bob << { println '7' }
bob.doLast() { println '8' }
bob { println '1' }
bob { configure { println '2' } }
bob { doLast { println '9' } }
bob.doFirst { println '6' }
bob { println '3' ; doLast { println '10' } ; doFirst { println '5' } }
bob.configure { println '4' }
Running "gradle -q bob" gives you 1 .. 10 listed in order. Running without the
-q flag actually is helpful in showing where configuration occurs, and where
execution occurs, as ":bob" will show up after "4" and before "5" in the output.
task abc << { action }
really is just shorthand for:
task abc { doLast { action } }
I actually need doFirst and doLast (and yes, it works with or without the
parens, so doLast or doLast() is preference at this point), so I must vote to
retain the ability to prepend and append at the execution phase. I thought I'd
require that ability during the configuration phase too, but so far that hasn't
been true - at least yet :-)
All things not in any named closure or the configuration closure happen in the
order they are defined during the configuration phase.
Then all doFirst closures happen in the reverse order they are defined during
the execution phase.
Finally, all doLast closures happen in the order they are defined during the
execution phase.
I believe that most of the confusion occurs because the "default" desired
behavior is to have tasks that do something at execution time, but the
non-short form happens at configuration time only.
It probably would be quite disruptive to the parsing I suspect (and existing
scripts), but maybe the default behavior should be an implicit doLast, and to
have things that absolutely need to happen at configuration time can use the
configure closure.
Then the short form would simply be the "normal" form, and the "<<" is much
less relevant, as it's usually only more advanced operations that might require
much at configuration time:
task myTask { implicitDoLastRunAtExecTime }
task myTask { configure { runAtConfigTime } ; implicitDoLastRunAtExecTime }
-Spencer
--- On Sun, 4/4/10, Geronimo M. H. <[email protected]> wrote:
I vote against reducing the number of (possible) task-actions and against the
removal of doFirst() and doLast().
I don't know, whether I understand things right, I stored (in my mind) the
behaviour of task definitions that
task {
action
}
is run during configuration stage, and could be used to configure an existing
task (with the same name), whereas the task definition of
task << {
action
}
is a "real" task definition, which runs at execution stage and will fail, if a
task of the same name already exists.
I very appreciate both - doFirst() and doLast() - to extend an already
existing task. I beleive, that extending existing tasks with an userdefined
action is easier to understand or implement, than breaking up an existing
task-dependency graph and adding a completely new task at the right point.