build.xml to set date and time as file name - ant

I want to set file name with date and time attached to it so I want to create file named as behat-20140913-195915.html however the example below sets the name as behat-yyyymmdd-hhiiss.html. Anyone know the solution to problem?
I followed this example
Note: These two don't work too: ${DSTAMP} ${TSTAMP}
<?xml version="1.0" encoding="UTF-8"?>
<project name="Sport" default="build-default" basedir=".">
<tstamp>
<format property="TODAY_MY" pattern="yyyymmdd-hhiiss" locale="en,UK" />
</tstamp>
<target name="build" description="Runs everything in order ..." depends="behat-bdd" />
<target name="behat">
<echo msg="Running Behat tests ..." />
<exec logoutput="true" checkreturn="true"
command="bin/behat -f progress --format html --out ${dir-report}/behat-${TODAY_MY}.html" dir="./" />
</target>
</project>

The tstamp task is documented in the ANT manual. It describes how the pattern format comes from the SimpleDateFormat object:
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
I suggest trying the following:
Example
Buildfile: build.xml
build:
[echo] date: 20140913-203419
build.xml
<project name="demo" default="build">
<tstamp>
<format property="TODAY_MY" pattern="yyyyMMdd-HHmmss" locale="en,UK" />
</tstamp>
<target name="build">
<echo message="date: ${TODAY_MY}"/>
</target>
</project>
Software versions
$ ant -v
Apache Ant(TM) version 1.9.4 compiled on April 29 2014
$ java -version
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

Related

Use pure Ant to search if list of files exists and take action based on condition

User passes a list of files in an XML file, below will be the sample:
<property-bundle name = "abc">
<action>clean</action>
<target-location>/vst/property/pog/</target-location>
<file-name>test1.props</file-name>
<file-name>test2.props</file-name>
<file-name>test3.props</file-name>
</property-bundle>
Now based on that action remove, I have to incorporate logic in build.xml to delete the files in the directory , but for that I want to perform a validation only if the file exists then remove or else throw the build failure error. I was able to read the values from the user input XML and takes those files into a file list property
<property name="file.list" value="test1.props,test2.props,test3.props"/>
<target name = "clean">
<delete>
<fileset dir="${target.location}" includes = "${file.list}"/>
</delete>
</target>
but with the clean target it only validates if the directory exists since it is fileset but does not do the validation if file exists , I read that filelist does validation for file exists but filelist can work with delete.
Since we are using Ant 1.6.5 in our environment I can not use antcontrib , It takes whole lot of process and approvals to upgrade Ant now , Can you please guide me on how it can be achieved with the pure Ant.
You should be able to just use delete's #failonerror attribute which throws an error if the file cannot be deleted.
<target name = "clean">
<delete failonerror="true">
<fileset dir="${target.location}" includes="${file.list}"/>
</delete>
</target>
The above will delete files and then error when it doesn't find a file, leaving you in a partially deleted state. If you want to avoid partial deletions, you can run another task to check first
<target name="failIfMissing">
<copy failonerror="true" todir="${temp.directory}">
<fileset dir="${target.location}" includes="${file.list}"/>
</copy>
</target>
by attempting to copy to a temporary directory, failing if some of the target files did not exist.
It is possible to loop over files with Ant-Contrib Tasks and then it will look something like this:
<target name="clean">
<foreach target="delete.if.exists" param="fileName">
<fileset dir="${target.location}" includes="${file.list}"/>
</foreach>
</target>
<target name="delete.if.exists">
<delete failonerror="true" file="$fileName"/>
</target>
Folks,
Thank you all for your outstanding help & contributions , I have finally achieved this with below
<target name="validate.file" depends="defineAntContribTasks,validate.dir">
<echo message=" The value of the filelist is ::::::::::::: ${file.list} :::::::::::::::::: "/>
<for param="file" list="${file.list}">
<sequential>
<if>
<available file="${target.location}/#{file}"/>
<then>
<echo message = "File::: #{file} ::::is valid , Found in :::${target.location}::: "/>
</then>
<else>
<fail message=" File::: #{file} ::::is not valid ,it is not found in :::${target.location}::: ,plesae recheck and submit again"/>
</else>
</if>
</sequential>
</for>
</target>
Thanks again for all of your valuable time and guidance.
<target name="removeUnwantedFiles" description="delete the build destination tree to ensure that it will contain ONLY what is explicitly needed for a build and ONLY what is intended to be release.">
<delete>
<fileset dir="${project-home}">
<includesfile name="${scripts}/excludeJavaFilesForV1.txt"/>
</fileset>
</delete>
</target>
This works for me.. hope this helps..
Ant is not a programming language and therefore has no native looping mechanism. In the absence of external plugins a trick that can used is an XSL transformation. Process the input XML file into a Ant script which implements the desired operation on each file.
Example
├── build.xml
├── files-process.xsl
├── files.xml <-- Input listed above
├── test1.props
├── test2.props
└── test3.props
Run the build and the files listed in "files.xml" are deleted:
build:
[delete] Deleting: /home/mark/tmp/test1.props
[delete] Deleting: /home/mark/tmp/test2.props
[delete] Deleting: /home/mark/tmp/test3.props
Run the build a second time and an error is generated:
BUILD FAILED
/home/mark/tmp/build.xml:6: The following error occurred while executing this line:
/home/mark/tmp/build-tmp.xml:4: file not found: test1.props
build.xml
Use the xslt task to generate a temporary Ant script containing the desired file deletion logic:
<project name="demo" default="process-files">
<target name="process-files">
<xslt style="files-process.xsl" in="files.xml" out="build-tmp.xml"/>
<ant antfile="build-tmp.xml"/>
</target>
<target name="clean">
<delete file="build-tmp.xml"/>
</target>
</project>
files-process.xsl
The following stylesheet generates an Ant script:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<project name="genbuild" default="build">
<target name="build">
<xsl:apply-templates select="property-bundle/file-name"/>
</target>
</project>
</xsl:template>
<xsl:template match="file-name">
<available file="{.}" property="{generate-id()}.exists"/>
<fail message="file not found: {.}" unless="{generate-id()}.exists"/>
<delete file="{.}" verbose="true"/>
</xsl:template>
</xsl:stylesheet>
build-tmp.xml
To aid readability I have formatted the generated Ant script:
<project name="genbuild" default="build">
<target name="build">
<available file="test1.props" property="N65547.exists"/>
<fail message="file not found: test1.props" unless="N65547.exists"/>
<delete file="test1.props" verbose="true"/>
<available file="test2.props" property="N65550.exists"/>
<fail message="file not found: test2.props" unless="N65550.exists"/>
<delete file="test2.props" verbose="true"/>
<available file="test3.props" property="N65553.exists"/>
<fail message="file not found: test3.props" unless="N65553.exists"/>
<delete file="test3.props" verbose="true"/>
</target>
</project>
Note:
Properties in Ant are immutable, so I used the XSL generate-id() function to create a unique property name.
Software used
This example was tested with the following software versions:
$ ant -version
Apache Ant version 1.6.5 compiled on June 2 2005
$ java -version
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

Target Clean does not exist in the project dir

I have installed Ant in my centos 6.3 , installed location are
/opt/ant and also ANT_HOME env are same
I have created build.xml to test by deleting testdir. This directory exist in the /opt/ant/testdir like this.
build.xml
<?xml version="1.0"?>
<project name="testdir" default="all" basedir=".">
<property name="src" value="src"/>
<property name="build" value="build"/>
<property name="lib" value="lib"/>
<target name="all" depends="clean, compile" description="Builds the whole project">
<echo>Doing all</echo>
</target>
<target name="clean">
<echo message="Deleting bin/java ..." />
<delete dir="testdir/test" />
</target>
</project>
Using Command :-
ant -buildfile build.xml Clean
getting error:-
BUILD FAILED
Target "Clean" does not exist in the project "testdir".
Any suggestion to make it work?
You mis-spelt the target name ? 'Clean' as against 'clean' ??
I have found solution. I missed target="compile" block in build.xml.
<target name="compile">
<echo message="Compiling source code"/>
</target>
Run command :-
ant clean

Ant: Why are my CLI args not persisting when I invoke targets that use them?

I have a property and target in my build.xml:
<property name="somedir" value="path/to/dir/${prop}"/>
<echo message="${prop}"/>
<target name="foo">
<echo message="Property: ${somedir}"/>
</target>
In the directory where build.xml is I run:
ant -Dprop="someVal" foo
This gets echoed:
[echo] someVal
[echo] Property: path/to/dir/
What happened to ${prop} when foo is called? How do I get the value to persist when foo is invoked?
Thanks in advance!
I can't reproduce your issue. What version of ANT are you using?
build.xml
<project name="demo" default="foo">
<property name="somedir" value="path/to/dir/${prop}"/>
<echo message="${prop}"/>
<target name="foo">
<echo message="Property: ${somedir}"/>
</target>
</project>
Run as follows:
$ ant -Dprop=hello
Buildfile: /home/me/tmp/build.xml
[echo] hello
foo:
[echo] Property: path/to/dir/hello
ANT version:
$ ant -version
Apache Ant(TM) version 1.9.0 compiled on March 5 2013
I'm using Ant version 1.8.4
I have this as my build.xml
<project>
<property name="somedir" value="path/to/dir/${prop}"/>
<echo message="${prop}"/>
<target name="foo">
<echo message="Property: ${somedir}"/>
</target>
</project>
I get this:
$ ant -Dprop=foo foo
Buildfile: /Users/david/build.xml
[echo] foo
foo:
[echo] Property: path/to/dir/foo
BUILD SUCCESSFUL
Total time: 0 seconds
I had to put <project> and </project> in the build.xml or else it wouldn't execute.
Is there something I'm missing? It seems to work fine.
I was trying to overwrite a pre-defined property that is immutable from the build.xml ...this is more along the lines of what I'm trying to do:
<project>
<property name="basedir" value="/usr/me/${prop}"/>
<echo message="${basedir}"/>
</project>
echos:
Buildfile: build.xml
[echo] /usr/me
BUILD SUCCESSFUL
Total time: 0 seconds
facepalm

How to get Sonar to export test stats?

I have the following Sonar Ant target defined:
<target name='sonar'>
<property name='sonar.sources' value='${src.dir}'/>
<property name='sonar.tests' value='${test.src.dir}'/>
<property name='sonar.binaries' value='build/classes'/>
<path id='jars'>
<fileset dir='${env.JAVA_HOME}/jre/lib' includes='*.jar'/>
<fileset dir='build/lib/test' includes='*.jar'/>
</path>
<pathconvert property='sonar.libraries' refid='jars' pathsep=','/>
<exec executable='p4' outputproperty='p4.P4CLIENT'>
<arg value='set'/>
<arg value='P4CLIENT'/>
</exec>
<propertyregex
property='p4client'
input='${p4.P4CLIENT}'
regexp='P4CLIENT=([^ ]+) *.*'
replace='\1'/>
<propertyregex
property='sonar.timestamp'
input='${build.time}'
regexp='_'
replace='T'/>
<sonar:sonar key='com.netflix:${module.name}' version='${p4client}#${sonar.timestamp}' xmlns:sonar='antlib:org.sonar.ant'/>
<property name='sonar.dynamicAnalysis' value='reuseReports'/>
<property name='sonar.emma.reportPath' value='${coverage.dir}'/>
</target>
When I run 'ant sonar' and bring up Sonar in my browser, I see info about the classes in the src directory, but nothing about the stuff in the test directory.
If I add ${test.src.dir} to sonar.sources and not set sonar.tests, I see some info about the test classes, but Sonar still reports 0 Test Successes.
How do I get it so I can drill down to each test method and their stats?
For anyone else that runs across this issue, I finally got Sonar to report on our Emma Code coverage. The first problem was that the Emma plugin did not come with the version of Sonar I was using (3.1.1). I had to download it and install it to the extensions/plugins directory of Sonar and restart it.
Then I had to set the following properties in my build.xml:
<property name="sonar.core.codeCoveragePlugin" value="emma" />
<property name="sonar.emma.reportPath" value="${coverage.dir}" />
After this, I atleast saw the following output after running the Sonar ant task:
[sonar:sonar] 13:41:49.705 WARN org.sonar.INFO - No coverage (*.ec) file found in /my/local/path
[sonar:sonar] 13:41:49.708 WARN org.sonar.INFO - No metadata (*.em) file found in /my/local/path
After some digging, I found that inside of the Sonar Emma plugin, it is hard-coded to look for a .ec (coverage) file and a .em (metadata) file. Unfortunately, my coverage file had a .emma extension as did my metadata file and I was unable to rename them as it would break other functionality. So I wrote the following Ant task to copy the files to match the naming standard that the Sonar Emma plugin expects.
<target name="createEmmaFilesWithSonarNamingStandard" depends="defineAntContribTasks">
<if>
<available file="${coverage.dir}/metadata.emma" />
<then>
<copyfile src="${coverage.dir}/metadata.emma" dest="${coverage.dir}/metadata.em" />
</then>
</if>
<if>
<available file="${coverage.dir}/coverage.emma" />
<then>
<copyfile src="${coverage.dir}/coverage.emma" dest="${coverage.dir}/coverage.ec" />
</then>
</if>
</target>
After running this again, I came across a new problem:
org.sonar.api.utils.SonarException: java.io.IOException: cannot read [/my/local/path/build/coverage/metadata.em]: created by another EMMA version [2.0.5312]
After some more digging, I found that the Sonar Emma 1.0.1 plugin was compiled against Emma 2.0.5312 and the Sonar Emma 1.1 and 1.2.x against Emma version 2.1.5320 as stated on the Sonar Emma plugin page.
I downloaded the 2.1.5320 version of Emma, replaced both emma.jar as well as emma_ant.jar in my Ant lib directory. After a clean re-compile and test, I was able to re-run the Sonar Ant task and have my code coverage reflected on Sonar.
The property 'sonar.surefire.reportsPath' needs to be defined before the definition of the sonar target.
The following definition gets the test info exported (although it's still not exporting coverage info):
<property name='sonar.surefire.reportsPath' value='${test.dir}'/>
<property name='sonar.dynamicAnalysis' value='reuseReports'/>
<property name='sonar.emma.reportPath' value='${coverage.report.dir}'/>
<target name='sonar'>
<property name='sonar.sources' value='${src.dir}'/>
<property name='sonar.tests' value='${test.src.dir}'/>
<property name='sonar.binaries' value='${build.dir}'/>
<path id='jars'>
<fileset dir='${env.JAVA_HOME}/jre/lib' includes='*.jar'/>
<fileset dir='${ivy.lib.dir}/test' includes='*.jar'/>
</path>
<pathconvert property='sonar.libraries' refid='jars' pathsep=','/>
<exec executable='p4' outputproperty='p4.P4CLIENT'>
<arg value='set'/>
<arg value='P4CLIENT'/>
</exec>
<propertyregex
property='p4client'
input='${p4.P4CLIENT}'
regexp='P4CLIENT=([^ ]+) *.*'
replace='\1'/>
<propertyregex
property='sonar.timestamp'
input='${build.time}'
regexp='_'
replace='T'/>
<sonar:sonar key='com.netflix:${module.name}' version='${p4client}#${sonar.timestamp}' xmlns:sonar='antlib:org.sonar.ant'/>
</target>

strip till delimeter in ant

I have a target which will run a executable and get a version. But I need to remove stuff till the delimeter. Help me please.
<target name="tomcatVersion">
<exec executable="${WT_HOME}/tomcat/bin/catalina.bat" outputproperty="tomcat.version">
<arg value="version" />
<redirector>
<outputfilterchain>
<tokenfilter>
<containsstring contains="Server number:"/>
</tokenfilter>
</outputfilterchain>
</redirector>
</exec>
<echo message="${tomcat.version}"/>
</target>
[Update: single step loadresource method with thanks to Matt]
You could do this by reading the output of the executable into a property and then filtering the property through a replaceregexp token filter to extract the string you require. For example:
<project default="get-version">
<target name="get-version">
<exec executable="bash" outputproperty="version.output">
<arg value="ant"/>
<arg value="-version"/>
</exec>
<loadresource property="version">
<string value="${version.output}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="[^\d]*(\d.\d.\d).*" replace="\1"/>
</tokenfilter>
<striplinebreaks/>
</filterchain>
</loadresource>
<echo level="info" message="version is: '${version}'"/>
</target>
</project>
Sample output:
$ ant -version
Apache Ant(TM) version 1.8.2 compiled on December 20 2010
$ ant
Buildfile: build.xml
get-version:
[echo] version is: '1.8.2'
BUILD SUCCESSFUL
Total time: 2 seconds
(I am using ant -version as a handy stand in for whatever executable you are running. I am aware that Ant version can be got from Ant properties.)
With older versions of Ant (<1.7) you could do this in two steps:
Write the output of the executable to file
Read the file through a replaceregexp token filter
For example:
<project default="get-version">
<target name="get-version">
<exec executable="bash" output="version.out">
<arg value="ant"/>
<arg value="-version"/>
</exec>
<loadfile property="version" srcfile="version.out">
<filterchain>
<tokenfilter>
<replaceregex pattern="[^\d]*(\d.\d.\d).*" replace="\1"/>
</tokenfilter>
<striplinebreaks/>
</filterchain>
</loadfile>
<echo level="info" message="version is: '${version}'"/>
</target>
</project>
Sample output
$ ant -version
Apache Ant version 1.6.5 compiled on June 2 2005
$ ant
Buildfile: build.xml
get-version:
[echo] version is: '1.6.5'
BUILD SUCCESSFUL
Total time: 2 seconds
The exec task has 3 attributes to catch the output from an executable :
outputproperty => catches stdout
errorproperty => catches stderr
resultproperty => catches returncode
see Ant Manual for exec task
So for your purpose :
use outputproperty to catch the
version written to stdout
grep the versionstring from
outputproperty via String replace
function from Ant Plugin Flaka
<project xmlns:fl="antlib:it.haefelinger.flaka">
<exec executable="bash" outputproperty="bashversion">
<arg value="--version"/>
</exec>
<fl:let>bashversion ::= '#{replace('${bashversion}','$2','(?s)(.+)(\d\.\d\.\d\(.\)?)(.+)')}'</fl:let>
<fl:echo>
Bashversion => ${bashversion}
</fl:echo>
</project>
output :
[fl:echo] Bashversion => 4.1.7(1)

Resources