Convert long name to short name in NANT? - nant

I am working on a NANT build project to build a VS project. One of the build file has a property definition like this:
<property name="App.dir"
value ="${directory::get-current-directory()}\Source\App"/>
This property value has been used in many other places. For example:
<exec program=".\test.exe" workingdir=".">
<arg line="${App.dir}\project1\resources\res1.resx /arg2"/>
Here I need to use <arg line=...> instead of <arg value=...> is to pass specified 2 arguments to text.exe.
when I build this NANT project on another developer's machine, I got a build failure. Finally I found out that the ${App.dir} on that developer's machine is a path in long-form and there is a space in the path. As a result, the arguments to text.exe were actually 3 or more.
I am not sure if there is any way to convert the ${App.dir} path to short name with no spaces:
<property name="App.dir" value ="????"/>
where ???? is something to convert "${directory::get-current-directory()}\Source\App" to a path name in a short-form. Is there any way to do that?
I am using NANT in Windows XP. In Unix/Cgywin, there is one function to get dos name:
cygpath::get-dos-path
Can I use this one in my NANT build file?

Use <arg value="">, from the NANT docs:
value - A single command-line argument; can contain space characters.

I think that I found two ways to resolve the issue. Instead of converting path to DOS path (8.3 name), I can use quotes around my arguments. The second method is the one as ovado recommened to use <arg value=.../> for a single argument value. Here is my test example. All the test files are in my C:\Test folder. First, I created a test bat:
#REM This is the content of Test.bat file.
#echo COMMAND PARAMETERS: %*
#echo FIRST PARAMETER: %1
#echo SECOND PARAMETER: %2
dir %1
Then I created a test build file (Test.Build)"
<project>
<target name="Test" description="Test with one line" failonerror="true">
<property name="App.dir" value ="C:\Program Files"/>
<exec program="test.bat" workingdir=".">
<arg line='"${App.dir}\Microsoft*.*" ${App.dir}\test2 /test3' />
</exec>
</target>
<target name="Test2" description="Test2 with values" failonerror="true">
<property name="App.dir" value ="C:\Program Files"/>
<exec program="test.bat" workingdir=".">
<arg value="${App.dir}\Microsoft*.*" />
<arg value="${App.dir}\test2" />
<arg value="/test3" />
</exec>
</target>
</project>
Here I used " to close my first argument in <arg ='"..."' .../>. Notice that I used single quote for my attribute line.
In this way, I run my build by NANT.EXE. I got the result as I expected:
C:\Test>NANT.exe -buildfile:test.build Test
Test:
[exec] COMMAND PARAMETERS: "C:\Program Files\Microsoft*.*" C:\Program Files\test2 /test3
[exec] FIRST PARAMETER: "C:\Program Files\Microsoft*.*"
[exec] SECOND PARAMETER: C:\Program
[exec] C:\Test\>dir "C:\Program Files\Microsoft*.*"
[exec] Volume in drive C has...
....
I got the same result with the alternative Test2,
C:\Test>NANT.exe -buildfile:test.build Test2
...

Related

URLEncode within NAnt

Is there a way to URLEncode something in NAnt generally - specifically in an echo to a file? One of my build processes enumerates all the PDF output files in a folder and makes an index.html, but some of the PDF files have [] characters in them and they need to be URLEncoded to %5D/%5B in the hrefs
<echo append="false" file="${reportlayout.dir}\index.html"><html><head><title>Product ${modulename} Report PDFs</title><head><body></echo>
<foreach item="File" property="filename">
<in>
<items>
<include name="${reportlayout.dir}\${modulename}/*.pdf" />
</items>
</in>
<do>
<echo append="true" file="${reportlayout.dir}\index.html"><a href="${modulename}/${path::get-file-name(filename)}">${path::get-file-name(filename)}</a><br/></echo>
</do>
</foreach>
<echo append="true" file="${reportlayout.dir}\index.html"></body></html></echo>
This is where href="${modulename}/${path::get-file-name(filename)}" contains characters coming from the filename that need to be URLEncoded, but I can't find a function to do that in the NAnt function list and I don't know if there is a way to get it to call through to .NET HttpUtility.URLEncode or similar.

NetBeans: Run Target to execute an external bat file

I have a JavaHelp project and I have a bat file that basically runs a jhindexer (to create help index).
I would like to make it so that every time I make a build (Run>Target>Other target>Final build - it would run the jhindexer bat on pre-compile. Unfortunately I can't seem to get it working.
Here is my build.xml bit:
<target name="-pre-compile">
<echo message="Creating index"/>
<property name="createIndex" value="${basedir}\" />
<echo>${createIndex}</echo>
<!--<exec command="cmd /C createIndex.bat" />--> //Says its deprecated
<exec dir="${createIndex}" executable="createIndex.bat">
<arg file="cmd createIndex.bat" />
</exec>
</target>
This code gives me:
Creating index
Y:\NetBeansProjects\JavaHelp\
Y:\NetBeansProjects\JavaHelp\build.xml:79: Execute failed:
java.io.IOException: Cannot run program "\createIndex.bat" (in directory "Y:\NetBeansProjects\JavaHelp"): CreateProcess error=2, The system cannot find the file specified
If I change it to:
<exec command="cmd /C createIndex.bat" />
Creating index
Y:\NetBeansProjects\JavaHelp\
The command attribute is deprecated.
Please use the executable attribute and nested arg elements.
I can't seem to figure out a way to run the bat file...
Edit 1:
here is the contents of the bat file:
cd src\helpsetproject
..\..\javahelp\bin\jhindexer topics
It basically goes from basedir too the folder where Images, Topics folders are. Then I run jhindexer (which is in basedir\javahelp\bin) and give it topics (name of folder in the director i am in) as a parameter I guess. It works standalone, but not from Run Target in NetBeans.
Try this:
<target name="-pre-compile">
<echo message="Creating index"/>
<property name="createIndex" value="${basedir}\" />
<echo>${createIndex}</echo>
<exec dir="${createIndex}" executable="cmd">
<arg line="/c createIndex.bat" />
</exec>
</target>

Iterating file structure in Phing and compressing with YUICompressor

I have a directory structure like so:
-css
---subdir1
------common.css
---subdir2
------common.css
------custom.css
---subdir3
------common.css
------styles.css
I'm trying to loop each directory in Phing, and subsequently minify each file into a single hashed filename within each directory using the YUI compressor. The result would look something like this:
-css
---subdir1
------1973a613f7c87b03dbe589e6935a09bd.min.css
---subdir2
------1973a613f7c87b03dbe589e6935a09bd.min.css
---subdir3
------1973a613f7c87b03dbe589e6935a09bd.min.css
I therefore need to know each directory that I'm within so I can output my minified scripts to it.
These are my two targets:
<target name="minify">
<echo msg="Minifying CSS and JS files with YUI at ${yuicompressor}" />
<foreach param="filename" absparam="absfilename" target="runyui">
<fileset dir="${publicdir}/css">
<include name="*.css" />
<include name="**/*.css" />
</fileset>
</foreach>
</target>
<target name="runyui">
<filehash file="${abspathtopwd}" hashtype="MD5" propertyname="filehash" />
<echo msg="java -jar ${yuicompressor} -v --line-break 5000 --type css ${absfilename} >> ${abspathtopwd}/${filehash}.min.css" />
<exec command="java -jar ${yuicompressor} -v --line-break 5000 --type css ${absfilename} >> ${abspathtopwd}/${filehash}.min.css" />
</target>
Where:
yuicompressor is the path to the yui compressor jar
publicdir is just an absolute path to my applications public directory
abspathtopwd is the property I wish to use for the "current iteration's directory"
How can I get the current working directory (or pwd if you prefer) in the current foreach iteration with Phing? All I can see I have access to is the relative and absolute paths to the files themselves.
Note: I'm aware that this current solution would create a new file for each input file, but that's what I'm aiming to fix with abspathtopwd.
Thanks!
For anyone interested in this problem, check out this post, which led me to:
<foreach param="dir" absparam="absdir" target="minify.directory">
<fileset dir="${publicdir}/css">
<type type="dir" />
<depth max="0" min="0" />
</fileset>
</foreach>
This allows me to specify a directory constraint when iterating, thus passing through the relative and absolute directory name as opposed to the filename.

In NAnt <exec>, how to have a conditional <arg> based on property value?

I've got an NAnt <exec> task. I want one argument presence to be conditional to some property being true.
For example, I want the -c command line argument of psExec to be conditional. It should be outputted only if ${pExec.copyprog == 'true'}.
The following does not work:
<property name="psExec.copyprog" value="false" />
...
<exec program="${psExec.path}" failonerror="false">
...
<arg line="-c" if="${psExec.copyprog}==true" />
</exec>
It yields the following error:
'false==true' is not a valid value for attribute 'if' of <arg ... />.
Cannot resolve 'false==true' to boolean value.
String was not recognized as a valid Boolean.
How can I achieve this?
Properties in NAnt are tricky since they don't have a type and simply are considered as of type string. So this would be the solution:
<exec program="${psExec.path}" failonerror="false">
<!-- ... -->
<arg line="-c" if="${bool::parse(psExec.copyprog)}" />
</exec>
Update: Mea culpa! I was wrong. if="${psExec.copyprog}" does also work. So there is some sort of property typing.
You'd need to put ==true inside {}, but you can also just skip it:
<arg line="-c" if="${psExec.copyprog}" />
Comparing a true boolean expression to true does not change the result.

How do I optionally require a command line arguement for Ant?

I'm new to ant, and I want to require a file name if something other than the default target is used, so the calling syntax would be something like this:
ant specifictarget -Dfile=myfile
I'm using the ant contrib package to give me additional functionality, so I have this:
<if>
<equals arg1="${file}" arg2="" />
<then>
<!-- fail here -->
</then>
</if>
My thinking is that if file was not specified it might be equal to the empty string. Obviously, this didn't work, and I'm not finding any examples on google or the right syntax in the manual.
So what syntax should I use?
You don't really need the contrib package. This is more conveniently done using built-in ant capabilities like if/unless and depends. See below:
<target name="check" unless="file" description="check that the file property is set" >
<fail message="set file property in the command line (e.g. -Dfile=someval)"/>
</target>
<target name="specifictarget" if="file" depends="check" description=" " >
<echo message="do something ${file}"/>
</target>
You've got the right idea. The
ant specifictarget -Dfile=myfile
sets Ant Properties from the command line. All you really need is
<property name="file" value=""/>
for your default value. That way if file is not specified, it will be equal to the empty string.
Since properties are not mutable in Ant, you can add this:
<property name="file" value="" />
This will set the property file to an empty string if it hasn't already been set on the command line. Then your equality test will work as you intended.
Alternately, you can use escape the value since ant just spits out the actual text when it can't do a property substitution.
<if>
<equals arg1="${file}" arg2="$${file}" />
<then>
<echo>BARF!</echo>
</then>
</if>