Gradle replacing Maven assembly plugin - maven

I'm fairly new to Gradle, and trying to port an existing Maven pom.xml that makes extensive use of maven-assembly-plugin to create various zip files.
In the example below, I'm getting files from various subdirectories (with particular extensions), and then mapping them in a flat structure to a ZIP file.
task batchZip(type: Zip) {
from fileTree('src/main/sas') {
include('**/*.sas')
include('**/*.ds')
}.files
}
This puts all the files in the root of the zip. What I ideally need though, is for the files to live under a particular path in the root of the zip, e.g. /shared/sas.
Is there a way to do this without first copying all the files to a local directory and then zipping that up?

task batchZip(type: Zip) {
into('shared/sas') {
from { fileTree('src/main/sas').files }
include('**/*.sas')
include('**/*.ds')
}
}

Have a look at the docs. It seems that if You specify appropriate into You'll get the result You're looking for.

Related

zip a folder from resources using gradle

I want to make a gradle task to zip a subdirectory called pack from my resources folder, I am not very familiar with gradle, so sorry if this seems like something easy, so far I have this:
task genResourcePack(type: Zip) {
from sourceSets.main.resources
include '**/*'
archiveName 'pack.zip'
}
this zips my entire resources folder, which I do not want, I also tried doing this as well:
task genResourcePack(type: Zip) {
from sourceSets.main.resources.include('pack/')
include '**/*'
archiveName 'pack.zip'
}
which is a little better, but then the zip has a folder called pack at the top, and I want to flatten this folder, but not all the way, basically I want the from to target the subdirectory of pack directly.
I actually just found a solution to my problem, but it isn't particularly elegant so I'll keep this open in case someone has a better way. I replaced my from with the following line:
from sourceSets.main.resources.getSrcDirs()[0].toPath().resolve('pack')

Gradle: Include dynamically generated file in build?

During my gradle build, I generate a temporary buildinfo.properties file containing things like Git commit info, build time, etc. I would like to include this file in my output *.jar / *.war files as a resource. However, I do not want to put this file in my project src/ folder (this would require fiddling with .gitignore and in general it just seems unnecessary to me). Ideally, the developer shouldn't even see this file at all, it should just be contained in the output archive.
How would you include a dynamically generated text file in a Gradle build?
Add that file in a jar task (Kotin DSL):
tasks {
val jar by getting(Jar::class) {
from("build/buildinfo.properties")
}
}
It will add build/buildinfo.properties file (assuming you generate it there with another taks) to the root of your JAR.
For dynamically generated file, standard gradle way to process resources is the gradle task called processResources. You can do something like this:
processResources {
dependsOn taskThatGeneratesYourBuildinfo
from("build/buildinfo.properties") {
into("desired/path/in/jar")
}
}

Exclude base directory inside Gradle tar/zip artifacts

The maven assembly plugin has an includeBaseDirectory option that (when set to false) avoids having a single top-level directory inside the tar/zip artifact with the same name as the artifact itself.
I'd like to achieve the same result with Gradle, but I don't see how. I'm using a configuration like this:
task distTar(type: Tar) {
compression Compression.GZIP
extension "tar.gz"
}
I don't see any options for the Tar task that do what I want. How can I exclude the base directory in my archive with Gradle?
By reconfiguring the distribution plugin (which gets implicitly applied by the application plugin) you can simply do (in Kotlin DSL):
distributions {
main {
contents {
into("/")
}
}
}
This affects the output in both Tar and Zip formats.
(Disclaimer: This answer is loosely based on this Gradle forum post).
Ok, I figured it out. It was simpler than I thought. To copy the library dependencies into lib at the root of the archive, I use a CopySpec:
task distTar(type: Tar) {
into('lib') {
from libsDir
include '*.jar'
}
}
Similar CopySpecs can be used to copy e.g. bin and conf directories.

How to make Gradle copy source directories in certain order?

I need resources from "myOtherResourcesDir" to be copied to output directory before "src/test/resources".
It looks like FileCollection does not obey the order:
sourceSets.test.resources.srcDirs 'myOtherResourcesDir', 'src/test/resources'
UPDATE:
Can I configure processTestResources task to skip existing files?
I ended up configuring processTestResources task with two "from". Files from 'src/test/resources' are copied last, so that they overwrite files from myOtherResourcesDir.
processTestResources {
from 'myOtherResourcesDir'
from 'src/test/resources'
}
Can you elaborate a bit what you're trying to achieve?
the files are copied in the processTestResourcestask. At the moment there is no way to specify the order when copying multiple directories
I assume the reason you need the ordering is, that a file in src/test/ressources overwrites a file copied from myOtherResourcesDir?. One option is to exclude that file specific file from 'myOtherResourcesDir' programmatically using the eachFile hook
processTestResources{
eachFile{fileDetails ->
if(fileDetails.file.absolutePath.contains("myOtherResourcesDir/fileToExclude.properties")){
fileDetails.exclude()
}
}
}

Copying Files From One Zip File Into Another In Gradle

We are working on migrating to Gradle from Maven. Unfortunately we still have a couple of War overlays to deal with.
As a work-around I am trying to copy the contents of one war file into another.
This is what I have so far:
task overlayWars (dependsOn: war) << {
// Get the source war files to copy the contents from...
def dependencyWars = configurations.runtime.filter { it.name.endsWith ('.war') }
dependencyWars.each { dependentWar ->
// Get the products, ie the target war file...
war.outputs.files.each { product ->
println "Copying $dependentWar contents into $product"
copy {
from { zipTree (dependentWar) }
into { zipTree (product)} // this seems to be the problem
include 'WEB-INF/classes/**/*.class'
include 'WEB-INF/jsp/**/*.jsp'
}
}
}
}
When into { zipTree (product)} is a file (like file ('tmp/whatever')) this works fine. When specifying another zip file (the target war file) it fails with the error:
Converting class
org.gradle.api.internal.file.collections.FileTreeAdapter to File using
toString() method has been deprecated and is scheduled to be removed
in Gradle 2.0. Please use java.io.File, java.lang.String,
java.net.URL, or java.net.URI instead.
If anyone has suggestions on this specifically, or a better way to "overlay" war files, I'd really appreciate it!
After chasing down a couple of different angles, I ended up with this:
war {
configurations.runtime.filter { it.name.endsWith ('.war') }.each {
from zipTree (it).matching {
include 'WEB-INF/classes/**/*.class'
include 'WEB-INF/jsp/**/*.jsp'
include 'images/**'
}
}
}
Basically I am just including filtered contents of any .war dependencies in the product. Being an alteration to the standard war task, the dependency tree is kept clean. It seems to work for us so far...
In case you are trying to merge Wars here, you can't do that with a Copy task/method. You'll have to use a Zip task (there is no equivalent method). In case you want to merge into an existing War, the way to do this is existingWar.from { zipTree(otherWar) }.

Resources