how to exclude path information in gradle zip task - gradle

Apologies in advance for this simple question I am relatively new to Gradle.
I would like to run a Zip task during my Build process and create a .zip file in my "archive" directory but without the source file's directory structure. I managed to get the task working but its retaining the directory structure. I read that for linux Zip there is the option -j or -r which flattens the directory but I am not sure if this is available to me via the Gradle task.
My input file structures looks similar to the below,
./libs/
./libs/file1.jar
./scripts/script1.sh
./scripts/script2.sh
but I would like to end up with a Zip file with directory structure as follows,
./
./file1.jar
./script1.sh
./script2.sh
My current Zip task is as follows,
task makeZipForDeploy(type: Zip) {
from 'build/'
include 'libs/*' //to include all files in libs folder
include 'scripts/*' //to include all files in the scripts folder
archiveName("${archiveFileName}")
destinationDir file("${archivePath}")
}

the solution was even more trivial than I thought. The below will flatten the structure
task makeZipForDeploy(type: Zip) {
from 'build/libs' //to include all files in libs folder
from 'build/scripts' //to include all files in the scripts folder
archiveName("${archiveFileName}")
destinationDir file("${archivePath}")
}

Related

Gradle copies all the files if at least one is not up-to-date

For instance, I've got the following task:
task testCopy(type: Copy) {
from ("folder/copy_from")
into ("folder/copy_to")
eachFile {println it.name}
}
Unless the inner files of the folder copy_from are touched, task works fine. As soon as I change, let's say one file in the folder copy_from, then Gradle begins to copy all the files from copy_from folder into copy_to instead of copying only one changed/added file.
Is this behaviour expected? Is there a way to make Gradle copy only changed/added file?
Yes based on this github issue and gradle discuss:
The build is incremental in the sense that the copy task only executes
when things have changed but it isn’t incremental itself, in that it
only copies inputs that have been modified.
I couldn't find a propper solution, but one solution is just splitting your task into smaller ones with specific types.
task copy1(type: Copy) {
into 'build/out'
from ('src') {
include 'docs/*.txt'
}
eachFile {println it.name}
}
task copy2(type: Copy) {
into 'build/out'
from ('src') {
include 'docs/*.md'
}
eachFile {println it.name}
}
task copy3 {
dependsOn copy1, copy2
}
It's not exactly what you want but it improves the performance by reducing files to copy.
when you change a text file and run gradle copy3 it just copies the text files not md files.
UPDATE:
Ant copy task doesn't have this problem
from it's documentation:
By default, files are only copied if the source file is newer than the destination file, or when the destination file does not exist. However, you can explicitly overwrite files with the overwrite attribute
So you can use ant copy task instead, as we can use ant tasks from gradle:
task copyFromAnt {
doLast {
ant.copy(todir: 'build/out') {
fileset(dir: 'src')
}
}
}
ant logs the files it copies so you can check the log with help of gradle -d and grep:
gradle copyFromAnt -d | grep "\[ant:copy\]"
and to see just the files it copies with out up-to-dat and etc. you can use the below command:
gradle copyFromAnt -d | grep "\[ant:copy\] Copying"

Copy latest folder Gradle

I am trying to copy the most lastet folder from insde a folder using gradle but I the script is sorting all the folders and copying the files inside the latest folder.
Below is the script.
task test(type: Copy) {
from(new Source("D:\\test").listFiles().sort{ it.lastModified() }.last())
into(new Source("D:\\folder\\output"))
}
What I got inside test directory is
test
└──folder1
| test1.txt
└──folder2
| test2.txt
If say folder2 in the test directory is the latest one tha I am getting the output as
test2.txt
But I am expecting the output as
folder2
└─ test2.txt
and the content inside it.
Can anyone please help?
This should work:
task testCopy(type: Copy) {
def latestDirName = file("test").listFiles().sort{ it.lastModified() }.last().name
from file("test") , {
include "$latestDirName/"
}
into(file("folder/output"))
}
Explanation
In your current task implementation, you have written:
from(new Source("D:\\test").listFiles().sort{ it.lastModified() }.last())
Which is equivalent to (assuming folder folder1 is the most recent):
from(new Source("D:\\test\\folder1"))
Gradle will use d:/test/folder1 as source folder for the copy: the content of this folder (but not the folder itself) will be copied to the destination directory.

include single directory in an archive with gradle Zip task

I have a directory A under my project's rootDir. Directory A has subidrectories B,C,D,E,etc.
I want to create archive of only B and ignore others. I have written a gradle task to zip the directory B.
task ZipOnlyB(type: Zip){
archiveName = "ArchiveOfB.zip"
destinationDir = file ("${rootDir}/toSendToArtifactory")
from "${rootDir}/A/B"
}
The above code works and creates an archive with name ArchiveOfB.zip. But this archive doesn't contain the directory B. The archive only contains the contents of directory B.
Expected content of zip file : A/B/contents-of-directory-B
Actual content of zip file : A/contents-of-directory-B
How do I go about getting the expected result. Any guidance in this regard is highly apprecited. i have looked up the "Working with fiels" section of Gradle documnetaion,but that doesn't help my cause. I was expecting some "include" property for including diretcories, but the include works only with files and no directory example was given.
You can use into method (see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Zip.html#org.gradle.api.tasks.bundling.Zip:into(java.lang.Object) ) to specify the destination directory inside the archive
In you case you could do something like:
task ZipOnlyB(type: Zip){
archiveName = "ArchiveOfB.zip"
destinationDir = file ("${rootDir}/toSendToArtifactory")
from fileTree('A/B')
into ('A/B')
}
This will create the archive with first level directory "A" containing the "B" directory and its content. If you don't want this root directory "A" but just directory "B", then use into ('B')

Intelligent up-to-date-check for a gradle task unzipping a file

My goal is to create a gradle task which fulfills the following requirements:
unzip a file into a directory
run as infrequent as possible (good up-to-date-check)
should detect if something has changed in the unzipped directory
The initial thought was to use a task like that:
p.task("unzip", type: Copy) {
def zipFile = p.file('some-zip-file.zip')
def outputDir = p.file("$p.buildDir/unpacked")
from p.zipTree(zipFile)
into outputDir
}
If I create a file "test.txt" within $p.buildDir/unpacked and I rerun the unzip task, the file "test.txt" remains within the unpacked directory. The unzip task effectively performs obviously something similar to a "merge". Unfortunately that is not optimal since the content of /unpacked should be defined as the unzipped zip file.
The following solution unfortunately doesn't detect that the output directory "unpacked" has changed since the last execution of the task:
p.task("deleteUnzippedDirectory", type: Delete) {
delete "$p.buildDir/unpacked"
inputs.file p.file('some-zip-file.zip')
outputs.dir p.file("$p.buildDir/unpacked")
}
p.task("unzip", type: Copy) {
def zipFile = p.file('some-zip-file.zip')
def outputDir = p.file("$p.buildDir/unpacked")
from p.zipTree(zipFile)
into outputDir
dependsOn p.deleteUnzippedDirectory
}
Is there a way to achieve the desired result besides running "deleteUnzippedDirectory" every time? (outputs.upToDateWhen {false})

Rename files in assemble task in gradle

I need to write a simple task to create a zip from the source code. I need to include a dir called 1-dir or 2-dir depending on a system property. But the name of the directory in the resulting zip should always be dir. So basically, I want to include a dir in a zip (conditionally) and rename it.
I tried the rename method but that does not work.
Any pointers?
It will be:
task zipDir(type: Zip) {
def fromDir = project.hasProperty('from') ? project.from : 'dir1'
from(fromDir)
into('dir')
}
It can be run in the following way gradle zipDir -Pfrom=dir2. If no from property is passed dir1 will be zipped.
If you need system property instead of gradle property, pass -Dfrom=dir2 and use System.properties['from'] instead of project.from.

Resources