Using a conditional length in ANT - ant

I am currently trying to use the length task in ANT, more specifically making a conditional length task.
I want to to flag a message to a currently existing file if a file is greater than a set length, like so:
<project name="ant" default="check-filesize">
<target name="check-filesize">
<length mode="all" property="fs.length.bytes" when="gt" length="100">
<fileset dir="size" includes="*"/>
</length>
<echo>sorry your file set is to large</echo>
</target>
</project>
I have already written the code to print the size of all files in the directory but I haven't included it here to keep this brief.
If length does not allow for the echo tag can I perform this another way if not does any one know what the when tag does ? Obviously I only want the echo to happen when the condition is violated
Many thanks in advance

I discovered a way to do this using no external libraries, but thankyou for your help. here is how :
<project name="ant" default="check-filesize">
<target name="check-filesize">
<fail message="Your File Exceeds Limitations Please Operator For Full Size Of Data Set>
<condition>
<length length="1000" when="gt" mode="all" property="fs.length.bytes">
<fileset dir="size" includes="*"/>
</length>
</condition>
</fail>
</target>
</project>

Here is a way to conditionally echo a statement using Ant's built-in tasks:
<project name="ant-length" default="check-filesize">
<target name="check-filesize" depends="get-length, echo-if-large"/>
<target name="get-length">
<condition property="fs.length.too.large">
<length mode="all" when="gt" length="100">
<fileset dir="size" includes="*"/>
</length>
</condition>
</target>
<target name="echo-if-large" if="fs.length.too.large">
<echo>sorry your file set is too large</echo>
</target>
</project>
The third-party Ant-Contrib library has an <if> task that simplifies this.

Related

Intentionally fail Ant build when using <delete> with a <fileset> including missing files

<delete includeEmptyDirs="false" failonerror="true">
<fileset dir="${dest.dir}" includes="a.txt,b.txt,c.abc"/>
</delete>
For example, if file a.txt is changed to a1.txt2 or something then Ant is not failing to find file. What to do?
That is not the purpose of failonerror attribute in this case.
From ant manual delete task :
Controls whether an error (such as a failure to delete a file)
stops the build or is merely reported to the screen. Only relevant if
quiet is "false".
It's not an error, if fileset doesn't match.
Also you don't need to set failonerror=true as it is default.
To make it fail, use fail with condition and resourcecount, f.e.:
<delete includeEmptyDirs="false" failonerror="true">
<fileset dir="${dest.dir}" includes="a.txt,b.txt,c.abc" id="foobar"/>
</delete>
<fail message="Fileset doesn't match !">
<condition>
<resourcecount when="eq" count="0">
<fileset refid="foobar"/>
</resourcecount>
</condition>
</fail>

Ant conditional if within a macrodef

Within ant, I have a macrodef.
Assuming I have to use this macrodef, and there is a item inside said macrodef that I want to run if the property special.property exists and is true, what do I do?
I currently have
<macrodef name="someName">
<sequential>
<someMacroDefThatSetsTheProerty />
<some:thingHereThatDependsOn if="special.property" />
<sequential>
</macrodef>
Which doesn't work - the some:thingHereThatDependsOn doesnt have an "if" attribute, and I cannot add one to it.
antcontrib is not available.
With a target I can give the target an "if", what can I do with a macrodef?
In Ant 1.9.1 and higher, there is now a new implementation of if and unless attributes. This might be what you're thinking of.
First, you need to put them into your namespace. Add them to your <project> header:
<project name="myproject" basedir="." default="package"
xmlns:if="ant:if"
xmlns:unless="ant:unless">
Now, you can add them to almost any Ant task or sub entity:
<!-- Copy over files from special directory, but only if it exists -->
<available property="special.dir.available"
file="${special.dir} type="dir"/>
<copy todir="${target.dir}>
<fileset dir="${special.dir}" if:true="special.dir.available"/>
<fileset dir="${other.dir}"/>
</copy>
<!-- FTP files over to host, but only if it's on line-->
<condition property="ftp.available">
<isreachable host="${ftp.host}"/>
</condition>
<ftp server="${ftp.host}"
userid="${userid}"
passowrd="${password}"
if:true="ftp.available">
<fileset dir=".../>
</ftp>
This is only possible if the ANT "thingHereThatDependsOn" task supports an "if" attribute.
As stated above, conditional execution in ANT, normally, only applies to targets.
<target name="doSomething" if="allowed.to.do.something">
..
..
</target>
<target name="doSomethingElse" unless="allowed.to.do.something">
..
..
</target>
<target name="go" depends="doSomething,doSomethingElse"/>

Loop through directory structure in ant

We want to loop through directory structure in ant without using foreach .
Is there any elegant way to do the same ?
The apply task can iterate over a set of directories or files
<target name="run-apply">
<apply executable="echo">
<dirset dir="src"/>
</apply>
</target>
I personally like the groovy ANT task
<target name="run-groovy">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<dirset id="dirs" dir="src"/>
<groovy>
project.references.dirs.each {
ant.echo it
}
</groovy>
</target>
The installation of the task jar is easily automated:
<target name="install-groovy">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/groovy-all.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.1.1/groovy-all-2.1.1.jar"/>
</target>
Finally if you're iterating thru other build files, the subant task is very useful:
<target name="run-subant">
<subant>
<fileset dir="src" includes="**/build.xml"/>
</subant>
</target>
Short answer: Not really. There are ways around this, but I prefer the ant-contrib <for/> task for clarity and simplicity. With the <local/> task, you can now localize values of variables. Before, you sometimes had to use ant-contrib's <var/> task to reset the values, so you could loop through them over and over.
<for param="directory">
<fileset dir="${some.dir}"/>
<sequential>
<local name="foo"/>
<local name="bar"/> <!-- Properties that may change with each iteration -->
<!-- Here be dragons -->
</sequential>
</for>
It's clean, simple, and easy to understand. The big issue many people have with Ant Contrib is that not everyone may have it installed in their $ANT_HOME/lib directory. Far enough. So, if you use ant-contrib, put it as part of your project.
I'll put the ant-contrib jar in ${basedir}/antlib/antcontrib and then put this in my program:
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${basedir}/antlib/antcontrib"/>
</classpath>
</taskdef>
Now, when someone checks out my project, they have ant-contrib already installed (since it's inside my project) and accessible (since I point my <taskdef> task at the location of ant-contrib.jar in my project).

subant on condition

I'd like to execute subant on some condition. something like:
<if>
<equals value="value1" property="${some.property">
<then>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref1" />
</subant>
</then>
<else>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref2" />
</subant>
</else>
</if>
But can't find a way to do it. Read the ant manual and googled, but no solution is found.
Thanks.
I believe the error may lie in your equals tag. Instead of using the 'value' and 'propery' attributes, try using 'arg1' and 'arg2', i.e.:
<equals arg1="value1" arg2="${some.property}">
Check out the examples in the ant-contrib doc: http://ant-contrib.sourceforge.net/tasks/tasks/if.html.
If the problem is that your 'if', 'then', and/or 'else' tags are not resolving properly, then you may be missing the ant-contrib libraries. Ant-contrib is not natively included with ant, but you can download it here: http://sourceforge.net/projects/ant-contrib/files/
Per the ant-contrib site (http://ant-contrib.sourceforge.net/), here's what you must do to install ant-contrib:
Option 1: Copy ant-contrib-0.3.jar to the lib directory of your Ant installation. If you want to use one of the tasks in your own project, add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
Option 2: Keep ant-contrib-0.3.jar in a separate location. You now have to tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
Please look up a <target if="${some.property}>. You may want another target with an unless.
If the property has to do with a file existing, see Ant task to check a file exists?. Even if this is not your main concern, I am sure you can get the idea from the accepted answer.
Do you mean calling another target
if so here is
<if>
<equals value="value1" property="${some.property">
<then>
<antcall target="#{target}" failonerror="true" inheritall="false">
</then>
<else>
<antcall target="#{target}" failonerror="true" inheritall="false">
</else>
</if>

ant conditional import

Is it possible to import a file in ant's build.xml if a property is set, if not then don't import it.
Is there a way OTHER THAN using ant-contrib if task.
Thanks
Yes, you can.
For example:
<target name="importFile" depends="myProperty.check" if="myPropertyIsSet">
<echo>Import my file here</echo>
</target>
<target name="myTarget.check">
<condition property="myPropertyIsSet">
<and>
<!-- Conditions to check if my property is set. -->
</and>
</condition>
</target>
Available conditions are described in Apache Ant Manual.
This is quite an old question but since Ant 1.9.1 you can use the "if"-attribute to do conditional imports:
<project name="cond-import" basedir="." xmlns:if="ant:if">
<condition property="script-exists">
<available file="other-ant-script.xml"/>
</condition>
<include if:set="script-exists" file="other-ant-script.xml"/>
</project>

Resources