Quantcast
Channel: Gradle Forums - Latest posts
Viewing all articles
Browse latest Browse all 19859

Short-circuit dependency chain if task outputs exist

$
0
0

I have a linear chain of dependent tasks: consume depends on generate depends on download. The download task is slow and unreliable, but changes rarely, so we intend to produce generate’s single output file once and store it in our source repository. We’d like to consider the generate output as up-to-date if it exists at all. But if generate’s output file is missing, then the download should happen followed by generate.

These three tasks are configured as follows, making full use of lazy configuration and task configuration avoidance:

final download = tasks.register('download') {
	outputs.file layout.buildDirectory.file(name)
	doFirst {
		println "$it: run"
		outputs.files.singleFile.text = ''
	}
}

final generate = tasks.register('generate') {
	inputs.files download
	outputs.file layout.buildDirectory.file(name)
	doFirst {
		println "$it: run"
		outputs.files.singleFile.text = ''
	}
	outputs.upToDateWhen { outputs.files.singleFile.exists() }
}

tasks.register('consume') {
	inputs.files generate
	outputs.file layout.buildDirectory.file(name)
	doFirst {
		println "$it: run"
		outputs.files.singleFile.text = ''
	}
}

Unfortunately, the outputs.upToDateWhen { outputs.files.singleFile.exists() } directive in the generate task is insufficient. If I remove build/download, then running the consume task causes the download task to run as well, even though generate’s own outputs are claimed to be up-to-date already. I have also tried adding onlyIf { !outputs.files.singleFile.exists() } to generate’s configuration, but that is likewise ineffective: removing build/download still causes download to rerun even if generate’s output file already exists.

The only way I can think of to prevent unwanted download task runs is to configure consume in two different ways depending on whether generate’s output file exists:

tasks.register('consume') {
	final alreadyGenerated = generate.get().outputs.files.singleFile
	inputs.files (alreadyGenerated.exists() ? alreadyGenerated : generate)
	...
}

That will work, but having the task dependency graph change depending on build-time conditions feels sketchy. Is there a more elegant way to manage my situation?


Viewing all articles
Browse latest Browse all 19859

Trending Articles