Getting condition doesn't support the nested "then" element in <condition> - ant

I'm new to Ant/Apache. When I tried to use <condition> tag in XML it's throwing an error. condition doesn't support the nested "then" element. Here is my code
<target name="determine-ae-build">
<condition property="ApplicationName">
<equals arg1="${ApplicationName}" arg2="new"/>
<then>
<echo>3.9 Robots Config Copied</echo>
</then>
<else>
<condition property="ApplicationName">
<equals arg1="${ApplicationName}" arg2="old"/>
<then>
<echo>3.8 Robots Config Copied</echo>
</then>
<else>
<echo>3.9 Robots Config Copied</echo>
</else>
</condition>
</else>
</condition>
</target>
I've tried with IF also but since my Ant version is not supporting to do this. Can someone help to resolve this issue. Thanks! in advance

The condition task simply sets a property; it doesn't contain nested build logic. The property that it sets can later be used to control which targets are executed.
While you can use antcontrib's extra if, then, and else tasks to accomplish something like what you showed in your example, I'd recommend sticking to the native Ant approach, which relies on target dependencies and uses separate targets to control build logic:
<project name="build" basedir="." default="build">
<target name="build" depends="copy-3.8,copy-3.9" />
<target name="copy-3.8" depends="determine-ae-build" if="copy.old">
<echo>3.8 Robots Config Copied</echo>
</target>
<target name="copy-3.9" depends="determine-ae-build" unless="copy.old">
<echo>3.9 Robots Config Copied</echo>
</target>
<target name="determine-ae-build">
<condition property="copy.old">
<equals arg1="${ApplicationName}" arg2="old"/>
</condition>
</target>
</project>
With the above script, you would run ant build (possibly with -DApplicationName=old). The build target depends on both copy targets, both of which depend on determine-ae-build. The determine-ae-build target will therefore run first. If ApplicationName is set to "old" (either from a properties file that has been loaded, or from being provided in command line with -DApplicationName=old) then the property copy.old will be set to true. Otherwise it will remain unset.
Then copy-3.8 and copy-3.9 will be called. If copy.old is is true, copy-3.8 will run. Otherwise, it will be skipped. copy-3.9 has no condition so it will run no matter what.
Lastly, the build target will execute because it was the original target called from the command line, but it contains no actual steps so the build will finish.

<target name="prepare-copy" description="copy file based on condition" depends="determine-ae-build, prepare-copy-old, prepare-copy-new, prepare-copy-default">
<sleep seconds="10"/> --To read the results
</target>
<target name="prepare-copy-old" description="copy file based on condition" if="copy.old">
<echo>Old File Copied </echo>
</target>
<target name="prepare-copy-new" description="copy file based on condition" if="copy.new">
<echo>New File Copied</echo>
</target>
<target name="prepare-copy-default" description="copy file based on false condition" if="copy.default">
<echo>Default File Coping</echo>
</target>
<target name="determine-ae-build">
<condition property="copy.old">
<equals arg1="${ApplicationName}" arg2="old"/>
</condition>
<condition property="copy.new">
<equals arg1="${ApplicationName}" arg2="new"/>
</condition>
<condition property="copy.default">
<not>
<or>
<equals arg1="${ApplicationName}" arg2="new"/>
<equals arg1="${ApplicationName}" arg2="old"/>
</or>
</not>
</condition>
</target>
Explanation: Calling way "ant -Dcopy.old = true prepare-copy". Here we are passing to copy old file hence, "Old File Copied" will copied. If you call it like "ant prepare-copy" it'll call "Default File Coping".
Kindly Accept my answer if it is answered your question.Thankyou!

Related

How to check if Ant is executed under certain path?

How can I use Ant to verify that the current working directory is located (arbitrarily deeply nested) under a certain path? For example, I want to execute a target only if the current directory is part of /some/dir/, for example if Ant is executed in directory /some/dir/to/my/project/.
The best I could come up with is a String contains condition:
<if>
<contains string="${basedir}" substring="/some/dir/"/>
<then>
<echo>Execute!</echo>
</then>
<else>
<echo>Skip.</echo>
</else>
</if>
This works for my current purpose but I'm afraid it might break some time in the future... for example when a build is executed in path /not/some/dir/ which is also contains the specified directory string.
Are there any more robust solutions like a startsWith comparison or even better a file system based check...?
There is no specific startswith condition in native Ant, but there is a matches condition that takes regular expressions.
As a side note, ant-contrib is rarely necessary for most build scripts, and will often lead to unreliable code. I would strongly recommend avoiding it.
Here's a sample script to illustrate how you can use the matches condition with native Ant. The test target is, of course, just for demonstration.
<property name="pattern" value="^/some/dir" />
<target name="init">
<condition property="basedir.starts.with">
<matches pattern="${pattern}" string="${basedir}" />
</condition>
</target>
<target name="execute" depends="init" if="basedir.starts.with">
<echo message="Executing" />
</target>
<target name="test">
<condition property="dir1.starts.with">
<matches pattern="${pattern}" string="/some/dir/" />
</condition>
<condition property="dir2.starts.with">
<matches pattern="${pattern}" string="/some/dir/to/my/project/" />
</condition>
<condition property="dir3.starts.with">
<matches pattern="${pattern}" string="/not/some/dir/" />
</condition>
<echo message="${dir1.starts.with}" />
<echo message="${dir2.starts.with}" />
<echo message="${dir3.starts.with}" />
</target>

Conditionally load properties files in Ant

My Ant script should download a ZIP file which contains a set-up file to be installed in a database (Oracle or PostgreSQL) and generate dumps. Different dumps are generated depending on the properties data provided in the set up file.
I have 3 properties files:
user.properties : this contains various details provided from Jenkins and apart from that a value: prepare.MTdump.generate=true
nonMT.properties
MT.properties
Is it possible in Ant to load the first properties file user.properties and depending upon the condition (e.g. if prepare.MTdump.generate=true) load MT.properties or if it's false load nonMT.properties?
I have been unable to add an IF condition to load the properties file. I even tried with the unless condition of <target> but have been unable to achieve the requirement.
If you are using ant-contrib, this should work:
<property file="user.properties"/>
<if>
<equals arg1="${prepare.MTdump.generate}" arg2="true"/>
<then>
<property file="MT.properties"/>
</then>
<else>
<property file="nonMT.properties"/>
</else>
</if>
Otherwise, you can just use conditions. Just run the loadProperties target below.
<property file="user.properties"/>
<target name="test.if.use.MT">
<condition property="useMT">
<equals arg1="${prepare.MTdump.generate}" arg2="true"/>
</condition>
<condition property="useNonMT">
<not>
<equals arg1="${prepare.MTdump.generate}" arg2="true"/>
</not>
</condition>
</target>
<target name="loadMTProperties" if="${useMT}" depends="test.if.use.MT">
<property file="MT.properties"/>
</target>
<target name="loadNonMTProperties" if="${useNonMT}" depends="test.if.use.MT">
<property file="nonMT.properties"/>
</target>
<target name="loadProperties" depends="loadMTProperties, loadNonMTProperties"/>

How to stop ant script execution or skip targets without fail?

I want to terminate an ant script, or skip some targets, but without the fail task. I wanted to do it like this:
`
<target name="init">
<condition property="canContinue">
<not>
<equals arg1="${isOffline}" arg2="1" />
</not>
</condition>
</target>
<target name="init-setup" depends="init" if="canContinue">
<echo message="CanContinue: ${canContinue}"/>
</target>
<target name="doIt" depends="init-setup">
</target>
`
I would like to skip all the targets which depend on init-setup, not just init-setup.
How can I do this?
Thank you!
If you're not using explicit fail tasks, you'll need to add your boolean flag to each target you want to skip.
Using your example:
<target name="doIt" depends="init-setup" if="canContinue">
</target>

Use pure Ant to implement if else condition (check command line input)

I am a newbie in Ant. My ant script receives a user input variable named "env" from command line:
e.g. ant doIt -Denv=test
The user input value could be "test","dev" or "prod".
I also have the "doIt" target:
<target name="doIt">
//What to do here?
</target>
In my target, I would like to create the following if else condition for my ant script:
if(env == "test")
echo "test"
else if(env == "prod")
echo "prod"
else if(env == "dev")
echo "dev"
else
echo "You have to input env"
That's to check which value user has inputted from command line, then, print a message accordingly.
I know with ant-Contrib, I can write ant script with <if> <else> . But for my project, I would like to use pure Ant to implement if else condition. Probably, I should use <condition> ?? But I am not sure how to use <condition> for my logic. Could some one help me please?
You can create few targets and use if/unless tags.
<project name="if.test" default="doIt">
<target name="doIt" depends="-doIt.init, -test, -prod, -dev, -else"></target>
<target name="-doIt.init">
<condition property="do.test">
<equals arg1="${env}" arg2="test" />
</condition>
<condition property="do.prod">
<equals arg1="${env}" arg2="prod" />
</condition>
<condition property="do.dev">
<equals arg1="${env}" arg2="dev" />
</condition>
<condition property="do.else">
<not>
<or>
<equals arg1="${env}" arg2="test" />
<equals arg1="${env}" arg2="prod" />
<equals arg1="${env}" arg2="dev" />
</or>
</not>
</condition>
</target>
<target name="-test" if="do.test">
<echo>this target will be called only when property $${do.test} is set</echo>
</target>
<target name="-prod" if="do.prod">
<echo>this target will be called only when property $${do.prod} is set</echo>
</target>
<target name="-dev" if="do.dev">
<echo>this target will be called only when property $${do.dev} is set</echo>
</target>
<target name="-else" if="do.else">
<echo>this target will be called only when property $${env} does not equal test/prod/dev</echo>
</target>
</project>
Targets with - prefix are private so user won't be able to run them from command line.
If any of you require a plain if/else condition (without elseif); then use the below:
Here I am dependent on a env variable DMAPM_BUILD_VER, but it may happen that this variable is not set in the env. So I need to have mechanism to default to a local value.
<!-- Read build.version value from env variable DMAPM_BUILD_VER. If it is not set, take default.build.version. -->
<property name="default.build.version" value="0.1.0.0" />
<condition property="build.version" value="${env.DMAPM_BUILD_VER}" else="${default.build.version}">
<isset property="env.DMAPM_BUILD_VER"/>
</condition>

How to use logical operators in ant?

i have a small peice of code which prints if platform is unix or windowsas
<if>
<equals=${arg1} value="linux-86"/>
<then>
<echo message="linux"
<then>
<elseif>
<equals=${arg1} value="linux-64"/>
<then>
<echo message="linux"/>
</then>
</elseif>
<else>
<echo message="Windows">
</else>
</if>
Here we can see we are unnecessarily checking first two conditions for same message,is there any OR operator in ant like we have in c ||,so that we can write arg1=linux-64||linux-86....if there is please tell me how should i use this will save up lot of time here
<condition property="WinPlatform.Check">
<or>
<equals arg1="${param1}" arg2="win-x86"/>
<equals arg1="${param1}" arg2="win-x86-client"/>
<equals arg1="${param1}" arg2="win-x64"/>
</or>
</condition>
<target name="Mytarget" if="WinPlatform.Check">
<echo message="executing windows family build:::${param1}"/>
</target>
now call Mytarget with your parameter,it will work
The if task is part of ant-contrib. It is not available in core Ant.
Various conditions are available in core Ant and can be used, for example, to make target execution conditional.
Before 1.8, if/unless conditions evaluate "is the property set?"
<target name="test" if="foo" unless="bar"/>
From 1.8, if/unless conditions can evaluate "is the property true/false":
<target name="test" if="${foo}" unless="${bar}"/>
Why don't you have a look in the ant manual? http://ant.apache.org/manual/Tasks/conditions.html
Or google for "ant if task".

Resources