Use ANT to update build number and inject into source code - ant

In my build.xml file I am incrementing a build version number in a property file like so:
<target name="minor">
<propertyfile file="build_info.properties">
<entry key="build.minor.number" type="int" operation="+" value="1" pattern="00" />
<entry key="build.revision.number" type="int" value="0" pattern="00" />
</propertyfile>
</target>
I also have similar entries for the major and revision. (from Build numbers: major.minor.revision)
This works great. Now I would like to take this incremented build number and inject it into my source code:
//Main.as
public static const VERSION:String = "#(#)00.00.00)#";
By using:
<target name="documentVersion">
<replaceregexp file="${referer}" match="#\(#\).*#" replace="#(#)${build.major.number}.${build.minor.number}.${build.revision.number})#" />
</target>
Now this sorta works. It does indeed replace the version but with the outdated version number. So whenever I run the ANT script the build_info.properties is updated to the correct version but my source code file is using the pre updated value.
I have echoed to check that indeed I am incrementing the build number before I call the replace and I have noticed that echoing:
<echo>${build.minor.number}</echo>
//After updating it still shows old non updated value here but the new value in the property file.
So is there a way to retrieve the updated value in the property file so I can use it to inject into my source code?
Cheers

So after spending hours not being able to solve this, I post this question and then figure it out 20 minutes later.
The problem was I had this at the top of my build file:
<property file="build_info.properties"/>
I guess it was due to scoping and that properties are immutable thus I was never able to update the value. Removing that line and then adding the following got it working perfectly:
<target name="injectVersion">
<property file="build_info.properties"/>
<replaceregexp file="${referer}" match="#\(#\).*#" replace="#(#)${build.major.number}.${build.minor.number}.${build.revision.number})#" />
</target>

Why not just use <buildnumber/>?

Project used to increment build number in build.properties file
file parameters:
version.number=
build.number=
if changes version.number then build.number starts from 1
====================================================================== -->
<property name="versionFileName" value="build.properties" />
<property file="${versionFileName}" />
<property name="currentVersion" value="0.1.37"/>
<target name="calculate.version.build">
<script language="javascript">
<![CDATA[
var currentVersion = project.getProperty("currentVersion");
var oldVersion = project.getProperty("version.number");
var buildNumber = project.getProperty("build.number");
if (!currentVersion.equals(oldVersion)){
project.setProperty("currentBuild", 1);
} else {
var newBuildNumber = ++buildNumber;
project.setProperty("currentBuild", newBuildNumber);
}
]]>
</script>
</target>
<target name="update.version.build" depends="calculate.version.build">
<propertyfile file="${versionFileName}">
<entry key="build.number" type="int" operation="=" value="${currentBuild}" />
<entry key="version.number" type="string" operation="=" value="${currentVersion}" />
</propertyfile>
<echo message="New version: ${currentVersion}.${currentBuild}" />
</target>

Related

Ant: If property contains certain string, change the name of the property

I am trying to check a folder's name, and if it contains a certain string, I want that folder path to be changed.
So far I came up with this:
<property name="component.release.dir" value="${install.dir}/${component.name}" />
<!-- Check if the component is a part of projectL -->
<condition property="projectLFolderSpotted">
<matches pattern="projectL" string="${component.release.dir}"/>
<!-- if so, put the component in an appropriate folder -->
<property name="component.release.dir" value="${install.dir}/projectL/${component.name}" />
<echo message="projectL component has been detected, and moved accordingly!"/>
</condition>
But I get the following error:
condition doesn't support the nested "property" element.
Is there a way to achieve this?
Thanks in advance.
Properties in ANT are immutable, once they're assigned a value it doesn't change.
Here's how I'd suggest you do it:
<project name="demo" default="build">
<property name="release.dir.seed" location="build/helloworld"/>
<condition property="release.dir" value="build/found/helloworld" else="build/notfound/helloworld">
<contains string="${release.dir.seed}" substring="helloworld"/>
</condition>
<target name="build">
<echo message="Result: ${release.dir}"/>
</target>
</project>

ant build version with leading zeros

I want my version numbers of the installer files to be like installer-02.
I have the following entry in <entry key="build.number" type="int" value="2" />
How to achieve this.
You can specify pattern for int type when you add entry to property file http://ant.apache.org/manual/Tasks/propertyfile.html.
<propertyfile
file="my.properties"
comment="My properties">
<entry key="build.number" type="int" value="2" pattern="00"/>
</propertyfile>
<property file="my.properties"/>
<echo message="build.number : ${build.number}"/>
Please note with above eg, it will prefix build # with 0 for values from 0-9.

How can I make an ant prompt use the default value if not entered within a given time?

Many ant scripts I write use a default value, and these default values are almost exclusive. I.e. only occasionally will I want to run it without the default values.
A lot of times, these scripts take enough time that it makes sense to go do something else while they run, like getting coffee or using the Little Developer's Room. Of course, if there's a prompt on it, and you forgot it, well, you're SOL.
Is there any way I can put a timeout on the prompt so if it isn't entered in, oh let's say 30 seconds, that it just accepts the default value so that when I get back to my workstation I have my war/jar/whatever ready to go? Something like
<input addproperty="branch.tag"
defaultvalue="dev"
timeout="30000">
Which branch would you like to build?
</input>
Now obviously this timeout feature doesn't exist, but you get the idea of what I'm trying to accomplish.
Option 1: Configure build to run automated or interactive
Rather than timing out the input prompts, you could configure the build to run fully automated by supplying the default input values in a properties file.
default.properties
Which\ branch\ would\ you\ like\ to\ build?=dev
To switch between interactive and automated builds, the type of input handler to use could be specified when invoking Ant:
Automated build
$ ant -Dhandler.type=propertyfile
Interactive build
$ ant -Dhandler.type=default
The input handler would need to be specified using the nested <handler> element.
<input addproperty="branch.tag" defaultvalue="dev"
message="Which branch would you like to build?">
<handler type="${handler.type}" />
</input>
The last step is to specify the properties file for the PropertyFileInputHandler by defining the ant.input.properties system property.
Linux
export ANT_OPTS=-Dant.input.properties=default.properties
Option 2: Use AntContrib Trycatch combined with Parallel in a macrodef
<taskdef name="trycatch" classname="net.sf.antcontrib.logic.TryCatchTask">
<classpath>
<pathelement location="/your/path/to/ant-contrib.jar"/>
</classpath>
</taskdef>
<macrodef name="input-timeout">
<attribute name="addproperty" />
<attribute name="defaultvalue" default="" />
<attribute name="handlertype" default="default" />
<attribute name="message" default="" />
<attribute name="timeout" default="30000" />
<text name="text" default="" />
<sequential>
<trycatch>
<try>
<parallel threadcount="1" timeout="#{timeout}">
<input addproperty="#{addproperty}"
defaultvalue="#{defaultvalue}"
message="#{message}">
<handler type="#{handlertype}" />
#{text}
</input>
</parallel>
</try>
<catch>
<property name="#{addproperty}" value="#{defaultvalue}" />
</catch>
</trycatch>
</sequential>
</macrodef>
<target name="test-timeout">
<input-timeout addproperty="branch.tag" defaultvalue="dev"
message="Which branch would you like to build?"
timeout="5000" />
<echo message="${branch.tag}" />
</target>
Option 3: Write a custom Ant task
Implementation left as an exercise to the reader.

How to pass paramters by refrence in ant

Hi all this is my code for target calling.
<target name="abc">
<var name="x" value="10"/>
<antcall target="def"/>
<!--Again Access The value of x here and also change it here-->
</target>
<target name="def">
<!--Access The value of x here and also change it here-->
</target>
and also i want to access this X in other build file,is there any way
This is not possible with ant. In an properties are immutable and cannot be reset. The var task from ant contrib can be used to override values, but should be used sparingly.
You could use a temporary file to achieve what you want. But probably you are trying something weird, which can be solved in a different way.
This would also work across buildfiles if they have access to the property file.
<target name="abc">
<var name="x" value="10"/>
<antcall target="def"/>
<!--Again Access The value of x here and also change it here-->
<var unset="true" file="myproperty.properties" /> <!-- read variable from property file-->
</target>
<target name="def">
<echo file="myproperty.properties" append="false">x=12</echo> <!-- create a new propertyfile-->
</target>
For the sake of justice, there is a hack that allows to alter ant's immutable properties without any additional libs (since java 6):
<scriptdef name="propertyreset" language="javascript"
description="Allows to assing #{property} new value">
<attribute name="name"/>
<attribute name="value"/>
project.setProperty(attributes.get("name"), attributes.get("value"));
</scriptdef>
Usage:
<target name="abc">
<property name="x" value="10"/>
<antcall target="def"/>
</target>
<target name="def">
<propertyreset name="x" value="11"/>
</target>
As #oers mentioned, this should be used with care after all canonical approaches proved not to fit.
It is difficult to suggest further without knowing the goal behind the question.

reloading properties after updating a property file

I'm trying to read a property after updating it using propertyfile task. Something like
<property file="test.properties" />
<echo>before :: ${modules}</echo>
<propertyfile file="test.properties" >
<entry key="modules" type="string" operation="+" value="foo" />
</propertyfile>
<property file="${status.path}/test.properties" />
<echo>after :: ${modules}</echo>.
It doesn't seem to load the second time. But the property file is updated.
You can invoke a new ant runtime with the antcall task that ignores the properties of your main target runtime - just make sure to include inheritAll="false"
<target name="main">
<property file="test.properties"/>
<echo>before :: ${modules}</echo>
<propertyfile file="test.properties">
<entry key="modules" type="string" operation="+" value="foo" />
</propertyfile>
<antcall target="second-runtime" inheritAll="false"/>
</target>
<target name="second-runtime">
<property file="${status.path}/test.properties" />
<echo>after :: ${modules}</echo>
</target>
antcall refrence
As sudocode already mentioned, in Core Ant properties are immutable - for good reasons.
With the unset task from Antelope Ant Tasks you're able to unset all properties set in a file with a one liner :
<unset file="test.properties"/>
afterwards
<propertyfile file="test.properties" >
<entry key="modules" type="string" operation="+" value="foo" />
</propertyfile>
will work.
Hint : the task works only for normal properties, not for xmlproperties.
But there's a simple workararound, simply use <echoproperties prefix="..." destfile="foo.properties"/> and afterwards <unset file="foo.properties"/>
If you don't want to use Antelope for that specific task only, you may write a macrodef or own task with similar features.
For this case, when whole properties file is loaded twice, I suggest using different prefixes for the first and second load. First load with aprefix attribute equal to first. Access the properties with this prefix, that is property foo will be accessible as first.foo. Then save the properties file and load again, but this time without a prefix. You will get modified properties in suitable place.
Without using the prefix the second load will do nothing, as ant prevents properties from overriding. Others pointed that already.
Ant properties are immutable - once set, they are fixed. So reloading the properties file will not refresh the value of a property already set.
this macro allow you to change the property value after fixed one
<macrodef name="set" >
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<script language="javascript">
<![CDATA[
project.setProperty("#{name}", "#{value}");
]]>
</script>
</sequential>
</macrodef>
you can create a new properties file and save the property in the new file.
Provide the reference of the file in the next line.
Done :)

Resources