Over the past week or so I have been working on automating a Visual Basic 6 build. My tool of course is Nant. It works very well for the most post.
The build compiles the VB programs and builds the installer. This has been working great. However one of the requirements was to only keep the last 5 Install CD images that the build created.
I prefer to not extend Nant to keep the build scripts as portable as possible. I have done many things using the Nant XML rather than dropping down to C#.
Believe it or not this was not an easy problem to solve. In other builds we save files based on the date. Just keep the last 7 days worth or something. This is pretty easy to do. Just loop through the folders using the
My first attempt was to do a
(Tip: when you are using the < or > operator in NAnt you have to encode it in your script or you get an XML parsing error. Use & gt; or & lt;)
This worked fine at first. But, the folders the build created where something like:
ProductName 1.0.95 - 200909100844
ProductName 1.0.96 - 200909100844
ProductName 1.0.97 - 200909100844
The
My next attempt was to see if there was a way to sort the fileset buy date order. There is not. After than I tried to use the
So, I finally decided to bite the bullet and use the script tag. At least using the script tag would keep the build scripts portable unlike creating a custom task or function which would be deployed into a separate DLL that had to always be available.
Here is my final task. Disclaimer, use this at your own risk. I only post the code here for academic interest. Don't blame me if this formats your C: drive or makes your laptop go up in flame.
<script language="C#">
<code><![CDATA[
public static void ScriptMain(Project project)
{
string path = project.Properties["InstallDir"];
string [] folders = System.IO.Directory.GetDirectories(path,"*",SearchOption.TopDirectoryOnly);
System.Collections.ArrayList dirlist = new System.Collections.ArrayList();
foreach (string folder in folders)
{
dirlist.Add(new DirectoryInfo(folder));
}
dirlist.Sort(new DirectoryInfoDateComparer());
dirlist.Reverse();
for (int i = 5; i < dirlist.Count; i++)
{
string foldername = ((DirectoryInfo)dirlist[i]).Name;;
try
{
((DirectoryInfo)dirlist[i]).Delete(true);
project.Log(Level.Info, String.Format("Deleted folder {0}", foldername));
}
catch { project.Log(Level.Warning, String.Format("Unable to delete folder {0}", foldername)); }
}
}
internal class DirectoryInfoDateComparer : System.Collections.IComparer
{
public int Compare(object x, object y)
{
DirectoryInfo di1 = (DirectoryInfo)x;
DirectoryInfo di2 = (DirectoryInfo)y;
return di1.CreationTime.CompareTo(di2.CreationTime);
}
}
]]></code>
</script>
This did the trick. The only niggle is that the Log messages don't conform to the rest of the Nant log. I got a workaround for that from the Nant email list, but have yet to try it.