Gradle copy task fails silently - gradle

I have a copy task for 1 file
task myCopyTask(type: Copy) {
copy {
from "/path/to/my/file"
into "path/to/out/dir"
}
}
How to do, so the task fails if the copy fails? Right now if the file does not exist, it does not give an error.
Fail Gradle Copy task if source directory not exist gives a solution. This does not work, because if everything is not inside of
copy { ... }
the task does not work at all.
I tried also
task myCopyTask(type: Copy) {
copy {
from "/path/to/my/file"
into "path/to/out/dir"
inputs.sourceFiles.stopExecutionIfEmpty()
}
}
The above would fail, as inputs.sourceFiles would be empty.

Why don't you specify your task as:
task myCopyTask(type: Copy) {
from "/path/to/my/file"
into "path/to/out/dir"
inputs.sourceFiles.stopExecutionIfEmpty()
}
This would work as expected during execution phase, while your solution would try to copy something during configuration phase of the build every time you call any task.

The very first definition of the tasks actually doesn't do what you expect from the task:
task myCopyTask(type: Copy) {
copy {
from "/path/to/my/file"
into "path/to/out/dir"
}
is acutually same as
task myCopyTask(type: Copy) {
project.copy {
from "/path/to/my/file"
into "path/to/out/dir"
}
}
And it will execute copy action during task configuration, no matter if the task is called or not.
What you need is:
task myCopyTask(type: Copy) {
from "/path/to/my/file"
into "path/to/out/dir"
doFirst {
if(inputs.empty) throw new GradleException("Input source for myCopyTask doesn't exist")
}
}

This solution for Kotlin DSL works for me:
tasks.register<Copy>("myCopyTask") {
val path = "/path/to/my/file"
from(path)
into("path/to/out/dir")
if (inputs.sourceFiles.isEmpty) {
throw GradleException("File not found: $path")
}
}

Related

Copy file from another project in a Gradle task

Given is the following Gradle task:
task copyResource(type: Copy) {
from('.') {
include '../anotherProject/password.txt'
}
into 'build/docker'
}
On task execution the include is ignored. What is the correct way to reference to a file from another project directory?
Try this :
task copyResource(type: Copy) {
from('../anotherProject') {
include 'password.txt'
}
into 'build/docker'
}
or even simpler :
task copyResource(type: Copy) {
from('../anotherProject/password.txt')
into 'build/docker'
}

Gradle Copy Task Is UP-TO-DATE After Manually Deleting a File

I am forced to use Gradle 2.3 in this project.
I am trying to copy a set of dependencies from a custom configuration to a specific dir.
If I delete one of the files manually, Gradle still marks the task as UP-TO-DATE and I end up with an incomplete set of files.
task copyFiles(type: Copy) {
from configurations.zips
into 'zip-dir'
configurations.zips.allDependencies.each {
rename "-${it.version}", ''
}
}
This works as expected in v4.0.2 though.
To work around it I am counting files in that dir.
task copyFiles(type: Copy) {
outputs.upToDateWhen {
def count = new File('zip-dir').listFiles().count { it.name ==~ /.*zip/ }
count == configurations.zips.files.size()
}
from configurations.zips
into 'zip-dir'
configurations.zips.allDependencies.each {
rename "-${it.version}", ''
}
}
Which issue and version of gradle was this fixed in and is there a better workaround than what I have so far?
You can just run it always with
outputs.upToDateWhen { false }
or not use a type Copy for your task and
task copyFiles {
doLast {
copy {
from configurations.zips
into 'zip-dir'
configurations.zips.allDependencies.each {
rename "-${it.version}", ''
}
}
}
}
Note that this is a workaround not the solution

gradle tasks -all throwing error

I have test build.gradle file as follows
task someTask(type: Sync) {
def folder = new File('fold1/fold2/');
if(!folder.exists()) {
throw new GradleException('Folder Absent');
}
else {
}
}
When I do gradle tasks --all it is running the task and throwing exception. I was thinking that only when this task is run that it will check for folder but it is actually running it for any task I run.
Can someone suggest workaround for this?
Thanks in advance.
Your code is executed during the configuration phase and not during the execution phase. You need to put it in a doFirst or doLast block:
task someTask(type: Sync) {
doLast {
def folder = new File('fold1/fold2/');
if (!folder.exists()) {
throw new GradleException('Folder Absent');
}
else {
}
}
}
See also: Why is my Gradle task always running?

Is there a way to "merge" gradle tasks to avoid many dependsOn declarations

Suppose this gradle script:
task copyGroovyScript(dependsOn: prepare, type: Copy) {
from "${scriptSrcLocation}/${scriptSrcName}"
into buildFolderZipSource
}
task copyDependenciesForGroovyScript(dependsOn: copyGroovyScript, type: Copy) {
from configurations.groovyScript.resolve()
into "${buildFolderZipSource}/groovy-plugin-lib"
}
task copyTestScripts(dependsOn: copyDependenciesForGroovyScript, type: Copy ) {
from "${scriptSrcLocation}/ReadClient.groovy"
into "${buildFolderZipSource}/test"
}
task copyTestScriptsBin(dependsOn: copyTestScripts, type: Copy ) {
from "${scriptSrcLocation}/bin"
into "${buildFolderZipSource}/test/bin"
}
task copyDependenciesForTestScripts(dependsOn: copyTestScriptsBin, type: Copy) {
from configurations.testScripts.resolve()
into "${buildFolderZipSource}/test/lib"
}
task packageAll(dependsOn: copyDependenciesForTestScripts, type:Zip) {
archiveName "output-${buildTime()}.zip"
excludes ['*.zip']
destinationDir buildFolder
from buildFolder
}
I need different Copy tasks before they have different output folders.
Is there a way to avoid having to have all those dependsOn statements and just have gradle execute things in order of declaration in the file somehow?
There's no way to execute in the way it's declared. But why don't you go this way:
task packageAll(dependsOn: copyDependenciesForTestScripts, type:Zip) {
doFirst {
copy {
from "${scriptSrcLocation}/${scriptSrcName}"
into buildFolderZipSource
}
}
//following doFirst and so on..
archiveName "output-${buildTime()}.zip"
excludes ['*.zip']
destinationDir buildFolder
from buildFolder
}
EDIT
After discussion in comments it turned out that the following piece of code should do the job
task prepare {
doFirst {
copy {
from "${scriptSrcLocation}/${scriptSrcName}"
into buildFolderZipSource
}
}
//following doFirst and so on..
}
task packageAll(dependsOn: prepare, type:Zip) {
archiveName "output-${buildTime()}.zip"
excludes ['*.zip']
destinationDir buildFolder
from buildFolder
}

Change copy task destination

I would like to change the destination dir for file copy depending on the chosen build.
This does not work since the task graph is executed in execution phase but the copyTask is set in configuration phase.
How can I achieve this?
gradle.taskGraph.whenReady { taskGraph ->
println('taskGraph')
if (taskGraph.hasTask(buildRelease)){
File toDir=file('test/r')
println('Copy to: ' + toDir.getName())
}else if (taskGraph.hasTask(buildDevel)) {
File toDir=file('test/d')
println('Copy to: ' + toDir.getName())
}
}
task buildDevel (dependsOn: ['copyTask']){}
task buildRelease (dependsOn: ['copyTask']){}
task copyTask(type: Copy) {
from "test"
into toDir
include 'a.txt'
}
This may help You (You need to create a.txt file on the same level as build.gradle is located:
gradle.taskGraph.whenReady { taskGraph ->
def cp = project.copyTask
if (taskGraph.hasTask(buildRelease)){
cp.into 'lol1'
} else if (taskGraph.hasTask(buildDevel)) {
cp.into 'lol2'
}
}
task buildDevel (dependsOn: ['copyTask']){}
task buildRelease (dependsOn: ['copyTask']){}
task copyTask(type: Copy) {
from file('.')
include 'a.txt'
}
This will also work:
task buildDevel
task buildRelease
buildDevel.doFirst {
cp('lol1')
}
buildRelease.doFirst {
cp('lol2')
}
def cp(to) {
copy {
from file('.')
into to
include 'a.txt'
}
}

Resources