I am migrating ant based project to gradle project. I have to use a set of files or pattern in many tasks which makes me write duplicate code while it can be simply kept in resources and patternset tags in ant. Is there any simpler way like equivalent to resources or patternset in gradle.
<patternset id="pattern.files.to.instrument">
<include name="lib/cat*.jar"/>
<include name="lib/extensions/cat*.jar"/>
<include name="lib/cas*.jar"/>
<include name="bld/internal-lib/cat*.jar"/>
<exclude name="**/*test.jar"/>
<exclude name="**/*.war"/>
</patternset>
<fileset id="fileset.instrument" dir="${uninstrumented.jars.folder}">
<patternset refid="pattern.files.to.instrument"/>
</fileset>
I'm not familiar with Ant, but my first thought on a similar concept in Gradle is a FileTree (or a ConfigurableFileTree). You may configure a FileTree once and (since it implements FileCollection) refer to it everywhere where you want to use the files matching the patterns you specified:
def filesToInstrument = fileTree(projectDir) {
include 'lib/cat*.jar'
include 'lib/extensions/cat*.jar'
include 'lib/cas*.jar'
include 'bld/internal-lib/cat*.jar'
exclude '**/*test.jar'
exclude '**/*.war'
}
task copyFilesToInstrument(type: Copy) {
from filesToInstrument
into 'my/destination/path'
}
However, as far as I know, FileTree elements are always bound to a root directory, so if you just want to reuse include/exclude patterns, you may take a look at CopySpec. Elements of type CopySpec may be reused using the method with on tasks that implement CopySpec theirselves (e.g. Copy, Zip, Jar ...):
def filesToInstrumentPattern = copySpec {
include 'lib/cat*.jar'
include 'lib/extensions/cat*.jar'
include 'lib/cas*.jar'
include 'bld/internal-lib/cat*.jar'
exclude '**/*test.jar'
exclude '**/*.war'
}
task zipFilesToInstrument(type: Zip) {
from fileTree('src')
with filesToInstrumentPattern
}
Related
I am working on moving an ant project to gradle project. I have a set of file collection where to be used in as input for several tasks. This is possible in ant with .
<zipfileset id="zipfileset1" src="C:/reporter/servlet/reporter.war">
<include name="WEB-INF/classes/**/*.class"/>
<exclude name="WEB-INF/classes/**/*_jsp*.class"/>
</zipfileset>
<fileset id="fileset1" dir="C:/lib">
<include name="test*.jar"/>
</fileset>
<union id="resources.reports.lib">
<fileset refid="fileset1"/>
<fileset id="fileset2" dir="C:/adaptors/lib">
<include name="com*.jar"/>
</fileset>
<zipfileset refid="zipfileset1"/>
</union>
Is there any method in gradle equivalent to "union" in ant.
There is a working example here
Note that Gradle has tight integration with Ant (see here) so one option is a straight migration from the Ant code. For example:
// NOTE: this uses local dirs instead of Windows paths (e.g. C:\lib)
ant.zipfileset(id:"zipfileset1", src:"c_reporter/servlet/reporter.war") {
include(name:"WEB-INF/classes/**/*.class")
exclude(name:"WEB-INF/classes/**/*_jsp*.class")
}
ant.fileset(id:"fileset1", dir:"c_lib") {
include(name:"test*.jar")
}
ant.union(id:"resources.reports.lib") {
fileset(refid:"fileset1")
fileset(id:"fileset2", dir:"c_adaptors/lib") {
include(name:"com*.jar")
}
zipfileset(refid:"zipfileset1")
}
Per comment, an alternative -- and more Gradle-esque approach -- is: (also illustrated in the link above)
project.ext.zipFiles1 =
zipTree("${projectDir}/c_reporter/servlet/reporter.war").matching {
include 'WEB-INF/classes/**/*.class'
exclude 'WEB-INF/classes/**/*_jsp.class'
}
project.ext.files1 =
fileTree("${projectDir}/c_lib").matching {
include 'test*.jar'
}
project.ext.files2 =
fileTree("${projectDir}/c_adaptors/lib").matching {
include 'com*.jar'
}
project.ext.allFiles =
project.ext.zipFiles1.plus(project.ext.files1)
.plus(project.ext.files2)
Net: 'junitreport' doesn't seem to provide a way to set the temporary folder that it uses while performing transformations, and the doesn't seem to be a way to update 'java.io.tmpdir' for the reporting task. In this case, setting 'user.home' or 'java.io.tmpdir' from the command line while invoking ant is not a solution which can be used.
In detail: I'm using junit tasks within ant/mantis, with this syntax:
<target name="unittest_report">
<sequential>
<echo>User Home [ user.home ] [ ${user.home} ]</echo>
<echo>Java Temp [ java.io.tmpdir ] [ ${java.io.tmpdir} ]</echo>
<junitreport todir="${dir.unittest.reports}/raw">
<fileset dir="${dir.unittest.reports}/raw">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${dir.unittest.reports}"/>
</junitreport>
</sequential>
</mantis:modifyenvironment>
This seems to be a very standard usage, with the addition of the "echo" statements to show system property values which are active when the task is executed.
The task runs fine, except that the processing writes temporary output relative to the java temporary directory (java.io.tmpdir):
[15:55:03+0000/tester/unittest_report/echo] User Home [ user.home ] [ C:\Users\MyUser ]
[15:55:03+0000/tester/unittest_report/echo] Java Temp [ java.io.tmpdir ] [C:\Users\MyUser\AppData\Local\Temp\ ]
[15:55:04+0000/tester/unittest_report/junitreport] Processing c:\work\tester\build\reports\unittest\raw\TESTS-TestSuites.xml to
C:\Users\MyUser\AppData\Local\Temp\null591799606
The key values are the "java.io.tmpdir" value and the write to "C:\Users\MyUser\AppData\Local\Temp\null591799606".
I've tried to temporary update the temporary directory using "sysproperty", for example:
<mantis:modifyenvironment>
<sysproperty key="java.io.tmpdir" value="${dir.build}/junit.report.tmp"/>
<sequential>
<echo>User Home [ user.home ] [ ${user.home} ]</echo>
<echo>Java Temp [ java.io.tmpdir ] [ ${java.io.tmpdir} ]</echo>
<junitreport todir="${dir.unittest.reports}/raw">
<fileset dir="${dir.unittest.reports}/raw">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${dir.unittest.reports}"/>
</junitreport>
</sequential>
</mantis:modifyenvironment>
But, that has no effect.
Then:
1) Is this correct expectation of "sysproperty" to update the system property for the "junitreport" task? For example, the effect of "sysproperty" might be limited to nested "java" sequential task invocations, in which case the expectation that the update be visible to "junitreport" would be incorrect.
2) Or, is there a limitation for "java.io.tmpdir" in particular which prevents this from working?
3) Or, is there a bug in "sysproperty"?
For this problem, I'm prevented from updating "java.io.tmpdir" (or "user.home") from the command line. Those values cannot be modified in a wider scope than the "junitreport" task invocations.
Finally: Not sure if it fits under this same set of questions:
4) Where is the documentation for "mantis:modifyenvironment"? I find this in my local "mantis.jar", but I am finding no documentation for it in the mantis manual / documentation.
5) That "junitreport" modifies the file system through "java.io.tmpdir" with no possible override seems to be very bad practice.
About questions 1-3 about sysproperty I can tell you that the only place it may be used is before executing a new JVM: I.E. within java and similar tasks, like junit. (You can read it in the respective documentations).
So, I have this setup in ant:
<target name="context">
<echo>docbase: ${docbase.dir}</echo>
<antcall target="_context.docbase"/>
<antcall target="_context.nodocbase"/>
</target>
<target name="_context.docbase" if="${docbase.dir}">
<echo>Context with docbase</echo>
<context.md docbase="..."/>
</target>
<target name="_context.nodocbase" unless="${docbase.dir}">
<echo>Context without docbase</echo>
<context.md/>
</target>
And when docbase.dir is set to true or false things work as you'd expect. But when docbase.dir is set to an actual value (e.g., /tmp/docbase) for some reason it hits the _context.nodocbase target instead of the expected _context.docbase target.
Reading the docs it implies that if the expanded property isn't one of the "truthy" for "falsey" constants then it will just interpret it as before, but this isn't what I'm seeing.
What am I doing wrong? Should I use a different approach?
Note: I'm using Ant 1.8.2 (and conditional parameter expansion started in 1.8.0).
As mentioned here: http://ant.apache.org/manual/properties.html
As of Ant 1.8.0, you may instead use property expansion; a value of true (or on or yes) will enable the item, while false (or off or no) will disable it. Other values are still assumed to be property names and so the item is enabled only if the named property is defined.
This is some really subtle information here. So what's going on in your code is ${docbase.dir} is expanded to "/tmp/docbase". That's not true/on/yes/false/off/no so Ant then looks for a property named "/tmp/docbase". It can't find it, so it runs the unless.
Here's an example that I hope will clarify things. This will run only the if target:
<project name="MyProject" default="context" basedir=".">
<target name="context">
<echo>docbase: ${docbase.dir}</echo>
<property name="/tmp/docbase" value="i exist!"/>
<antcall target="_context.docbase"/>
<antcall target="_context.nodocbase"/>
</target>
<target name="_context.docbase" if="${docbase.dir}">
<echo>Context with docbase</echo>
</target>
<target name="_context.nodocbase" unless="${docbase.dir}">
<echo>Context without docbase</echo>
</target>
</project>
The important thing here is this line:
<property name="/tmp/docbase" value="i exist!"/>
Because that property is defined, it will run the if and not the unless.
I have a java project and an ANT script to build and then distribute the project to other projects with a simple copy command.
I would like to only name the place where to copy to files to once in the header of the ant script, and not have an explicit copy-task for every project that is dependent on this project.
I can't find anything like arrays in ANT, so what would be the cleanest way of distributing something to multiple directories?
According to what I commented under Martin's answer, I'd like to post my version of solution as another choice. And I am using property names from Martin's answer to make it clear.
<target name="deploy" >
<property name="dest.dirs" value="/dir/one,/dir/two,/dir/thr/ee" />
<for list="${dest.dirs}" param="dest.dir" parallel="true" delimiter="," >
<sequential>
<copy todir="#{dest.dir}" >
<fileset dir="${srd.dir}" />
</copy>
</sequential>
</for>
</target>
Please note that "for" is an Ant-Contrib task, and it's using Macrodef in the back so you should use #{} to refer to "dest.dir"; the "dest.dirs" will be splited into a list (maybe String[]) by delimiter. Here we use comma to split it (and the default value to delimiter is comma). I also added "parallel" to make it copy files to all the "dest.dirs" at same time, however, if the project to copy is large, you should delete "parallel".
Please check http://ant-contrib.sourceforge.net/tasks/tasks/for.html
and http://ant-contrib.sourceforge.net/tasks/tasks/foreach.html for more information.
I don't believe you have many viable options: the copy task accepts only a single directory.
Create your own copy task that takes a list of directories.
Exec a script/program that does the copying.
Have the subprojects do a pull.
I'm really hesitant about having a project push to other projects, because that makes the assumption that those projects will work with the newly-pushed code. IMO the "sub-"projects should be making the decision if they want the new version or not.
To me this sounds more like a dependency management issue, better handled with Ivy/Maven/Gradle (or other Maven-alike).
All that said, it sounds like you'd want to do option 1, create a custom Ant task that accepts a list of destination directories; it might be pretty easy to just extend the existing copy task to get all its functionality--just add a "todirs" property.
You might consider using a scriptmapper in your copy task with enablemultiplemappings true.
First, list the target directories in a property and create a filelist from it. (You could use a dirset, but the API for filelist is simpler.) Then run the copy, with the scriptmapper setting up the multiple destinations.
<property name="dest.dirs" value="/dir/one,/dir/two,/dir/thr/ee" />
<filelist id="dests" dir="/" files="${dest.dirs}" />
<copy todir="/" enablemultiplemappings="yes">
<fileset dir="${srd.dir}" />
<scriptmapper language="javascript">
<![CDATA[
// Obtain a reference to the filelist
var filelist = project.getReference( "dests" );
var dests = filelist.getFiles( project );
for ( var i = 0; i < dests.length; i++ )
{
self.addMappedName( dests[i] + "/" + source );
}
]]>
</scriptmapper>
</copy>
I use the Ant API for creating tasks programmatically, but I have not yet found the class that create JUnit report task.
in short, I want the equivalent of the code below using the Ant API:
<junitreport todir="..">
<fileset dir="..">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir=".." />
</junitreport>
Thanks for your help.
All task definitions are declared in ant.jar!org\apache\tools\ant\taskdefs\defaults.properties
Here is the JUnit-related ones:
junit=org.apache.tools.ant.taskdefs.optional.junit.JUnitTask
junitreport=org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator
Here is corresponding Java code may look something like this:
FileSet fs = new FileSet();
fs.setDir(new File(".."));
fs.createInclude().setName("TEST-*.xml");
XMLResultAggregator aggregator = new XMLResultAggregator();
aggregator.addFileSet(fs);
AggregateTransformer transformer = aggregator.createReport();
transformer.setFormat(Format.FRAMES);
transformer.setTodir(new File("..");