Gradle copy without overwrite - gradle

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()
}
}
}

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

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 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 Zip Task: Replace Entire File Content While Being Copied

I currently have a set of files that contain a DSL that needs to be parsed and converted to XML before being copied over to the destination build directory.
I'm using the eachFile hook to accomplish this, but when I replace the content of the file the source file is being changed as well:
task build(type: Zip) {
with {
archiveName = "${project.name}-${project.version}.${extension}"
destinationDir = buildDir
}
from('workflow/dsl') {
eachFile { fileDetails ->
String xml = new OozieDslParser().parse(fileDetails.getFile())
fileDetails.setName(fileDetails.getName().replaceFirst(~/\.[^\.]+$/, '.xml')
fileDetails.getFile().text = xml //This changes the source file as well.
}
}
from('workflow/resources')
}
What is the best way to approach this problem?
Unfortunately, the 'expand' and 'filter' options don't seem to work as the former just expands properties and the latter only feeds me one line at a time.
Thanks!
I used a custom FilterReader to solve this problem:
class OozieDslFilter extends FilterReader {
OozieDslFilter(Reader input) {
super(new StringReader(new OozieDslParser().parse(input.text)))
}
}
task build(type: Zip) {
with {
archiveName = "${project.name}-${project.version}.${extension}"
destinationDir = buildDir
}
from('workflow/resources')
from('workflow/dsl') {
rename { it - ~/\.[^\.]+$/ + '.xml' }
filter(OozieDslFilter)
}
}

How can I define two different 'distribution' tasks in gradle?

The normal behavior of the distTar and distZip tasks from the application plugin in gradle seems to be to copy the contents of src/dist into the zip and tar files, but I have a subfolder in src/dist that I want to exclude from the default distribution, and include it for a new (extended) task, possibly to be called distZipWithJRE.
I have been able to exclude this folder in the default task as follows:
distributions.main {
contents {
from('build/config/main') {
into('config')
}
from('../src/dist') {
exclude('jre')
}
}
}
How can I define a second task that behaves just like the original (unmodified) task?
Using Gradle 4.8 I had to tweak the answer to use 'with' from CopySpec instead
distributions {
zipWithJRE {
baseName = 'zipWithJRE'
contents {
with distributions.main.contents
}
}
}
It seems that what you're looking for is in the docs. You need to leave current settings as is and for zipWithJRE create and configure custom distribution:
distributions {
zipWithJRE {
baseName = 'zipWithJRE'
contents {
from { distributions.main.contents }
}
}
}

Resources