Alternative pattern to deal with special checkout/clean/init type tasks


(spencer_allain) #1

doing “gradle init release” from the command line does exactly what one wants, but ideally you want to programmatically have “gradle release” call “init” before any other dependent tasks would ever get invoked.

Technically it seems possible that the task graph can be constructed, examined, and then the exact nodes to descend from could be selectable before execution actually occurs (akin to what happens to the startParameter.taskNames gets mapped to internally).

Below shows what can be done with a project variable (could as easily be a system variable) and a failed attempt at trying to change the tasks to execute after the task graph is ready.

task init { doLast { println 'init' }}
  task release {
  // Works, but not ideal
  if (project.hasProperty('doRelease')) {
    project.gradle.startParameter.taskNames = ['init'] +
      project.gradle.startParameter.taskNames
  }
}
  gradle.taskGraph.whenReady { graph ->
  // Too late
  if (graph.hasTask(':release')) {
    project.gradle.startParameter.taskNames = ['init'] +
      project.gradle.startParameter.taskNames
  }
}

I’ve not considered all the possible side effects, but it seems that marking the fixed order of the nodes where depth-first execution searches start from is already possible from the command line, and this would simply be exposing that capability to the build scripts after the DAG is ready (it would not attempt to change any links in the graph, just essentially provide the ordered list of nodes to start working from).

-Spencer


(andrew.oberstar) #2

How about something like this?

task init << { println 'init' }
  gradle.taskGraph.whenReady { graph ->
  init.onlyIf { graph.hasTask(':release') }
}

You’d still have to do something to make sure the init task ran first, though…


(Peter Niederwieser) #3

@Spencer: Sounds like a good thing to have. Besides that, I think we also need a way to inspect the task graph and still make changes to it (like adding dependencies). tI’m envisioning a two-pass algorithm with ‘whenPrepared’ and ‘whenReady’ callbacks.


(Matthias Pfau) #4

@Peter: That’ exactly what we need, too.