Thursday, March 10, 2005

NAnt expressions

After exrecising NAnt a lot, I'm really liking many of it's features. It still has a few rough edges, but overall it has been a good experience. The power of it struck me when I had a large section of copied code (nant xml build script) that I was able to refactor to remove the copied code. When I was done, I sat back and thought "Wow! I could never have done that in Ant".

To make this post more interesting I'm going to include a little code to demonstrate the NAnt expressions. I'm not going to show the refactoring because it would take too long to explain. So instead I'm going to show a simple subroutine task that converts paths which I pull out of Visual Studio project files. Some of the paths refer to webproject and have to be converted from URL's into local file paths. This subroutine does the conversion...




<target name="common.resolve.url.to.path">
<description>
input properties:
path.temp
wwwroot
output property
path.temp

When path.temp property contains a URL (i.e. starts with http://), this target will search
the directories directly under wwwroot (i.e. ${wwwroot}/*/) for the file contained in
path.temp. When the file is found, it will replace the URL in path.temp with the full
path to the file. If the file is not found, the build fails with a descriptive message.

If path.temp is not a URL, then path.temp is left alone.
</description>
<if test="${string::starts-with(path.temp,'http://')}">
<property name="isFound.temp" value="false">
<foreach item="File" property="filename">
<in>
<items>
<include name="${wwwroot}/*/${path::get-file-name(path.temp)}">
</items>
</in>
<do>
<property name="isFound.temp" value="true">
<property name="path.temp" value="${filename}">
</do>
</foreach>
<if test="${bool::parse(isFound.temp) == false}">
<fail message="Unable to find ${path::get-file-name(path.temp)} under ${wwwroot} directory.">
</if>
</if>
</target>




Notice the ${...} isn't just a simple property replacement. Instead in NAnt, I can make function calls ${string::starts-with(...)} for example. Also, I can have simple expressions like ${bool::parse(aProperty) == false}. Very cool stuff. Ant needs to catch up.

No comments: