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

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

Related

Gradle JAR Creation Timing

i have a gradle build that retrieves properties file and such that are remote (to keep passwords out of github) but the remote retrieval doesn't complete by the time the JAR is built.
i figured i either had to get the JAR created in the execution phase instead of configuration phase or add the remote files in the execution phase but i couldn't get either working.
any suggestions?
task fatJar(type: Jar) {
doFirst {
exec {
executable './scripts/getRemoteResources.sh'
}
}
...
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
//some resources are retrieved remotely & b/c of timing they don't get included here
from ('src/main/java/resources') {
include '*'
}
with jar
//tried this but doesn't work
//doLast {
// jar {
// from ('src/main/java/resources') {
// include '*'
// }
// }
//}
}
You shouldn't use the task graph for this. Also you shouldn't download the file to src/main/
Instead, you should
Create a task to download the remote resources to a directory under $buildDir (so it's cleaned via the "clean" task)
Configure the TaskOutputs so that the result can be cached and re-used.
Wire the task into Gradle's DAG
Add the directory to the "processResources" task so it ends up on the runtime classpath (ie in the jar)
Eg:
tasks.register('remoteResources', Exec) {
inputs.property('environment', project.property('env')) // this assumes there's a project property named 'env'
outputs.dir "$buildDir/remoteResources" // point 2 (above)
commandLine = [
'./scripts/getRemoteResources.sh',
'--environment', project.property('env'),
'--outputdir', "$buildDir/remoteResources"
]
doFirst {
delete "$buildDir/remoteResources"
mkdir "$buildDir/remoteResources"
}
}
processResources {
from tasks.remoteResources // points 3 & 4 (above)
}
See The Java Plugin - Tasks
processResources — Copy
Copies production resources into the production resources directory.
this seems to work so i'm going with it unless someone has a better solution...
gradle.taskGraph.beforeTask { Task task ->
println "just before $task.name"
// i just chose to kick this off with the first task sent through here
if (task.name=="compileJava") {
exec {
executable './scripts/getRemoteResources.sh'
}
}
}
task fatJar(type: Jar) {
...
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
from ('src/main/java/resources') {
include '*'
}
with jar
}

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'
}

How do I perform a rename on only one "from" in a Gradle Copy task?

I am trying to copy from multiple "from" locations on a single Gradle Copy task. For one of those - and only one - I want to also perform a rename operation.
This code works:
task dist(type: Copy) {
from task1
rename { filename -> filename.replace '-all.jar', '.jar' }
from task2 { exclude "lib" }
into "${projectDir}/dist"
}
But the renaming operation also affects task2. I tried doing it this way:
task dist(type: Copy) {
from task1 { rename { filename -> filename.replace '-all.jar', '.jar' } }
from task2 { exclude "lib" }
into "${projectDir}/dist"
}
But it does not do the renaming operation. The exclude operation on task2 works as expected. Is it possible? Am I missing something in the syntax?
Someone posted the solution here and deleted it before I could accept/reply, so I'm posting the correct form here for future reference:
task dist(type: Copy) {
from (task1) { rename { filename -> filename.replace '-all.jar', '.jar' } }
from (task2) { exclude "lib" }
into "${projectDir}/dist"
}
Thanks, Opalo!

Gradle task to create a zip archive of a directory

I have a gradle task to create a zip archive of a directory.
The gradle task is:
task archiveReports(type: Zip) {
from '/projects/Reports/*'
archiveName 'Reports.zip'
}
When I am running the command 'gradle archiveReports', its showing the build is successful. However, no zip file is getting created.
Am I missing something here?
I figured out a way for this:
Its working for me now.
task myZip(type: Zip) {
from 'Reports/'
include '*'
include '*/*' //to include contents of a folder present inside Reports directory
archiveName 'Reports.zip'
destinationDir(file('/dir1/dir2/dir3/'))
}
With Gradle 6.7,
task packageDistribution(type: Zip) {
archiveFileName = "my-distribution.zip"
destinationDirectory = file("$buildDir/dist")
from "$buildDir/toArchive"
}
Note : archiveName is deprected.
With Kotlin DSL
tasks.register<Zip>("packageDistribution") {
archiveFileName.set("my-distribution.zip")
destinationDirectory.set(layout.buildDirectory.dir("dist"))
from(layout.buildDirectory.dir("toArchive"))
}
With Groovy
tasks.register('packageDistribution', Zip) {
archiveFileName = "my-distribution.zip"
destinationDirectory = layout.buildDirectory.dir('dist')
from layout.buildDirectory.dir("toArchive")
}
Taken from the official docs
Just in case anyone will come here to find out how to zip your project e.g. to use it as an AWS lambda zip, here you go:
tasks {
val zipTask by register("createZip", Zip::class) {
from(processResources)
from(compileKotlin)
archiveFileName.set("app.zip")
into("lib") {
from(configurations.runtimeClasspath)
}
}
build {
dependsOn(zipTask)
}
}

Gradle copy without overwrite

Is there a way to avoid overwriting files, when using task type:Copy?
This is my task:
task unpack1(type:Copy)
{
duplicatesStrategy= DuplicatesStrategy.EXCLUDE
delete(rootDir.getPath()+"/tmp")
from zipTree(rootDir.getPath()+"/app-war/app.war")
into rootDir.getPath()+"/tmp"
duplicatesStrategy= DuplicatesStrategy.EXCLUDE
from rootDir.getPath()+"/tmp"
into "WebContent"
}
I want to avoid to specify all the files using exclude 'file/file*'.
It looks like that duplicatesStrategy= DuplicatesStrategy.EXCLUDE doesn't work. I read about an issue on gradle 0.9 but I'm using Gradle 2.1.
Is this problem still there?
Or am I misunderstanding how this task should be used properly?
Thanks
A further refinement of BugOrFeature's answer. It's using simple strings for the from and into parameters, uses the CopySpec's destinationDir property to resolve the destination file's relative path to a File:
task ensureLocalTestProperties(type: Copy) {
from zipTree('/app-war/app.war')
into 'WebContent'
eachFile {
if (it.relativePath.getFile(destinationDir).exists()) {
it.exclude()
}
}
}
You can always check first if the file exists in the destination directory:
task copyFileIfNotExists << {
if (!file('destination/directory/myFile').exists())
copy {
from("source/directory")
into("destination/directory")
include("myFile")
}
}
Sample based on Peter's comment:
task unpack1(type: Copy) {
def destination = project.file("WebContent")
from rootDir.getPath() + "/tmp"
into destination
eachFile {
if (it.getRelativePath().getFile(destination).exists()) {
it.exclude()
}
}
}

Resources