How to copy files from some source path with gradle script? - gradle

I am trying to copy images for javadocs with gradle. Currenly images are located under
MYPROJECT/src/main/resources/doc-files/images/
I refer these images with something like this
<img src="{#docRoot}/doc-files/images/myimage.jpg">
Now I wish to copy all content from under MYPROJECT/src/main/resources/doc-files/ into MYPROJECT/build/docs/javadoc/doc-files/ and I write in build.gradle:
javadoc << {
FileTree docFilesTree = fileTree(dir: 'src/main/resources/doc-files')
copy {
from docFilesTree
into destinationDir
}
}
This has two problems:
1) It does nothing :)
2) It refers resources/doc-files/images/ explicitly, while I would like to deduce it from parameters. I failed to know how to use something from here: https://docs.gradle.org/current/userguide/java_plugin.html

I'm not exactly sure what you mean by you want to deduce resources/doc-files/images from its parameters.
However, if you want to copy files from one directory to another, you can create a task such as:
FileTree docFilesTree = fileTree(dir: 'src/main/resources/doc-files')
task copyJavaDocSupportFiles(type: Copy) {
from docFilesTree
into 'build/docs/javadoc/doc-files/'
}
You can then add this dependency to a javadoc task such as:
task generateJavadocs(type: Javadoc, dependsOn: ['copyJavaDocSupportFiles']) {
source = sourceSets.main.allJava
}
When you run the generateJavadocs task, it will copy the files from src/main/resources/doc-files to build/docs/javadoc/doc-files

Related

In the settings.gradle file how can i dynamically include all the subprojects?

As settings.gradle file runs on groovy is it possible to write a script which will include all the subprojects which contains for example build.gradle files inside it.
I tried using this
new File('.').eachFileRecurse {
if (it.name.endsWith("build.gradle")) {
//include it
println "Processing file ${it}"
}
}
but can't figure out how it will work. I mean how will i include all my subprojects
I don't want to hardcode include 'x', include 'y' in the settings.gradle file
You can call include with the parent of the locations where the
build.gradle files are found. Be careful to not include things
multiple times or the root itself by the net you are casting.
E.g.
new File('.').eachFileRecurse {
if (it.name == "build.gradle" /* && ... more checks */)) {
println "Included directory ${it.name} due to ${it}"
include it.parent
}
}

Run a groovy class file without main method using gradle task

I have a class file which does not have a main method. I need to run the class file only when needed with the help of a gradle task. Can someone help me with writing a gradle task for it?
I'd guess it'd be something like
buildscript {
// add your library to the buildscript classpath
classpath 'foo.bar:mygroovylib:1.0'
}
task runMyGroovy {
// let's assume your service accepts an input file and writes to an output directory
File inFile = file('path/to/some/file.xml')
File outDir = file("$buildDir/myGroovy")
// set task inputs/outputs to benefit from gradle's up-to-date checks
inputs.file inFile
outputs.dir outDir
doLast {
// actually do stuff in gradle's execution phase
def myObject = new MyGroovyObject();
myObject.doSomethingFantastic(inFile, outDir)
}
}

How can I iterate over CopySpec in gradle, or even get the destination pathname of a file from the copyspec

I have a Zip task which uses the CopySpec like DSL.Like:-
task1 {
from(src/main/pig).exclude(<some file pattern>) {
into "pigscripts"
}
}
What I want to do is iterate over the pig scripts, as in if copySpec is the CopySpec object associated with it,
Map<String,String map> = new HashMap<String,String>()
copySpec.eachfile {
map.put(it.originalpath,it.destinationpath)
}
However in this gradle discussion forum https://discuss.gradle.org/t/iterate-over-a-copyspesc/13030/6 it seems this is not straight forward.
It will also suffice if I can get the destination path of a single file since I can get a FileTree of all the source files as
FileTree filetree = (copySpec as CopySpecInternal).buildRootResolver().allSource
then i would like to do something like
filetree.each{
//map.put(it,copySpec.findDestinationPath(it))
}

Gradle copy and filter task not executed

We are filtering an xml file replacing some tokens with gradle properties.
But the filtering (i.e. copy task) is not executed when we just change the properties in our build.gradle file.
How should we modify our script so that the filtering is performed each time or at least when the template and/or the build.gradle has been modified.
This we have:
war.doFirst {
delete 'src/main/webapp/WEB-INF/appengine-web.xml'
copy {
from 'build.gradle'
from 'src/main/webapp/WEB-INF/'
into 'src/main/webapp/WEB-INF/'
include '*-template.*'
rename { String fileName ->
fileName.replace('-template', '')
}
expand(gaeApp: "$gaeApp", gaeAppVersion: "$gaeAppVersion")
}
}
I just ran some test where the filtering worked. I am confused... I am sure that it sometimes does not!
So after good input from Vampire we tried this
war {
inputs.file "build.gradle"
exclude 'src/main/webapp/WEB-INF/appengine-web.xml'
// filesMatching('src/main/webapp/WEB-INF/**/*-template.*') {
filesMatching('**/*-template.*') {
println "WAR template: $it"
rename { it.replace '-template', '' }
expand gaeApp: gaeApp, gaeAppVersion: gaeAppVersion
}
}
A dollar and a dime to anyone who can explain why the filesMatching('src/main/webapp/WEB-INF/**/*-template.*')does not work!
BUT the biggest problem is that even if the filesMatching locates the template file the appengine-web.xml that is placed inside the WAR is not a processed version of appengine-web-template.xml.
You need to add those properties to the inputs of the task like
war.inputs.property 'gaeApp', gaeApp
war.inputs.property 'gaeAppVersion', gaeAppVersion
so that gradle knows the input changed, otherwise it cannot know when the input is different.
But besides that, you should not (need not) use a copy { } block in there.
The war task itself is an implicit copy spec, so you should be able just doing something like
war {
inputs.property 'gaeApp', gaeApp
inputs.property 'gaeAppVersion', gaeAppVersion
exclude 'src/main/webapp/WEB-INF/appengine-web.xml'
filesMatching('src/main/webapp/WEB-INF/**/*-template.*') {
rename { it.replace '-template', '' }
expand gaeApp: gaeApp, gaeAppVersion: gaeAppVersion
}
}
This is what worked for us in the end.
We moved the template to 'src/template/webapp' and removed the "-template" suffix,
war {
inputs.file "build.gradle"
with copySpec {
from 'src/template/webapp'
expand gaeApp: gaeApp, gaeAppVersion: gaeAppVersion
}
}
Our problem with Vampire's solution must be related to the fact that the template file was in same directory as the file it was to replace.

gradle tar include nested files at top level

In gradle (1.9), I have multiple subprojects. Each one uses the application plugin to create a tar and cli. I am trying to get all these tars into a unified tar, but I am having a lot of trouble.
Here is the tar format I am looking for:
${project.name}/${subproject.name}.tar
I have tried using both the Tar task and the distribution plugin, but for each one, I am not able to find a clean way to just get the generated tars (or any tar), and put them at top level, excluding everything else.
Here is a sample using the distirbution pluging, but its not giving the output I like
apply plugin: 'distribution'
distributions {
testing {
contents {
from(".")
exclude "*src*"
exclude "*idea*"
exclude "*.jar"
exclude ".MF"
filesMatching("**/build/distributions/*.tar") {
if(file.name == "${project.name}-testing.tar") {
exclude()
} else {
name file.name
}
}
}
}
}
Here is what I would like (but not working):
apply plugin: 'distribution'
distributions {
testing {
contents {
include "**/*.tar" // shows up at top level
}
}
}
EDIT:
Getting closer.
distributions {
testing {
contents {
from subprojects.buildDir
includeEmptyDirs false
include "**/*.tar"
exclude "**/${project.name}-testing.tar"
}
}
}
This will give me ${project.name}/distribution/${subproject.name}.tar
Here is the solution for your problem. Put the following to the root project:
task distTar(type: Tar) {
destinationDir = new File("$buildDir/distributions")
baseName = 'unifiedTar'
}
subprojects {
// definitions common to subprojects...
afterEvaluate {
def distTar = tasks.findByName('distTar')
if(distTar) {
rootProject.distTar.dependsOn distTar
rootProject.distTar.inputs.file distTar.archivePath
rootProject.distTar.from distTar.archivePath
}
}
}
then invoke "build distTar" on the root project - it will assemble "unifiedTar.tar" in "build/distributions" subfolder (of the root project).
How it works:
"task distTar(...)" declares a new task of type Tar in the root project.
"subprojects" applies the specified closure to each subproject.
"afterEvaluate" ensures that the specified closure is called AFTER the current project (in this case subproject) is evaluated. This is very important, because we are going to use properties of the subproject which are defined only after it's evaluation.
"tasks.findByName" allows us to determine, whether the given task is defined for given project. If not, it returns null and the following code is not performed. This way we stay agnostic regarding the nature of the subproject.
"dependsOn" ensures that distTar of the root project depends on distTar of the given project (and, therefore, is executed later than it).
"inputs.file" ensures that distTar on root project is not executed, if none of the constituent tars has changed.
"from" adds constituent tar to unified tar.

Resources