Conditional property in Ant properties' file - ant

Is it possible to set a property value in Ant property files (as opposed to build.xml) in a conditional way? For example, if apache.root property is set - the my_property will be ${apache.root}/myapp, /var/www/myapp otherwise. If not, what would be the common practice - reusable build.xml files?

Use the condition task:
<project name="demo" default="run">
<condition property="my_property" value="${apache.root}/myapp" else="/var/www/myapp">
<isset property="apache.root"/>
</condition>
<target name="run">
<echo message="my_property=${my_property}"/>
</target>
</project>

You can include different property files based on environments or the conditional variables. For example
<echo>Building ${ant.project.name} on OS: ${os.name}-${os.arch}</echo>
<property file="build-${os.name}.properties" />
this would include a file named 'build-Windows 7.properties' or 'build-Linux.properties' depending on where the build is being run. Of course the property directive looks in the current directory as well as home directory. So the property file could be a part of the build source or in the home directory of the build account.
You can use the condition tag to generate part of the name of the property file as well to select

One of the simplest form of condition you can use is:
<exec executable="hostname" outputproperty="hostname"/>
<condition property="python" value="/usr/bin/python3.4">
<equals arg1="${hostname}" arg2="host0"/>
</condition>
<property name="python" value="/usr/bin/python"/>
to accommodate different python installation path for example. Here, default install path is /usr/bin/python except for host0 where it /usr/bin/python3.4

The OP was asking about a properties file, not within the ant build file. Unfortunately conditionals cannot be done from within the build file. What you can do is have separate property files for each set of dependant properties. For instance:
Build.xml
<condition property="app.name" value="appA">
<equals arg1="${appName}" arg2="A" />
</condition>
<condition property="app.name" value="appB">
<equals arg1="${appName}" arg2="B" />
</condition>
<property file="${app.name}.properties" />
<!-- since properties are immutable, set your defaults here -->
<property name="apache.root" value="/var" />
<property file="restOfProps.properties" />
appA.properties
apache.root=/appA
restOfProps.properties
my_property=${apache.root}/myapp

Related

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"/>

Condition based on environment in Ant buildfile

I am new to Ant and any help will be appreciated.
What I want to do is:
<target name="run-tenantManagement" depends="jar"
description="Running TestNG Tests">
<if> ... SIMV3.1 env variable set
<property name="output.dir.name" value="tenantManagementV3"/>
<else>
<property name="output.dir.name" value="tenantManagement"/>
</if>
</target>
Basically I am setting one env variable
setenv SIMV3.1 true
I want to put a check in the Ant target if this variable is set and has value=true, then set output.dir.name to a particular value, else set it to another value.
Kindly help. I have googled through many Ant tutorials but everything seems ambiguous.
There's a few ways to do this, for example using an Ant <condition> task:
<property environment="env" />
<condition property="output.dir.name" value="tenantManagementV3"
else="tenantManagement">
<istrue value="${env.SIMV3.1}" />
</condition>
There are a number of other tests you can use and combine in the task, see Conditions for the list.
Also: I'd avoid using an environment variable name with an embedded dot - it won't work in all shells.

ant: how to compare contents of two files

I want to compare the contents of two files (say file1.txt,file2.txt) using ANT.
if files content are same then it should set some 'property' to true, if contents are not same then it should set the 'property' as false.
Can anyone suggest me any ANT task that can do this.
Thanks in advance.
You can use something like:
<condition property="property" value="true">
<filesmatch file1="file1"
file2="file2"/>
</condition>
This will set the property only if the files are the same.
You can then check for the property, using
<target name="foo" if="property">
...
</target>
This is available in ant, with no added dependency, see here for other conditions.
I am in the same situation to compare two files and switch into different targets depending on files match or files mismatch...
Heres the code:
<project name="prospector" basedir="../" default="main">
<!-- set global properties for this build -->
<property name="oldVersion" value="/code/temp/project/application/configs/version.ini"></property>
<property name="newVersion" value="/var/www/html/prospector/application/configs/version.ini"></property>
<target name="main" depends="prepare, runWithoutDeployment, startDeployment">
<echo message="version match ${matchingVersions}"></echo>
<echo message="version mismatch ${nonMatchingVersion}"></echo>
</target>
<target name="prepare">
<!-- gets true, if files are matching -->
<condition property="matchingVersions" value="true" else="false">
<filesmatch file1="${oldVersion}" file2="${newVersion}" textfile="true"/>
</condition>
<!-- gets true, if files are mismatching -->
<condition property="nonMatchingVersion" value="true" else="false">
<not>
<filesmatch file1="${oldVersion}" file2="${newVersion}" textfile="true"/>
</not>
</condition>
</target>
<!-- does not get into it.... -->
<target name="startDeployment" if="nonMatchingVersions">
<echo message="Version has changed, update gets started..."></echo>
</target>
<target name="runWithoutDeployment" if="matchingVersions">
<echo message="Version equals, no need for an update..."></echo>
</target>
The properties are correct and change on changing file contents.
the task for nonMatchingVersions never gets started.

How to set an Ant property only if it is unset

I can't figure out how to set an Ant property on the condition that it has not been set (i.e it is not defined in the properties file and should automatically default).
So far, I only have the following code:
<condition property="core.bin" value="../bin">
<isset property="core.bin"/>
</condition>
But this only seems to work if the value is defined in a <property> tag.
Does anyone know how to conditionally set a property for the first time if it currently unset?
You simply can set the property with the property-task. If the property is already set, the value is unchanged, because properties are immutable.
But you can also include 'not' in your condition:
<condition property="core.bin" value="../bin">
<not>
<isset property="core.bin"/>
</not>
</condition>
Ant does this by default; if the property is already set; setting it again has no effect:
<project name="demo" default="demo">
<target name="demo" >
<property name="aProperty" value="foo" />
<property name="aProperty" value="bar" /> <!-- already defined; no effect -->
<echo message="Property value is '${aProperty}'" /> <!-- Displays 'foo' -->
</target>
</project>
Gives
/c/scratch> ant -f build.xml
Buildfile: build.xml
demo:
[echo] Property value is '${aProperty}'
BUILD SUCCESSFUL
Total time: 0 seconds
/c/scratch> ant -f build.xml
Buildfile: build.xml
demo:
[echo] Property value is 'foo'
BUILD SUCCESSFUL
Properties cannot be redefined; to do this you need to use something like the variable task from ant-contrib.
The easiest way to do what you want:
<if>
<not>
<isset property="your.property"/>
</not>
<then>
<property name="your.property" value="your.value"/>
</then>
</if>
There is support of using 'else' within : https://ant.apache.org/manual/Tasks/condition.html to serve your exact purpose.
else
The value to set the property to if the condition evaluates to false. By default the property will remain unset. Since Apache Ant 1.6.3
So change to :
<condition property="core.bin" else="../bin">
<isset property="core.bin"/>
</condition>
Properties in Ant are immutable. After defined they cannot be changed.
But the Ant Contrib package offers the variable task. It works like a property but the values can be modified and unset.
Exmaple from the variable task documentation:
<var name="x" value="6"/>
<if>
<equals arg1="${x}" arg2="6" />
<then>
<var name="x" value="12"/>
</then>
</if>
<echo>${x}</echo> <!-- will print 12 -->

Can I make the Ant copy task OS-specific?

I have an Ant script that performs a copy operation using the 'copy' task. It was written for Windows, and has a hardcoded C:\ path as the 'todir' argument. I see the 'exec' task has an OS argument, is there a similar way to branch a copy based on OS?
I would recommend putting the path in a property, then setting the property conditionally based on the current OS.
<condition property="foo.path" value="C:\Foo\Dir">
<os family="windows"/>
</condition>
<condition property="foo.path" value="/home/foo/dir">
<os family="unix"/>
</condition>
<fail unless="foo.path">No foo.path set for this OS!</fail>
As a side benefit, once it is in a property you can override it without editing the Ant script.
The previously posted suggestions of an OS specific variable will work, but many times you can simply omit the "C:" prefix and use forward slashes (Unix style) file paths and it will work on both Windows and Unix systems.
So, if you want to copy files to "C:/tmp" on Windows and "/tmp" on Unix, you could use something like:
<copy todir="/tmp" overwrite="true" >
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</copy>
If you do want/need to set a conditional path based on OS, it can be simplified as:
<condition property="root.drive" value="C:/" else="/">
<os family="windows" />
</condition>
<copy todir="${root.drive}tmp" overwrite="true" >
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</copy>
You could use the condition task to branch to different copy tasks... from the ant manual:
<condition property="isMacOsButNotMacOsX">
<and>
<os family="mac"/>
<not>
<os family="unix"/>
</not>
</and>
Declare a variable that is the root folder of your operation. Prefix your folders with that variable, including in the copy task.
Set the variable based on the OS using a conditional, or pass it as an argument to the Ant script.
You can't use a variable and assign it depending on the type? You could put it in a build.properties file. Or you could assign it using a condition.
Ant-contrib has the <osfamily /> task. This will expose the family of the os to a property (that you specify the name of). This could be of some benefit.

Resources