During the last days, I started reading about PowerShell and PSake. While looking at the NAnt scripts that I currently use, I recognized that among others the capability of examining and editing XML files is required.
Examining XML in NAnt
In NAnt, inspecting XML is done with the xmlpeek-task. It takes a file name, an XPath and a property name to fill with the result.
One of the uses of xmlpeek is to find out the current revision of a code base, for example to set the private part of the version number with it. In the Castle Project’s build script this is done this way:
<target name="common.find-svninfo">
<!-- For adding SVN revision to builds -->
<property name="svn.revision" value="0" overwrite="false" />
<!-- try to update the revision -->
<exec
program="svn"
commandline='info "${project::get-base-directory()}" --xml'
output="_revision.xml"
failonerror="false"/>
<xmlpeek
file="_revision.xml"
xpath="/info/entry/@revision"
property="svn.revision"
failonerror="false"/>
<delete file="_revision.xml" failonerror="false" />
<echo message="INFO: Using Subversion revision number: ${svn.revision}"/>
</target>
So while this is quite a clever solution to find out the projects current revision, it has some drawbacks, such as being nearly 20 lines of code and that it uses a temporary file. But it does the job, reading the revision from the project folder.
Examining XML in PowerShell
PowerShell treats XML as a first class type and also has some shortcuts available. If we take a look at the result of svn info, we see that it is thankfully simple:
<?xml version="1.0"?>
<info>
<entry
kind="dir"
path="."
revision="6536">
...
</entry>
</info>
And because we can traverse XML nodes and attributes in PowerShell like object properties, it is possible to get the revision number even without an XPath expression.
$revision = $rev_xml.info.entry.revision
So now it is only necessary to fill the $rev_xml variable with the output of the svn info command. The NAnt script does this using a temporary file but PowerShell allows to assign the standard output of a command line program directly to a variable:
$rev_xml = svn.exe info --xml
But PowerShell treats the output of such a program as an array of objects, in this case strings. We have to hint PowerShell that what we want is an XMLDocument instead of an array of strings:
[xml] $rev_xml = svn.exe info --xml
That’s all. We now only have to put this together into a PSake build script for testing and reference.
properties { [string] $project_path = "C:\dev\castle\SVN\ActiveRecord" $revision = 0 } task default -depends get_revision task get_revision { [xml] $rev_xml = svn.exe info $project_path --xml $revision = $rev_xml.info.entry.revision "INFO: Using Subversion revision number: $revision" }
This whole script is shorter than the snippet of NAnt script I’ve shown at the beginning. Taking only the relevant work, 5 lines of PS script replace 15 lines of NAnt XML.
The script of course ignores the fact that getting the revision number should not be a task but rather a function that is called by a build task’s precondition for example. I will get back this in a while in another post.
No comments:
Post a Comment