get file content and assign to property in Phing - phing

Is there a way to get a file content and assign to property for Phing?
An equivalent to ant:
<project name="foobar" default="foo">
<target name="foo">
<loadfile property="foo.bar" srcFile="foobar/moo.txt"/>
<echo>${foo.bar}</echo>
</target>
</project>
?

Doesn't the loadfile task do what you're after?

Related

Use a phing ForEach loop to execute tasks

I want to execute an arbitrary selection of tasks in a Phing build.
I'm passing in a list of modules for building. Each module is of a particular type. The type is specified in the name, as {type}_{unitname}. I started with a build file that took a single module name and built it, that works fine. I now want to pass in a list of modules and have it build all of them. (What I'd really like to do is load the list of modules from an XML manifest file, but perhaps one thing at a time).
I've tried multiple ways and have found a problem with each.
I seem to need an ad-hoc task to derive my properties (task and related directory settings) from the module name. This seems to cause problems, but not at first.
At first I tried to use the loop variable as the target
<foreach list="${mylist}" param="item" target="${item"} />
but it doesn't seem to allow a variable as a target name. So I split it up into two tasks.
<foreach list="${parts}" param="dTarg" target="doIt" >
<task name="DoIt">
<phingcall target="build">
<property name="extension" value="${dTarg}" />
</phingcall -->
</task>
My problem here is (I think) "extension" is a constant and thus can't be overwritten. I tried using "var", which the docs say is a thing, but my setup complains it doesn't exist. Is it a 3.0 feature? I'm running 2.17.
So I tried changing the "phingcall" to "phing" and put my main functionality in a separate file. Here I run into problems with the ad-hoc task again. If I put it in the "subordinate" file, it complains that's it's re-declared (I think, the message isn't very helpful) when the file is called a second time. If I leave it in the main file, the subordinate file can't find it, even with inheritrefs and inheritall set.
How can I execute tasks whose names are in list?
At first I tried to use the loop variable as the target
<foreach list="${mylist}" param="item" target="${item"} />
but it doesn't seem to allow a variable as a target name
The target attribute of the foreach task is able to use variables as a value, but at this point param="item" is not yet available but in the target it is.
So I split it up into two tasks.
<foreach list="${parts}" param="dTarg" target="doIt" >
<task name="DoIt">
<phingcall target="build">
<property name="extension" value="${dTarg}" />
</phingcall>
</task>
Here you try to use a task task which is simply not a valid target.
What you want to do instead is to have targets to iterate over. The following example demonstrates the usage:
Input build.xml
<?xml version="1.0" encoding="utf-8" ?>
<project name="test" default="main">
<property name="mylist" value="A,B,C" />
<target name="main">
<foreach list="${mylist}" param="item" target="DoIt"/>
</target>
<target name="DoIt">
<echo>${item}</echo>
</target>
</project>
Output
test > main:
test > DoIt:
[echo] A
test > DoIt:
[echo] B
test > DoIt:
[echo] C
BUILD FINISHED
Complex Example (with property override and inheritAll)
<?xml version="1.0" encoding="utf-8" ?>
<project name="test" default="main">
<property name="mylist" value="A,B,C" />
<target name="main">
<foreach list="${mylist}" param="item" target="DoIt"/>
</target>
<target name="DoIt">
<phingcall target="${item}" inheritAll="true">
<property name="extension" override="true" value="${item}-ext" />
</phingcall>
</target>
<target name="A">
<echo>Inside target ${item} with ${extension} extension</echo>
</target>
<target name="B">
<echo>Inside target ${item} with ${extension} extension</echo>
</target>
<target name="C">
<echo>Inside target ${item} with ${extension} extension</echo>
</target>
</project>
Output
test > main:
test > DoIt:
test > A:
[echo] Inside target A with A-ext extension
test > DoIt:
test > B:
[echo] Inside target B with B-ext extension
test > DoIt:
test > C:
[echo] Inside target C with C-ext extension
BUILD FINISHED
Example execute as one task with changed values from the list
<?xml version="1.0" encoding="utf-8" ?>
<project name="test" default="main">
<property name="mylist" value="A,B,C" />
<target name="main">
<foreach list="${mylist}" param="item" target="DoIt"/>
</target>
<target name="DoIt">
<phingcall target="build">
<property name="extension" override="true" value="${item}-ext" />
</phingcall>
</target>
<target name="build">
<echo>Inside target build with ${extension}</echo>
</target>
</project>
Output
test > main:
test > DoIt:
test > build:
[echo] Inside target build with A-ext
test > DoIt:
test > build:
[echo] Inside target build with B-ext
test > DoIt:
test > build:
[echo] Inside target build with C-ext
BUILD FINISHED
Simplified and final build
<?xml version="1.0" encoding="utf-8" ?>
<project name="test" default="main">
<property name="mylist" value="A,B,C" />
<target name="main">
<foreach list="${mylist}" param="item" target="build">
<property name="extension" override="true" value="${item}-ext" />
</foreach>
</target>
<target name="build">
<echo>Inside target build with ${extension}</echo>
</target>
</project>
Output
test > main:
test > build:
[echo] Inside target build with A-ext
test > build:
[echo] Inside target build with B-ext
test > build:
[echo] Inside target build with C-ext
BUILD FINISHED

Phing update version number in XML manifest

I need to add the ability to a phing build to:
Parse an existing xml file within the project area to get an existing build number (in format 1.2.3)
Ask the user what type of 'change' this is (i.e. major, minor, fix)
Based on the response of the user at the time of run, upgrade the respective digit from the build number (if major increase 1 by 1; if minor increase 2 by 1; if fix increase 3 by 1)
Store the build number back into the original xml file
Have the new build number available for use when naming a zip file (later in the build).
Wondering if anyone already has a phing build file that does something like this or if you happen to know what phing tasks might help with these steps?
As a starting point you could do it without overhead using the version task (it uses a property file to store the version information) or with some more effort from a xml file.
The following example build script (documentation links can be found in the description attributes) contains both ways.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="version test"
default="help"
phingVersion="3.0"
description="https://stackoverflow.com/questions/68584221/phing-update-version-number-in-xml-manifest"
>
<target name="help" description="usage help">
<echo>Usage:</echo>
<echo>bin/phing xml-file-based-workflow</echo>
<echo>bin/phing property-file-based-workflow</echo>
</target>
<target name="xml-file-based-workflow"
description="version handling with xml file"
depends="user-input,handle-xml-version,use-version"
/>
<target name="property-file-based-workflow"
description="version handling with property file"
depends="user-input,handle-property-version,use-version"
/>
<target name="user-input"
description="https://www.phing.info/guide/hlhtml/#InputTask"
hidden="true"
>
<input message="what is your release type?" propertyName="release.type" defaultValue="Bugfix"/>
</target>
<target name="handle-property-version"
description="https://www.phing.info/guide/hlhtml/#VersionTask"
hidden="true"
>
<version releasetype="${release.type}" file="VERSION.txt" property="version.number"/>
</target>
<target name="handle-xml-version"
description="
https://www.phing.info/guide/hlhtml/#XmlPropertyTask
https://www.phing.info/guide/hlhtml/#EchoPropertiesTask
https://www.phing.info/guide/hlhtml/#VersionTask
https://www.phing.info/guide/hlhtml/#DeleteTask
https://www.phing.info/guide/hlhtml/#EchoXMLTask
"
hidden="true"
>
<xmlproperty file="VERSION.xml" />
<echoproperties destfile="VERSION.txt" regex="/version\.number/"/>
<version releasetype="${release.type}" file="VERSION.txt" property="version.number"/>
<delete file="VERSION.txt"/>
<echoxml file="VERSION.xml">
<version>
<number>${version.number}</number>
</version>
</echoxml>
</target>
<target name="use-version"
description="https://www.phing.info/guide/hlhtml/#EchoTask"
hidden="true"
>
<echo message="${version.number}" />
</target>
</project>

error while building project using Nant

I have file pro.build:
<?xml version="1.0" ?>
<project name="NAnt.NUnit2ReportTasks" default="build" basedir=".">
<sysinfo />
<target name="nunitreport">
<nunit2report out="HTML_TestResults.html">
<fileset>
<includes name="NUnitTestResult.xml" />
</fileset>
</nunit2report>
<echo message="HTML Test report generated." />
</target>
</project>
From command prompt(DOS), I am giving command,
Nant -buildfile:pro.build
But I am getting error
Target 'build' does not exist in this project
Can you help me resolving this?
With <project>'s default attribute you specify the target which should be executed if no other target is specified on the command line.
Problem: On the command line you're calling Nant -buildfile:pro.build so you are not specifying a target there. NAnt tries to execute default target build which is not present and fails.
Solution: Either you specify target nunitreport on the command line by calling Nant -buildfile:pro.build nunitreport. But since specifying a non-existent default target in your build file doesn't make much sense, I would suggest changing the default target:
<project name="NAnt.NUnit2ReportTasks" default="nunitreport" basedir=".">
<!-- ... -->
</project>
Specifing complete path for the buildfile could resolve the issue
nant –buildfile:"c:\FolderpathofAppdotbuildfileGoesHere\buildfilename.build"

NAnt ignoring property in included build file

I'm trying to make my project build file include a local build file, to allow for some customization for each developer, without having to keep exclulding the build file from version control commits etc.
But NAnt keeps ignoring the properties in my included build file, and not overwriting the properties set in the global build file.
For demo purposes this short build file behaves the same:
<project name="FooProject" default="showme" basedir="." >
<description>Foo</description>
<!-- Overwrite this property in local.build -->
<property name="database.connectionstring" overwrite="true" readonly="false" value="foo" />
<include buildfile="local.build" failonerror="true" verbose="true" />
<target name="showme" description="Show connectionstring variable">
<echo message="Connectionstring: ${database.connectionstring}" />
</target>
</project>
-and my local.build file looks like this:
<property name="database.connectionstring" value="bar" />
The expected output when running NAnt with this build file is "Connectionstring: bar", but the resulit is "Connectionstring: foo", no matter which combination of readonly and overwrite I try.
It does fail if I rename the file to something else, so NAnt is aware of the included file.
NAnt is v0.91 alpha.
Am I overlooking something or is NAnt not supposed to work like I expect?
It seems you should still wrap the contents of the included build file inside a project-element. Like so:
<project>
<property name="database.connectionstring" value="bar" />
</project>
When I did that the connectionstring was "bar".
Granted: I use Nant 0.91 final.

Include/Exclude buildfiles

How do you do this? Given several build files, I only want to include the ones where the target (specified from the command line) exists. Using target::exists in does not seem to work. Thanks.
<target name="*">
<property name="curr.target" value="${target::get-current-target()}"/>
<nant target="${curr.target}">
<buildfiles>
<include name="*.build" if="${target::exists(curr.target)}"/>
<!-- avoid recursive execution of current build file-->
<exclude name="${project::get-buildfile-path()}" />
</buildfiles>
</nant>
</target>
Using robaker's solution, my final build file looks like this. It does not fail anymore if the target is not found in a certain build file (unlike my previous code).
<project>
<include buildfile="A.build"/>
<include buildfile="B.build"/>
<target name="*">
<nant target="${target::get-current-target()}"/>
</target>
</project>
Why not just use the include task to include all your child build scripts instead?