execute Ant task if TWO conditions are met - ant

The above ant script implements if dir_is_empty then git-clone else git-fetch using Ant-1.7.1 core statements:
<target name="update" depends="git.clone, git.fetch" />
<target name="check.dir">
<fileset dir="${dir}" id="fileset"/>
<pathconvert refid="fileset" property="dir.contains-files" setonempty="false"/>
</target>
<target name="git.clone" depends="check.dir" unless="dir.contains-files">
<exec executable="git">
<arg value="clone"/>
<arg value="${repo}"/>
<arg value="${dir}"/>
</exec>
</target>
<target name="git.fetch" depends="check.dir" if="dir.contains-files" >
<exec executable="git" dir="${dir}">
<arg value="fetch"/>
</exec>
</target>
(see my other post)
But how to implement a target enabled by two conditions?
if dir_does_not_exist or dir_is_empty then git-clone else git-fetch
my current attempt:
<target name="git.clone"
depends="chk.exist, chk.empty"
unless="!dir.exist || dir.noempty" >
[...]
</target>
<target name="chk.exist">
<condition property="dir.exist">
<available file="${dir}/.git" type="dir"/>
</condition>
</target>
[...]
I would prefer Ant-1.7.1 core statements. But I am open about other possibilities as Ant contrib, or embedded script... Feel free to post your ideas...
(See also question Execute ANT task just if a condition is met)

Even when bound to Ant 1.7.1 you may combine your 3 chk targets into one, see the condition part in the snippet.
Since Ant 1.9.1 (better use Ant 1.9.3 because of bugs in Ant 1.9.1 see this answer for details) it is possible to add if and unless attributes on all tasks and nested elements, so no extra target needed, f.e. :
<project xmlns:if="ant:if" xmlns:unless="ant:unless">
<condition property="cloned" else="false">
<and>
<available file="${dir}/.git" type="dir" />
<resourcecount when="gt" count="0">
<fileset dir="${dir}/.git" />
</resourcecount>
</and>
</condition>
<exec executable="git" unless:true="${cloned}">
<arg value="clone" />
<arg value="${repo}" />
<arg value="${dir}" />
</exec>
<exec executable="git" dir="${dir}" if:true="${cloned}">
<arg value="fetch" />
</exec>
</project>

From the ant documentation on targets:
Only one propertyname can be specified in the if/unless clause.
If you want to check multiple conditions, you can use a dependend target for computing the result for the check:
<target name="myTarget" depends="myTarget.check" if="myTarget.run">
<echo>Files foo.txt and bar.txt are present.</echo>
</target>
<target name="myTarget.check">
<condition property="myTarget.run">
<and>
<available file="foo.txt"/>
<available file="bar.txt"/>
</and>
</condition>
</target>
Moreover, there were some discussions on dev#ant.apache.org and user#ant.apache.org mailing-lists:
Using multiple properties in the 'if' and 'unless' conditions (June 2006)
Support mutliple if and unless (August 2008)
Multiple conditions satisfying in an ant target (October 2008)
For example, the following target combines two properties (dir.exist and dir.noempty) to create another one (cloned) using operators <and> and <istrue> (many other operators are documented as <or>, <xor>, <not>, <isfalse>, <equals>, <length>).
<target name="chk" depends="chk.exist, chk.empty" >
<condition property="cloned">
<and>
<istrue value="dir.exist" />
<istrue value="dir.noempty" />
</and>
</condition>
</target>
The above property "cloned" is used by targets git.clone and git.fetch as follows:
<target name="update" depends="git.clone, git.fetch" />
<target name="git.clone" depends="chk" unless="cloned" >
<exec executable="git" >
<arg value="clone" />
<arg value="${repo}" />
<arg value="${dir}" />
</exec>
</target>
<target name="git.fetch" depends="chk" if="cloned" >
<exec executable="git" dir="${dir}">
<arg value="fetch"/>
</exec>
</target>
<target name="chk.exist" >
<condition property="dir.exist" >
<available file="${dir}" type="dir" />
</condition>
</target>
<target name="chk.empty" >
<fileset dir="${dir}" id="fileset" />
<pathconvert refid="fileset" property="dir.noempty" setonempty="false" />
</target>

Related

how to change variable depending on OS in ant

I am using more then one target for setting the variable name depending on OS.
<target name="checkos">
<condition property="isWindows">
<os family="windows" />
</condition>
<condition property="isUnix">
<os family="unix" />
</condition>
</target>
<target name="if_windows" depends="checkos" if="isWindows">
<property name="path" location="deploy.exe"/>
</target>
<target name="if_unix" depends="checkos" if="isUnix">
<property name="path" location="deploy.sh"/>
</target>
How can i set it in the single target.
I used if and condition but it doesn't allow it to do so.
With ant >= 1.9.1 use the new if/unless feature introduced with Ant 1.9.1 but you should use Ant 1.9.3 because of bugs in Ant 1.9.1 see this answer for details
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<target name="setos">
<condition property="isWindows">
<os family="windows" />
</condition>
<property name="path" location="deploy.exe" if:true="${isWindows}"/>
<property name="path" location="deploy.sh" unless:true="${isWindows}"/>
</target>
</project>
otherwise with ant < 1.9.1 use something like :
<target name="checkos">
<condition property="isWindows">
<os family="windows" />
</condition>
</target>
<target name="if_windows" depends="checkos" if="isWindows">
<property name="path" location="deploy.exe"/>
</target>
<target name="if_unix" depends="checkos" unless="isWindows">
<property name="path" location="deploy.sh"/>
</target>

How to check two properties in an if condition of an Ant task?

It is possible to execute an Ant target conditionally by specifying an if or unless clause. As far as I can see this clause accepts only one property. How can I check for two properties?
This is an example:
<project default="test">
<property name="a" value="true"/>
<property name="b" value="true"/>
<target name="test-a" if="a">
<echo>a</echo>
</target>
<target name="test-b" if="b">
<echo>b</echo>
</target>
<target name="test-ab" if="a,b">
<echo>a and b</echo>
</target>
<target name="test" depends="test-a,test-b,test-ab"/>
</project>
If I run it, the test-ab target generates no output:
$ ant -f target-if.xml
Buildfile: target-if.xml
test-a:
[echo] a
test-b:
[echo] b
test-ab:
test:
BUILD SUCCESSFUL
Total time: 0 seconds
How to specify an and expression for the two properties?
Unfortunately, no. From the ant Targets manual:
Only one propertyname can be specified in the if/unless clause. If you
want to check multiple conditions, you can use a dependend target for
computing the result for the check:
<target name="myTarget" depends="myTarget.check" if="myTarget.run">
<echo>Files foo.txt and bar.txt are present.</echo>
</target>
<target name="myTarget.check">
<condition property="myTarget.run">
<and>
<available file="foo.txt"/>
<available file="bar.txt"/>
</and>
</condition>
</target>
This is my example with the use of the condition element:
<project default="test">
<property name="a" value="true"/>
<property name="b" value="true"/>
<target name="test-a" if="a">
<echo>a</echo>
</target>
<target name="test-b" if="b">
<echo>b</echo>
</target>
<condition property="a-and-b">
<and>
<equals arg1="${a}" arg2="true"/>
<equals arg1="${b}" arg2="true"/>
</and>
</condition>
<target name="test-ab" if="a-and-b">
<echo>a and b</echo>
</target>
<target name="test" depends="test-a,test-b,test-ab"/>
</project>

How to emulate if-elseif-else in Ant without using Ant-contrib?

I need an if-elseif-else conditional statement in Ant.
I do not want to use Ant-contrib.
I tried the solution here
<target name="condition.check">
<input message="Please enter something: " addproperty="somethingProp"/>
<condition property="allIsWellBool">
<not>
<equals arg1="${somethingProp}" arg2="" trim="true"/>
</not>
</condition>
</target>
<target name="if" depends="condition.check, else" if="allIsWellBool">
<echo message="if condition executes here"/>
</target>
<target name="else" depends="condition.check" unless="allIsWellBool">
<echo message="else condition executes here"/>
</target>
But I will have to set properties inside the if and else targets which will not be visible in the calling target.
Is there any other way out using conditions?
Move the dependencies out of if and else into a new target that depends on all of the other targets:
<project name="ant-if-else" default="newTarget">
<target name="newTarget" depends="condition.check, if, else"/>
<target name="condition.check">
<input message="Please enter something: " addproperty="somethingProp"/>
<condition property="allIsWellBool">
<not>
<equals arg1="${somethingProp}" arg2="" trim="true"/>
</not>
</condition>
</target>
<target name="if" if="allIsWellBool">
<echo message="if condition executes here"/>
</target>
<target name="else" unless="allIsWellBool">
<echo message="else condition executes here"/>
</target>
</project>

How to conditionally execute batch scripts for different platforms using Ant?

I am attempting to use an Ant build script to build a project that already has nmake (Visual Studio) build scripts. Rather than redo the entire build script, I would like to have Ant reuse the existing scripts.
So, I have something like this which works for Windows Mobile 6 ARMV4I builds:
<project ...>
<target name="-BUILD.XML-COMPILE" depends="-init, -pre-compile">
<exec executable="cmd">
<arg value="/c"/>
<arg line='"${g.path.project}\build-wm6-armv4i.bat"'/>
</exec>
<antcall target="-post-compile" inheritall="true" inheritrefs="true" />
</target>
</project>
But I would also like it to work for other platforms like Win32 x86 and Windows CE6 x86.
How can I have the Ant script discriminate which batch file it should execute to perform the build?
The <os> condition may be used to set properties based on the operating system and the hardware architecture. Targets may be conditionally executed using the if and unless attributes.
<?xml version="1.0" encoding="UTF-8"?>
<project name="build" basedir="." default="BUILD.XML-COMPILE">
<condition property="Win32-x86">
<and>
<os family="windows" />
<or>
<os arch="i386" />
<os arch="x86" />
</or>
</and>
</condition>
<condition property="Win-ARMv4">
<os family="windows" arch="armv4" />
</condition>
<target name="-BUILD.XML-COMPILE_Win-ARMv4" if="Win-ARMv4"
depends="-init, -pre-compile">
<exec executable="cmd">
<arg value="/c"/>
<arg line='"${g.path.project}\build-wm6-armv4i.bat"'/>
</exec>
<antcall target="-post-compile" inheritall="true" inheritrefs="true" />
</target>
<target name="-BUILD.XML-COMPILE_Win32-x86" if="Win32-x86"
depends="-init, -pre-compile">
<exec executable="cmd">
<arg value="/c"/>
<arg line='"${g.path.project}\build-win32-x86.bat"'/>
</exec>
<antcall target="-post-compile" inheritall="true" inheritrefs="true" />
</target>
<!-- Execute the correct target automatically based on current platform. -->
<target name="BUILD.XML-COMPILE"
depends="-BUILD.XML-COMPILE_Win-ARMv4,
-BUILD.XML-COMPILE_Win32-x86" />
</project>
The paths to the batch files are both single and double quoted so that file paths with spaces will not break the script. I have not tested this script on Windows Mobile 6 ARMV4I, so you will want to use the Ant target below to verify the name.
<target name="echo-os-name-arch-version">
<echo message="OS Name is: ${os.name}" />
<echo message="OS Architecture is: ${os.arch}" />
<echo message="OS Version is: ${os.version}" />
</target>
Related stack overflow questions:
how to detect the windows OS in ANT
Using ant to detect os and set property

How to read properties file in ant

Hi all these are the contents of my file.properties file and i want to print those platforms which have true valu and their installer location,it is sure that the platform which has true value will only have installer:
platform.win-x86=true
platform.win-x86-client=false
platform.win-x64=true
platform.linux-x86=false
installer-zip.win-x86=E:\\abc\\abc.jar
installer-zip.win-x64=E:\\def\\def.jar
tried many thing but could not one of the things i used was as
<propertyselector property="platform.list"
delim`enter code here`iter=","
match="platform\.([^\.]*)"
select="\1"
casesensitive="false" />
<propertyselector property="zip.list"
delimiter=","
match="installer-zip\.([^\.]*)"
select="\1"
casesensitive="false" />
<target name="print.name" >
<propertycopy name="platform.name" from="platform.${platform.id}" />
<if> <equals arg1="${platform.name}" arg2="true" />
<then>
<echo>PlatForm.Id====>${platform.id}</echo>
<echo message="${platform.name}" />
<echo file="platform.properties" append="yes">${new.platform-name}=Yes${line.separator}</echo>
</then>
</if>
</target>
<target name="print.zipname" >
<propertycopy name="zip.name" from="installer-zip.${zip.id}" />
<echo>zip.Id====>${zip.id}</echo>
<echo message="${zip.name}" />
</target>
<target name="first">
<foreach list="${platform.list}"
delimiter=","
target="print.name"
param="platform.id" />
<foreach list="${zip.list}"
delimiter=","
target="print.zipname"
param="zip.id" />
</target>
although it prints value for all true platforms but for installer it prints only 1,and then breaks..can you help please
This is not directly answering your question, but rather showing you how you could use the same properties to perform conditional targets in your build.
<project default="build">
<property file="platform.properties"/>
<condition property="build.win-x86">
<and>
<istrue value="${platform.win-x86}"/>
<isset property="installer-zip.win-x86"/>
</and>
</condition>
<condition property="build.win-x86-client">
<and>
<istrue value="${platform.win-x86-client}"/>
<isset property="installer-zip.win-x86-client"/>
</and>
</condition>
<condition property="build.win-x64">
<and>
<istrue value="${platform.win-x64}"/>
<isset property="installer-zip.win-x64"/>
</and>
</condition>
<condition property="build.linux-x86">
<and>
<istrue value="${platform.linux-x86}"/>
<isset property="installer-zip.linux-x86"/>
</and>
</condition>
<target name="build" depends="win-x86, win-x86-client, win-x64, linux-x86"/>
<target name="win-x86" depends="win-x86-build, win-x86-installer"/>
<target name="win-x86-client" depends="win-x86-client-build, win-x86-client-installer"/>
<target name="win-x64" depends="win-x64-build, win-x64-installer"/>
<target name="linux-x86" depends="linux-x86-build, linux-x86-installer"/>
<target name="win-x86-build" if="${build.win-x86}">
<echo message="executing win-x86-build"/>
</target>
<target name="win-x86-installer" if="${build.win-x86}">
<echo message="installer: ${installer-zip.win-x86}"/>
</target>
<target name="win-x86-client-build" if="${build.win-x86-client}">
<echo message="executing win-x86-client-build"/>
</target>
<target name="win-x86-client-installer" if="${build.win-x86-client}">
<echo message="installer: ${installer-zip.win-x86-client}"/>
</target>
<target name="win-x64-build" if="${build.win-x64}">
<echo message="executing win-x64-build"/>
</target>
<target name="win-x64-installer" if="${build.win-x64}">
<echo message="installer: ${installer-zip.win-x64}"/>
</target>
<target name="linux-x86-build" if="${build.linux-x86}">
<echo message="executing linux-x86-build"/>
</target>
<target name="linux-x86-installer" if="${build.linux-x86}">
<echo message="installer: ${installer-zip.linux-x86}"/>
</target>
</project>
The output based on your properties file is below. Note that only the win-x86 and win-64 targets were actually executed. The others were skipped because the required conditions were not satisfied:
win-x86-build:
[echo] executing win-x86-build
win-x86-installer:
[echo] installer: E:\abc\abc.jar
win-x86:
win-x86-client-build:
win-x86-client-installer:
win-x86-client:
win-x64-build:
[echo] executing win-x64-build
win-x64-installer:
[echo] installer: E:\def\def.jar
win-x64:
linux-x86-build:
linux-x86-installer:
linux-x86:
build:
BUILD SUCCESSFUL
Total time: 0 seconds

Resources