Can i set an variable in available tag like this?
<available file="${inf.root}/schema_params/#{componame}-schema.sql"
type="file"
variable="schema.file" />
because when i use property instead of variable in available tag, Its value is immutable. But i want to change it at run time.Below is my code.i want to copy 1 file checking through my component list. if the file exists, i have to copy and move it. else i have to skip the logic. But whats happening is, if i dont use this code,
<var name="schema.params.file" unset="true"/>
<property name="schema.params.file" value="false"/>
<var name="scripts.dir" unset="true"/>
<property name="scripts.dir" value="false"/>
in the first iteration if schema.params.file,scripts.dir is set to true if files exist, it is not overided in the next iteration even though if file doenot exist. so i have added above code.but now always the values are set to false again by above code. how can i overcome the issue of overiding these 2 schema.params.file,scripts.dir in every iteration?
<for list="${t1.#{componentname}}" param="installableid" delimiter="${line.separator}">
<sequential>
<available file="${infinys.root}/schema_params/#{componentname}-schema_params.sql"
type="file"
property="schema.params.file" />
<available file="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts"
type="dir" property="scripts.dir"/>
<if>
<and>
<equals arg1="true" arg2="${schema.params.file}" />
<equals arg1="true" arg2="${scripts.dir}" />
</and>
<then>
<copy file="${infinys.root}/schema_params/#{componentname}-schema_params.sql"
todir="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts"
failonerror="false" />
<move file="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts/#{componentname}-schema_params.sql"
tofile="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts/schema_params.sql"
failonerror="false"/>
<chmod file="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts/schema_params.sql" perm="775"/>
<var name="schema.params.file" unset="true"/>
<property name="schema.params.file" value="false"/>
<var name="scripts.dir" unset="true"/>
<property name="scripts.dir" value="false"/>
</then>
</if>
</sequential>
</for>
Can i set an variable in available tag like this?
Yes, you can.
Macro names are changed with each iteration. The <var/> task is simply a way to unset and reset a property in Ant. It's part of the Ant-Contrib project. You don't need to unset and reset the property:
<var name="schema.params.file" unset="true"/>
<property name="schema.params.file" value="false"/>
You could do this in a single statement:
<var name="schema.params.file" value="false"/>
Their use is highly discouraged since it breaks Ant's immutable property idea. However, I've find that I too use <var/> a lot when going through <for/> loops and sometimes <macrodef>. Newer versions of Ant allow you to localize properties, so I suspect the <var/> task will soon no longer be needed.
Another thing which may make things a bit easier is that you can use <if/> tests with <available/>
<if>
<then>
<and>
<available file="${infinys.root}/schema_params/#{componentname}-schema_params.sql"
type="file"/>
<available file="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts"
type="dir"/>
</and>
<sequencial>
....
</sequential/>
</then>
</if>
Doing this may make your code a bit cleaner and easier to understand. It will also eliminate the need to unset properties in the first place.
Ant doesn't allow overwriting properties. You still can use macrodef but that's another story (see How to over-write the property in Ant?).
What you can do is move the internals of your cycle to the separate target like (can't see why you copy a file to another location and immediately move it to another another location, so I just replaced this copy-move with one copy)
<target name="cycle-body">
<available file="${schema.params.file.name}" type="file" property="schema.params.file" />
<available file="${scripts.dir.name}" type="dir" property="scripts.dir"/>
<if>
<and>
<equals arg1="true" arg2="${schema.params.file}" />
<equals arg1="true" arg2="${scripts.dir}" />
</and>
<then>
<copy file="${schema.params.file.name}"
tofile="${scripts.dir.name}/schema_params.sql" failonerror="false"/>
<chmod file="${scripts.dir.name}/schema_params.sql" perm="775"/>
</then>
</if>
</target>
and call it like
<for list="${t1.#{componentname}}" param="installableid" delimiter="${line.separator}">
<antcall target="cycle-body">
<param name="schema.params.file.name" value="${infinys.root}/schema_params/#{componentname}-schema_params.sql" />
<param name="scripts.dir.name" value="${stage.dir}/#{componentname}/#{installableid}/schema/install/scripts" />
</acntcall>
</for>
Related
I have more than 30 odx-d files (odx-d is just xml file with different extension).
All files have common tags:
<DOC-REVISION>
<REVISION-LABEL>01.02.03-04</REVISION-LABEL>
<STATE>RELEASE</STATE>
<DATE>2018-11-14T16:26:00+01:00</DATE>
</DOC-REVISION>
At every release I need to change these values in all files.
Note: Manipulation using Java is not possible as while build just making zip of all these files not using Java to manipulate these files.
Please suggest a way to have one file (any file type you suggest) where I can have these values and place holders for the tags in all these files.
Thanks.!
This is doable with the following steps:
replace the common tag values with placeholders e.g. #revision#,
#state#, #date#
copy each file to a temporary location
perform the replacements in the copied files using a <replace file="${dest.file}"> task with nested <replacefilter .../> elements
zip the transformed files in the temporary location
For example, using a template file "template.xml" like this:
<DOC-REVISION>
<REVISION-LABEL>#revision#</REVISION-LABEL>
<STATE>#state#</STATE>
<DATE>#date#</DATE>
</DOC-REVISION>
you can set the real values with this ant target (skipping the zip part):
<target name="test">
<property name="my.revision" value="01.02.03-04"/>
<property name="my.state" value="RELEASE"/>
<tstamp>
<format property="my.date" pattern="yyyy-MM-dd hh:mm z"/>
</tstamp>
<property name="template.file" value="./template.xml"/>
<property name="dest.file" value="./doc.odx"/>
<delete file="${dest.file}" quiet="true"/>
<copy toFile="${dest.file}" file="${template.file}"/>
<replace file="${dest.file}">
<replacefilter token="#revision#" value="${my.revision}"/>
<replacefilter token="#state#" value="${my.state}"/>
<replacefilter token="#date#" value="${my.date}"/>
</replace>
</target>
Solution for multiple files.
Replace values with placeholders #revision#, #state#, #date# and place into template folder.
Perform the copy operation with filterset from template to dest directory.
Example:
Template dir: 'fromDir', destination: 'toDir'
1) Template files:
<DOC-REVISION>
<REVISION-LABEL>#revision#</REVISION-LABEL>
<STATE>#state#</STATE>
<DATE>#date#</DATE>
</DOC-REVISION>
2) Declare properties and perform test target operation.
<!-- Properties -->
<property name="version" value="01.02.03-04" />
<property name="state" value="RELEASE" />
<tstamp>
<format property="now" pattern="yyyy-MM-dd'T'HH:mm:ss.SSSXXX"/>
</tstamp>
<!-- Target -->
<target name="test">
<copy todir="${toDir}">
<fileset dir="${fromDir}" />
<filterset>
<filter token="revision" value="${version}" />
<filter token="state" value="${state}" />
<filter token="date" value="${now}" />
</filterset>
</copy>
</target>
Thanks!
I have a very little knowledge about writing build files using ant targets.
the problem i am facilng is i want to have a build file which should import other ant build file if the given condition is satisfied.
For suppose here in the below code if ${myresult} is set to true then the postgreswebtest.xml should be used else mysqlwebtest.xml should be used.
So i tried to achieve this with the following code.
<?xml version="1.0" encoding="utf-8" ?>
<project name="webtest" default="build" basedir=".">
<target name="build">
<property name="DBTYPE" value="${arg0}" />
<echo message="${DBTYPE}" />
<condition property="myresult">
<equals arg1="${DBTYPE}" arg2="postgres" />
</condition>
<echo message="${myresult}" />
<if>
<isset property="myresult"/>
<then>
<import file="postgreswebtest.xml" />
</then>
<else>
<import file="mysqlwebtest.xml" />
</else>
</if>
</target>
</project>
but when i execute this code getting the following error.
BUILD FAILED:
webtest.xml:21: import only allowed as a top-level task
Could someone please help me out with the solution
You can use ant ant task instead which acts as if it is imporing supplied build file. Refer to : https://ant.apache.org/manual/Tasks/ant.html for more details.
With ant you can provide default target to run as well.
With this approach it will conditional evaluate and import file inside your 'build' target.
<if>
<isset property="myresult"/>
<then>
<ant antfile="postgreswebtest.xml" />
</then>
<else>
<ant antfile="mysqlwebtest.xml" />
</else>
</if>
I have a webapp to be ran on Tomcat6/JbossAS 5 and, for versioning purposes, I have several AND targets that will perform a set of operations to define a constant with version number and build datetime.
The targets perform the following:
Delete the Release.java
Copy the Release.template to Release.java with the versioning info properly set as a constant (public static final String)
The thing is that, the constant references are replaced on the code before compilation. For instance, where I have
log.debug("Release: " + Release.info);
I can see, using java decompiler, the following (let's assume that "TO_BE_DEFINED" is the initial value for Relase.info):
log.debug("Release: TO_BE_DEFINED");
The targets are the following:
<target name="build-config" >
<!-- config -->
<property name="project.name" value="MY PROJECT" />
<property name="release.prefix" value="MPROJECT" />
<property name="release.num" value="1.0" />
<property name="release.info.file.path" value="org/my/project/Release" />
<tstamp>
<format property="release.date" pattern="yyyy-MM-dd HH:mm:ss z" />
</tstamp>
<!-- end config -->
<property name="release.version" value="${release.prefix}-${release.num}" />
<property name="release.info" value="${release.version} ${release.date}" />
</target>
<target name="build-replace">
<filter token="release.info" value="${release.version} ${release.date}" />
<delete file="${src.dir}/${release.info.file.path}.java" />
<copy file="${src.dir}/${release.info.file.path}.template" tofile="${src.dir}/${release.info.file.path}.java" filtering="true" />
</target>
<target name="build-myproj-1.0.jar" depends="init,buil-config,build-replace,compile">
<mkdir dir="${dist.dir}"/>
<jar compress="true" jarfile="${dist.dir}/MPROJECT-1.0.jar">
<fileset dir="${build.classes.dir}"
excludes="META-INF/*.*, WEB-INF/classes/*.xml"
includes="**/*.class"
/>
<manifest>
<section name="${project.name}">
<attribute name="Release-Version" value="${release.version}" />
<attribute name="Release-Date" value="${release.date}" />
</section>
</manifest>
</jar>
</target>
and my class is defined as
public abstract class Release {
/** Release info */
public static final String INFO = "TO_BE_DEFINED";
}
I understand that this may be a little bit confusing and if I'm missing some information please feel free to ask
Compile-time constants are replaced in client code when the client code is compiled.
To get the client code to pick up the new value of the constant, either recompile everything, replace the field with a getter, or use one of the strategies from this question
How would you write a build.xml file, using neither custom code nor external dependencies (such as a shell script), that:
Generates a build number of the form major.minor.revision (e.g., 01.02.34).
Auto-increments the revision on each compile of the source code.
Auto-increments the minor version on each execution of a dist(ribution) task.
Additionally:
Provides an option to increment the major number.
Provides an option to increment the minor number.
Whenever the major number is incremented, the minor and revision numbers are set to 0.
Whenever the minor number is incremented, the revision number is set to 0.
Bonus:
Creates a variable based on the git revision number (like a subversion revision number).
Clarification:
Automatic checkout (or commit) is not required.
Integration with Subversion is not desired.
Thank you for any examples. Here are some related sites that describe how to perform similar tasks:
Create a Build Number with Ant.
Using the BuildNumber Ant task.
Ant and Build Version Numbers.
The build_info.properties file:
build.major.number=00
build.revision.number=00
build.minor.number=00
The build.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="current-number">
<property file="build_info.properties"/>
<property name="build.number" value="${build.major.number}.${build.minor.number}.${build.revision.number}"/>
<target name="current-number">
<echo>Current build number:${build.number}</echo>
</target>
<target name="compile">
<antcall target="revision"></antcall>
</target>
<target name="dist">
<antcall target="minor"></antcall>
</target>
<target name="revision">
<propertyfile file="build_info.properties">
<entry key="build.revision.number" type="int" operation="+" value="1" pattern="00"/>
</propertyfile>
</target>
<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>
<target name="major">
<propertyfile file="build_info.properties">
<entry key="build.major.number" type="int" operation="+" value="1" pattern="00"/>
<entry key="build.minor.number" type="int" value="0" pattern="00"/>
<entry key="build.revision.number" type="int" value="0" pattern="00"/>
</propertyfile>
</target>
<target name="all">
<propertyfile file="build_info.properties">
<entry key="build.major.number" type="int" operation="+" value="1" pattern="00"/>
<entry key="build.minor.number" type="int" operation="+" value="1" pattern="00"/>
<entry key="build.revision.number" type="int" operation="+" value="1" pattern="00"/>
</propertyfile>
</target>
</project>
This solution does increment minor or revision number automatically if a compile or a dist target has been selected. The incrementation can be switched off if one of the following properties has been set:
-Dno.increment.minor=true
-Dno.increment.revision=true
If the property inc.major has been set, then the major number will be incremented and the other both values will be set to zero. The SHA-1 checksum is being calculated by the textual representation of the version file.
By the way: If would have been allowed, you could create your own ant task in java script, which is included in JDK 6.
Now here's the ant file
<?xml version="1.0" encoding="UTF-8"?>
<project name="Numbers" default="dist" basedir=".">
<property name="version.file" location="${basedir}/version.properties"/>
<target name="inc.revision.properties" unless="no.increment.revision">
<propertyfile file="${version.file}">
<entry key="minor.number" default="00" operation="=" pattern="00" type="int"/>
<entry key="major.number" default="00" operation="=" pattern="00" type="int"/>
<entry key="build.number" default="00" operation="+" pattern="00" type="int"/>
</propertyfile>
</target>
<target name="inc.minor.properties" unless="no.increment.minor">
<propertyfile file="${version.file}">
<entry key="minor.number" default="00" operation="+" pattern="00" type="int"/>
<entry key="major.number" default="00" operation="=" pattern="00" type="int"/>
<entry key="build.number" value="00" operation="=" type="int"/>
</propertyfile>
</target>
<target name="inc.major" if="inc.major">
<property name="no.increment.minor" value="true" />
<property name="no.increment.revision" value="true" />
<propertyfile file="${version.file}">
<entry key="minor.number" value="00" operation="=" pattern="00" type="int"/>
<entry key="major.number" default="00" operation="+" pattern="00" type="int"/>
<entry key="build.number" value="00" operation="=" pattern="00" type="int"/>
</propertyfile>
<load.version.info/>
</target>
<target name="inc.minor" depends="inc.major,inc.minor.properties">
<property name="no.increment.revision" value="true"/>
<load.version.info/>
</target>
<target name="inc.revision" depends="inc.major,inc.revision.properties">
<load.version.info/>
</target>
<macrodef name="load.version.info">
<sequential>
<property file="${version.file}"/>
<checksum file="${version.file}" property="sha1.number" algorithm="SHA" format="CHECKSUM"/>
<echo>Version: ${major.number}.${minor.number}.${build.number}</echo>
<echo>SHA1: ${sha1.number}</echo>
</sequential>
</macrodef>
<target name="compile" depends="inc.revision" description="Compile Task"/>
<target name="dist" depends="inc.minor, compile" description="Dest Task"/>
</project>
Build Process
build_info.properties will be created during build in your project
folder You could write all information about your build in this file.
Like build number, major and minor numbers of release, timestamp, and revision number.
Your build script can
modify these values how ever your
want
After the build was successfull commit the file 'build_info.properties' back to the
repository
During Development
After first build the file build_info.properties will be placed in the repository.
You can change and commit any number (major, minor, build numbers) by your self when ever you want, or increase it automatically during build like build.number in the example below.
svnant Example
Using svnant 1.3.0:
<target name="checkout">
<echo>Checking out revision ${param_SubProjectSvnREV} of project: ${param_SubProjectSvnName}</echo>
<svn username="${svnant.repository.user}" password="${svnant.repository.passwd}">
<checkout url="${svnant.latest.url}/${param_SubProjectSvnName}/" revision="${param_SubProjectSvnREV}" destPath="${all.projects.dir}/${param_SubProjectDirName}" />
<info target="${all.projects.dir}/${param_SubProjectDirName}" ></info>
</svn>
<propertyfile file="${all.projects.dir}/${param_SubProjectDirName}/build_info.properties" comment="Modify build numbers in a properties file.">
<entry key="build.number" type="int" operation="+" value="1" pattern="00"/><!--increment it here -->
<entry key="build.revision" type="string" value="${svn.info.rev}"/>
<entry key="build.major.number" default="01"/><!-- can do some logic here to increase the values, or write value from somewhere else-->
<entry key="build.minor.number" default="01"/><!-- can do some logic here to increase the values, or write value from somewhere else-->
</propertyfile>
</target>
<target name="compile" depends="checkout">
<property file="${all.projects.dir}/${param_SubProjectDirName}/build_info.properties" />
<mkdir dir="${release.name}/${param_SubProjectDirName}/${build.major.number}.${build.minor.number}.${build.number}" />
<!-- compile it to the new folder, an so on... -->
<!-- after all, if the build wass successfull, commit the file 'build_info.properties' back to repository -->
</target>
The easiest way of doing this is to change the problem. Instead of making the Any build do this for you, have whatever process that you're calling Ant calculate what the version number should be, and then pass that in as a property e.g.
ant -Dbuild.version=1.2.3
This has the flexibility of whatever build you're working with being able to take its cue from whatever, such as the SVN revision, the current date and time, or whatever.
ant -Dbuild.version=svnversion .
ant -Dbuild.version=date +"%Y%m%d%H%D"
ant -Dbuild.version=${major}.svnversion ..date +"%Y%m%d%H%D"
etc. You can get pretty comprehensive if you want.
If you want to have an ever incrementing number, then you can store it in a file and then pass that in at compile time. For example, you can do:
VER=cat build.version
VER=$((VER+1))
echo $VER > build.version
Lastly, if you really want this to be in the build.xml file, the best thing to do is have a separate task to execute the increment-and-build option and fork off a nested ant build with your 'main' target. You'd thus end up with
ant -> ant -Dbuild.version=1.2.3.4 -> ...
In other words, given your build.xml with a (current) default of 'build', then change it to 'version' and have the ant 'version task do the calculation followed by a nested call to and build.
Implementation is left as an exercise to the reader, as is translating the approach to a non-UNIX platform.
This was a while ago, so this is from memory:
I build a custom CruiseControl.Net labeller block that ticked up the build number on each build. It maintained an XML file with all 4 components of the version number and identified each project by name (so it could support multiple projects).
The four values it generated get passed to the build process (nAnt, in our case), which had the responsibility of tweaking all the AssemblyInfo.cs files to reflect the proper build number.
Edited to note: The only value that get automatically ticked up was the build number. Major/Minor version numbers were specified in the CC.Net project configuration. The build number restarted at 0001 for each change in major or minor revision number (e.g., if you went from version 7.1 to version 7.3, for instance, the 7.1 build might be at build number 783, but the first 7.3 build started with build number 1; the next 7.1 build would be build 784.
Change version numbers merely required tweaking 1 setting the CC.Net config file.
In my project i don’t increase the minor and major number automatically. We set it from our global build properties. Like that:
<entry key="build.major.number" value="${global.release.major}"></entry>
<entry key="build.minor.number" value="${global.release.minor}"></entry>
That’s because they will be changed for releases (not for test or other builds) and committed together with other sources (we have be able to build some old or branch version).
But if you want to increase the minor number, you can do it like the build number in my example.
<entry key="build.major.number" type="int" operation="+" default="1" pattern="00"/>
We can use conditions to check if we should increase the micro,minor and major version.
Increase minor if micro is 9, and so on.
<target name="increaseBuildNumber" depends="increase.micro, increase.minor, increase.major" description="Increase Build Number"/>
<target name="increase.micro" if ="microNotEquals9">
<propertyfile file="build.properties">
<entry key="micro.number" default="0" operation="+" pattern="0" type="int"/>
</propertyfile>
</target>
<target name="increase.minor" if = "microEquals9andMinorNotEquals9">
<propertyfile file="build.properties">
<entry key="minor.number" default="0" operation="+" pattern="0" type="int"/>
<entry key="micro.number" value="0" operation="=" pattern="0" type="int"/>
</propertyfile>
</target>
<target name="increase.major" if = "microAndMinorEquals9" >
<propertyfile file="build.properties">
<entry key="major.number" default="0" operation="+" pattern="0" type="int"/>
<entry key="minor.number" value="0" operation="=" pattern="0" type="int"/>
<entry key="micro.number" value="0" operation="=" pattern="0" type="int"/>
</propertyfile>
</target>
<condition property="minorEquals9">
<equals arg1="${minor.number}" arg2="9"/>
</condition>
<condition property="microEquals9andMinorNotEquals9">
<and>
<equals arg1="${micro.number}" arg2="9"/>
<not><equals arg1="${minor.number}" arg2="9"/></not>
</and>
</condition>
<condition property="microAndMinorEquals9">
<and>
<equals arg1="${micro.number}" arg2="9"/>
<equals arg1="${minor.number}" arg2="9"/>
</and>
</condition>
<condition property="microNotEquals9">
<not><equals arg1="${micro.number}" arg2="9"/></not>
</condition>
I have a property, app.version, which is set to 1.2.0 (and, of course, always changing) and need to create zip file with name "something-ver-1_2_0". Is this possible?
You can use the pathconvert task to replace "." with "_" and assign to a new property:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<property name="app.version" value="1.2.0"/>
<pathconvert property="app.version.underscore" dirsep="" pathsep="" description="Replace '.' with '_' and assign value to new property">
<path path="${app.version}" description="Original app version with dot notation" />
<!--Pathconvert will try to add the root directory to the "path", so replace with empty string -->
<map from="${basedir}" to="" />
<filtermapper>
<replacestring from="." to="_"/>
</filtermapper>
</pathconvert>
<echo>${app.version} converted to ${app.version.underscore}</echo>
</project>
Another approach is to filter the version number from a file to a property using a regular expression, as suggested in this example:
<loadfile srcfile="${main.path}/Main.java" property="version">
<filterchain>
<linecontainsregexp>
<regexp pattern='^.*String VERSION = ".*";.*$'/>
</linecontainsregexp>
<tokenfilter>
<replaceregex pattern='^.*String VERSION = "(.*)";.*$' replace='\1'/>
</tokenfilter>
<striplinebreaks/>
</filterchain>
</loadfile>
Since the property app.version is always changing i assume you don't want to hard code it into the properties files, rather pass it when you do the build. Further to this answer, you can try the following on the command line;
ant -f build.xml -Dapp.version=1.2.0
changing app.version to the one required then.
Edit:
Understood better your question from the feedback. Unfortunately ant does not have string manipulation tasks, you need to write you own task for this. Here is a close example.
It's possible using the zip task
<zip zipfile="something-ver-${app.version}.zip">
<fileset basedir="${bin.dir}" prefix="bin">
<include name="**/*" />
</fileset>
<fileset basedir="${doc.dir}" prefix="doc">
<include name="**/*" />
</fileset></zip>
For more information about the zip task: http://ant.apache.org/manual/Tasks/zip.html
Properties can't be changed but antContrib vars (http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) can.
Here is a macro to do a find/replace all on a var:
<macrodef name="replaceVarText">
<attribute name="varName" />
<attribute name="from" />
<attribute name="to" />
<sequential>
<local name="replacedText"/>
<local name="textToReplace"/>
<local name="fromProp"/>
<local name="toProp"/>
<property name="textToReplace" value = "${#{varName}}"/>
<property name="fromProp" value = "#{from}"/>
<property name="toProp" value = "#{to}"/>
<script language="javascript">
project.setProperty("replacedText",project.getProperty("textToReplace").split(project.getProperty("fromProp")).join(project.getProperty("toProp")));
</script>
<ac:var name="#{varName}" value = "${replacedText}"/>
</sequential>
</macrodef>
Then call the macro like:
<ac:var name="newFileName" value="${app.version}"/>
<current:replaceVarText varName="newFileName" from="." to="_" />
<echo>Filename will be ${newFileName}