I want to have my Ant project output a few properties as YAML file.
For example:
<property name="foo" value="aaa"/>
<property name="bar" value="bbb"/>
<property name="baz" value="ccc"/>
Is written to output.yml as
foo: aaa
bar: bbb
baz: ccc
Can anyone suggest a method that doesn't require external tools/libraries?
Ant has built in JavaScript, which you might try. See below for an illustration.
This uses <scriptdef> to create a task "props2yaml" that writes a set of properties to a file. I've not tried to generalise for characters needing escape sequences, etc.
<scriptdef name="props2yaml" language="javascript">
<attribute name="destfile"/>
<element name="propertyset" type="propertyset"/>
<![CDATA[
var destfile = attributes.get( "destfile" );
//var properties = project.getProperties( );
//var prop_names = properties.keySet( ).toArray( ).sort( );
var properties = elements.get( "propertyset" ).get( 0 ).getProperties( );
var prop_names = properties.stringPropertyNames( ).toArray( ).sort( );
var fw = new java.io.FileWriter( destfile );
for ( var i in prop_names ) {
fw.write( prop_names[i] + ': "' + properties.get( prop_names[i] ) + '"\n' );
}
fw.flush( );
fw.close( );
]]></scriptdef>
<property name="foo" value="aaa"/>
<property name="bar" value="bbb"/>
<property name="baz" value="ccc"/>
<props2yaml destfile="output.yml">
<propertyset>
<propertyref name="foo" />
<propertyref name="bar" />
<propertyref name="baz" />
</propertyset>
</props2yaml>
For me the output in this case is:
bar: "bbb"
baz: "ccc"
foo: "aaa"
You could preserve order by changing the scriptdef as you see fit.
The commented out lines show how to get a full list of all Ant properties in the project.
Related
How to write Ant pattern to get latest modified file with timestamp.
My Files are :
Testcases_Results_dd-mm-yyyy_hh_mm_ss.xlsx
Testcases_Results_dd-mm-yyyy_hh_mm_ss.xlsx
Testcases_Results_dd-mm-yyyy_hh_mm_ss.xlsx
In Jenkins i've configured in attachment as **/TestResults/Testcases_Results_*.xlsx
but i'm not getting latest file,it is picking all files.
if your latest file has highest lastmodifieddate then you can use
<last>
<sort>
<date xmlns="antlib:org.apache.tools.ant.types.resources.comparators"/>
<resources>
<fileset dir="/path/to/files/">
<include name="Testcases_Results_*" />
</fileset>
</resources>
</sort>
</last>
as mentioned here.
In another way you can define and use scriptdef like
<scriptdef name="getLatesFile" language="javascript">
<attribute name="result"/>
<element name="fileset" type="fileset"/>
<![CDATA[
fileset = elements.get("fileset").get(0);
scanner = fileset.getDirectoryScanner(project);
scanner.scan();
files = scanner.getIncludedFiles();
var latestDate = new Date(1970, 0, 1, 0, 0, 0);
for( j=0; j < files.length; j++) {
var filename = files[j];
var dateSuffix = filename.substring("Testcases_Results_".length, filename.indexOf(".xlsx"));
//dd-mm-yyyy_hh_mm_ss
var bits = dateSuffix.split(/\D/);
var date = new Date(bits[2], --bits[1], bits[0], bits[3], bits[4], bits[5]);
if(date > latestDate) {
latestDate = date;
self.project.setProperty( attributes.get("result"), filename );
}
}
]]>
</scriptdef>
<target name="init">
<getLatesFile result="latest_file">
<fileset dir="/path/to/files/">
<include name="Testcases_Results_*" />
</fileset>
</getLatesFile>
<echo>${latest_file}</echo>
</target>
I am using the below mentioned code to get the content of a specific tag, but when I am trying to execute it I am getting some extra data along with it, I don't understand why is it happening. Lets say if I search for title tag then I am getting " [echo] Title : <title>Unit Test Results</title>,Unit Test Results" this as result, but the problem is title only contains "<title>Unit Test Results</title>" why this extra ",Unit Test Results" thing is coming.
<project name="extractElement" default="test">
<!--Extract element from html file-->
<scriptdef name="findelement" language="javascript">
<attribute name="tag" />
<attribute name="file" />
<attribute name="property" />
<![CDATA[
var tag = attributes.get("tag");
var file = attributes.get("file");
var regex = "<" + tag + "[^>]*>(.*?)</" + tag + ">";
var patt = new RegExp(regex,"g");
project.setProperty(attributes.get("property"), patt.exec(file));
]]>
</scriptdef>
<!--Only available target...-->
<target name="test">
<loadfile srcFile="E:\backup\latest report\Report-20160523_2036.html" property="html.file"/>
<findelement tag="title" file="${html.file}" property="element"/>
<echo message="Title : ${element}"/>
</target>
The return value of RegExp.exec() is an array. From the Mozilla documentation on RegExp.prototype.exec():
The returned array has the matched text as the first item, and then
one item for each capturing parenthesis that matched containing the
text that was captured.
If you add the following code to your JavaScript...
var patt = new RegExp(regex,"g");
var execResult = patt.exec(file);
print("execResult: " + execResult);
print("execResult.length: " + execResult.length);
print("execResult[0]: " + execResult[0]);
print("execResult[1]: " + execResult[1]);
...you'll get the following output...
[findelement] execResult: <title>Unit Test Results</title>,Unit Test Results
[findelement] execResult.length: 2
[findelement] execResult[0]: <title>Unit Test Results</title>
[findelement] execResult[1]: Unit Test Results
I need to iterate two property in build.xml
<target name="sample">
<property name="modules" value="" />
<property name="env" value="" />
</target>
Can any one help me to write looping concept I need to iterate two property at same time. for example ( property " modules " having list of values like = " a, b ,c d )( property " env " having list of values like = x, y ,z . )
I need value to get = modules.env .. it will gives a.x or b.y in iteration loop. So can any one help how to loop at the same time?
You can always try javascript for non-trivial tasks
<project name="proj">
<property name="modules" value="a,b,c,d" />
<property name="env" value="x,y,z,w" />
<script language="javascript"> <![CDATA[
var modules = proj.getProperty("modules").split(",");
var env = proj.getProperty("env").split(",");
var size = Math.min(modules.length, env.length);
for(var i = 0; i < size; ++i) {
proj.setProperty("mp." + i, modules[i] + "." + env[i]);
}
]]></script>
<echo message="${mp.0}" />
<echo message="${mp.1}" />
<echo message="${mp.2}" />
<echo message="${mp.3}" />
</project>
Is there a way to check age of file during build process?
I would like to check if specified file is older than 1 week.
Something like
<olderthan property="property.name" file="checked.file" days="7"/>
I thought of using touch and uptodate but touch can use only specified date or now.
Mark's link didn't solved my problem but gave me idea to use script
<!-- Check if specified file is newer than age in seconds -->
<scriptdef name="isNewerThan" uri="composer.ant.mleko" language="javascript">
<attribute name="file"/> <!-- The file to check. -->
<attribute name="age"/> <!-- The threshold of file age in seconds. -->
<attribute name="property"/> <!-- The name of property to set. -->
<attribute name="value"/> <!-- The value to set the property to. Defaults to "true". -->
<attribute name="else"/> <!-- The value to set the property to if the condition evaluates to false. By default the property will remain unset. -->
<![CDATA[
var fileName = attributes.get("file");
var age = attributes.get("age");
var property = attributes.get("property");
var value = attributes.get("value");
var elseValue = attributes.get("else");
var maxAge = parseInt(age, 10);
if(null === fileName)self.fail("`file` is required");
if(null === age || isNaN(maxAge))self.fail("`age` is required and must be valid int string");
if(null === property)self.fail("`property` is required");
if(null === value)value="true";
var file = new java.io.File(fileName);
var ageInSeconds = (Date.now() - file.lastModified())/1000;
if(ageInSeconds < maxAge){
project.setProperty(property, value);
}else if(null !== elseValue){
project.setProperty(property, elseValue);
}
]]>
</scriptdef>
To use <touch> and <uptodate> together with <tstamp>:
<tstamp>
<format property="one.week.ago" offset="-7" unit="day" pattern="MM/dd/yyyy hh:mm aa"/>
</tstamp>
<touch file="source-file.txt" datetime="${one.week.ago}"/>
<uptodate
property="target-file-modified-in-previous-week"
targetfile="target-file.txt"
>
<srcfiles dir= "." includes="source-file.txt"/>
</uptodate>
<condition property="is-target-file-out-of-date" value="true" else="false">
<isset property="target-file-modified-in-previous-week"/>
</condition>
<echo>is-target-file-out-of-date: ${is-target-file-out-of-date}</echo>
I need to do 500 times loop. Is there better way rather than
<property name="javato.activetesting.trialnum.list" value="0,1,2,...,500(terrible)" />
<for param="trialnum" list="${javato.activetesting.trialnum.list}">
<sequential>
<echo message="Sub-iteration:#{trialnum}" />
<echo message="................" />
</sequential>
</for>
I'm not sure how to progress this - any suggestions?
Antelope has an additional task called repeat which can be used like this:
<taskdef name="repeat" classname="ise.antelope.tasks.Repeat"/>
<repeat count="2" interval="1" unit="milliseconds">
<echo>${count}</echo>
</repeat>
Also found this solution from another question:
<target name="example4">
<property name="n" value="3300"/>
<property name="target" value="callee"/>
<property name="param" value="calleeparam"/>
<script language="javascript">
// does n antcall's with iteration number param
var n = parseInt(project.getProperty("n"),10);
for (var i = 0; i < n; i++) {
var t = project.createTask("antcall");
t.setTarget(project.getProperty("target"));
var p = t.createParam();
p.setName(project.getProperty("param"));
p.setValue(""+i);
t.perform();
}
</script>
</target>