- multiple delimiters are allowed
- multiple properties are allowing the item="Line" case, but only if delimiter(s) are specified
- trim="" property allows you to specify trimming whitespace from begin, end or both parts of a string
You can now do this (using Scott's example):
<foreach item="Line" in="properties.csv" trim="both" delim="," property="x,y">
<property name="${x}" value="${y}"/>
</foreach>where properties.cvs is prop1, value prop2, value
New tests added for new functionality, all tests pass w/current CVS.
Note that my earlier patch from today is included in this one - sorry!
? patch.txt
Index: src/NAnt.Core/Tasks/CopyTask.cs
===================================================================
RCS file: /cvsroot/nant/nant/src/NAnt.Core/Tasks/CopyTask.cs,v
retrieving revision 1.4
diff -u -r1.4 CopyTask.cs
--- src/NAnt.Core/Tasks/CopyTask.cs 26 Feb 2003 07:02:30 -0000 1.4
+++ src/NAnt.Core/Tasks/CopyTask.cs 3 Mar 2003 17:34:34 -0000
@@ -126,6 +126,8 @@
Log.WriteLineIf(Verbose, LogPrefix + "Created directory
{0}", dstDirectory);
}
+ if (File.Exists(dstPath))
+ File.SetAttributes(dstPath, FileAttributes.Normal);
File.Copy(sourcePath, dstPath, true);
} catch (Exception e) {
string msg = String.Format(CultureInfo.InvariantCulture,
"Cannot copy {0} to {1}", sourcePath, dstPath);
Index: src/NAnt.Core/Tasks/LoopTask.cs
===================================================================
RCS file: /cvsroot/nant/nant/src/NAnt.Core/Tasks/LoopTask.cs,v
retrieving revision 1.1
diff -u -r1.1 LoopTask.cs
--- src/NAnt.Core/Tasks/LoopTask.cs 14 Aug 2002 23:21:51 -0000 1.1
+++ src/NAnt.Core/Tasks/LoopTask.cs 3 Mar 2003 17:34:34 -0000
@@ -27,7 +27,7 @@
/// <remarks>
/// <para>Loop over items in a set. Can loop over files in directory, lines in
a file, etc.</para>
/// <para>The Property value is stored before the loop is done, and restored
when the loop is finished.
- /// The Property is returned to its normal value once it is used.</para>
+ /// The Property is returned to its normal value once it is used. Read-only
parameters cannot be overridden in this loop.</para>
/// </remarks>
/// <example>
/// <para>Loops over the files in C:\</para>
@@ -49,11 +49,19 @@
/// <para>Loops over a list</para>
/// <code>
/// <![CDATA[
- /// <foreach item="String" in="1 2 3" delim=" " property="count">
+ /// <foreach item="String" in="1 2,3" delim=" ," property="count">
/// <echo message="${count}"/>
/// </foreach>
/// ]]>
/// </code>
+ /// <para>Loops over lines in the file "properties.csv", where each line is of
the format name,value.</para>
+ /// <code>
+ /// <![CDATA[
+ /// <foreach item="Line" in="properties.csv" delim="," property="x,y">
+ /// <echo message="Read pair ${x}=${y}"/>
+ /// </foreach>
+ /// ]]>
+ /// </code>
/// </example>
[TaskName("foreach")]
public class LoopTask : TaskContainer {
@@ -64,20 +72,35 @@
String,
Line
}
+ public enum TrimTypes {
+ None,
+ End,
+ Start,
+ Both
+ }
+
string _prop = null;
+ string[] _props = null;
ItemTypes _itemType = ItemTypes.None;
+ TrimTypes _trimType = TrimTypes.None;
string _source = null;
- string _delim = " ";
+ string _delim = null;
- /// <summary>The NAnt propperty name that should be used for the current
iterated item.</summary>
+ /// <summary>The NAnt propperty name(s) that should be used for the current
iterated item.</summary>
+ /// <remarks>If specifying multiple properties, separate them with a
comma.</remarks>
[TaskAttribute("property", Required=true)]
public string Property {
get { return _prop; }
set {
_prop = value;
- if(Properties.IsReadOnlyProperty(_prop)) {
- throw new BuildException("Property is readonly! :" + _prop,
Location);
- }
+ _props = _prop.Split( ',' );
+ foreach ( string prop in _props )
+ {
+ if(Properties.IsReadOnlyProperty(prop))
+ {
+ throw new BuildException("Property is
readonly! :" + prop, Location);
+ }
+ }
}
}
@@ -87,7 +110,13 @@
[TaskAttribute("item", Required=true)]
public ItemTypes ItemType { get { return _itemType;} set {_itemType =
value; }}
- /// <summary>
+ /// <summary>
+ /// The type of whitespace trimming that should be done.
+ /// </summary>
+ [TaskAttribute("trim")]
+ public TrimTypes TrimType { get { return _trimType;} set {_trimType
= value; }}
+
+ /// <summary>
/// The source of the iteration.
/// </summary>
[TaskAttribute("in", Required=true)]
@@ -100,7 +129,11 @@
public string Delimiter { get { return _delim;} set {_delim = value; }}
protected override void ExecuteTask() {
- string oldPropVal = Properties[_prop];
+ string[] oldPropVals = new string[ _props.Length ];
+ // Save all of the old property values
+ for ( int nIndex = 0; nIndex < oldPropVals.Length; nIndex++ ) {
+ oldPropVals[ nIndex ] = Properties[ _props[ nIndex ] ];
+ }
try {
switch(ItemType) {
@@ -109,7 +142,9 @@
case ItemTypes.File: {
if(!Directory.Exists(Project.GetFullPath(_source)))
throw new BuildException("Invalid Source: " + _source,
Location);
- DirectoryInfo dirInfo = new
DirectoryInfo(Project.GetFullPath(_source));
+ if(_props.Length != 1)
+ throw new
BuildException(@"Only one property is valid for item=""File""");
+ DirectoryInfo dirInfo = new
DirectoryInfo(Project.GetFullPath(_source));
FileInfo[] files = dirInfo.GetFiles();
foreach(FileInfo file in files) {
DoWork(file.FullName);
@@ -119,6 +154,8 @@
case ItemTypes.Folder: {
if(!Directory.Exists(Project.GetFullPath(_source)))
throw new BuildException("Invalid Source: " + _source,
Location);
+ if(_props.Length != 1)
+ throw new
BuildException(@"Only one property is valid for item=""Folder""");
DirectoryInfo dirInfo = new
DirectoryInfo(Project.GetFullPath(_source));
DirectoryInfo[] dirs = dirInfo.GetDirectories();
foreach(DirectoryInfo dir in dirs) {
@@ -129,37 +166,61 @@
case ItemTypes.Line: {
if(!File.Exists(Project.GetFullPath(_source)))
throw new BuildException("Invalid Source: " + _source,
Location);
- StreamReader sr = File.OpenText(Project.GetFullPath(_source));
+ if(_props.Length > 1 && ( Delimiter ==
null || Delimiter.Length == 0 ) )
+ throw new
BuildException("Delimiter(s) must be specified if multiple properties are specified");
+
+ StreamReader sr =
File.OpenText(Project.GetFullPath(_source));
while(true) {
string line = sr.ReadLine();
if (line ==null)
break;
- DoWork(line);
+ if (Delimiter == null ||
Delimiter.Length == 0)
+ DoWork(line);
+ else
+
DoWork(line.Split(Delimiter.ToCharArray()));
}
sr.Close();
break;
}
case ItemTypes.String: {
- if(Delimiter != null && Delimiter.Length > 0) {
- string[] items =
_source.Split(Delimiter.ToCharArray()[0]);
- foreach(string s in items)
- DoWork(s);
- }
- else
- throw new BuildException("Invalid delim: " + _delim,
Location);
+ if(_props.Length > 1)
+ throw new
BuildException(@"Only one property may be specified for item=""String""");
+ if(Delimiter == null ||
Delimiter.Length == 0)
+ throw new
BuildException(@"Delimiter must be specified for item=""String""");
+ string[] items = _source.Split(Delimiter.ToCharArray());
+ foreach(string s in items)
+ DoWork(s);
break;
}
-
}
}
finally {
- Properties[_prop] = oldPropVal;
+ // Restore all of the old property values
+ for ( int nIndex = 0; nIndex < oldPropVals.Length;
nIndex++ ) {
+ Properties[ _props[ nIndex ] ] = oldPropVals[
nIndex ];
+ }
}
-
}
- protected virtual void DoWork(string propVal) {
- Properties[_prop]= propVal;
+ protected virtual void DoWork(params string[] propVals) {
+ for ( int nIndex = 0; nIndex < propVals.Length; nIndex++ ) {
+ string propValue = propVals[ nIndex ];
+ if ( nIndex >= _props.Length )
+ throw new BuildException("Too many items on
line");
+ switch (_trimType)
+ {
+ case TrimTypes.Both:
+ propValue = propValue.Trim();
+ break;
+ case TrimTypes.Start:
+ propValue = propValue.TrimStart();
+ break;
+ case TrimTypes.End:
+ propValue = propValue.TrimEnd();
+ break;
+ }
+ Properties[ _props[ nIndex ] ] = propValue;
+ }
base.ExecuteTask();
}
}
Index: src/NAnt.Core.Tests/Tasks/LoopTest.cs
===================================================================
RCS file: /cvsroot/nant/nant/src/NAnt.Core.Tests/Tasks/LoopTest.cs,v
retrieving revision 1.2
diff -u -r1.2 LoopTest.cs
--- src/NAnt.Core.Tests/Tasks/LoopTest.cs 25 Oct 2002 10:18:09 -0000 1.2
+++ src/NAnt.Core.Tests/Tasks/LoopTest.cs 3 Mar 2003 17:34:34 -0000
@@ -36,7 +36,7 @@
public void Test_Loop_String_Default_Delim() {
string _xml = @"
<project>
- <foreach item='String' in='1,2,3,4' delim=','
property='count'>
+ <foreach item='String' in='1,2,3,4;5' delim=';,'
property='count'>
<echo message='Count:${count}'/>
</foreach>
</project>";
@@ -46,7 +46,8 @@
Assertion.Assert(result.IndexOf("Count:2") != -1);
Assertion.Assert(result.IndexOf("Count:3") != -1);
Assertion.Assert(result.IndexOf("Count:4") != -1);
- }
+ Assertion.Assert(result.IndexOf("Count:5") != -1);
+ }
[Test]
public void Test_Loop_Files() {
@@ -79,16 +80,57 @@
[Test]
public void Test_Loop_Lines() {
- string _xml = @"
- <project>
- <!-- Hello from inside -->
- <foreach item='Line' in='${nant.project.basedir}/test.build'
property='line'>
- <echo message='Line:${line}'/>
- </foreach>
- </project>";
- string result = RunBuild(_xml);
- //Log.WriteLine(result);
- Assertion.Assert(result.IndexOf("Hello") != -1);
+ string strTempFile =
CreateTempFile("looptest.loop_lines_test.txt");
+ using ( StreamWriter sw = new StreamWriter( strTempFile ) )
+ {
+ sw.WriteLine( "x,y" );
+ sw.WriteLine( "x2,y2 " );
+ sw.WriteLine( "x3 ,y3" );
+ sw.WriteLine( "x4, y4" );
+ sw.Close();
+
+ string _xml = String.Format( @"
+ <project>
+ <!-- Hello from inside -->
+ <foreach item='Line'
delim=',;' trim='Both' in='{0}' property='x,y'>
+ <echo
message='|${{x}}=${{y}}|'/>
+ </foreach>
+ </project>", strTempFile );
+ string result = RunBuild(_xml);
+ //Log.WriteLine(result);
+ Assertion.Assert(result.IndexOf("|x=y|") != -1);
+ Assertion.Assert(result.IndexOf("|x2=y2|") != -1);
+ Assertion.Assert(result.IndexOf("|x3=y3|") != -1);
+ Assertion.Assert(result.IndexOf("|x4=y4|") != -1);
+ }
}
- }
+
+ [Test]
+ public void Test_Loop_Lines_No_Delim()
+ {
+ string strTempFile =
CreateTempFile("looptest.loop_lines_test.txt");
+ using ( StreamWriter sw = new StreamWriter( strTempFile ) )
+ {
+ sw.WriteLine( "x,y " );
+ sw.WriteLine( "x2,y2 " );
+ sw.WriteLine( " x3 ,y3 " );
+ sw.WriteLine( " x4, y4 " );
+ sw.Close();
+
+ string _xml = String.Format( @"
+ <project>
+ <!-- Hello from inside -->
+ <foreach item='Line'
trim='Start' in='{0}' property='x'>
+ <echo
message='|${{x}}|'/>
+ </foreach>
+ </project>", strTempFile );
+ string result = RunBuild(_xml);
+ Log.WriteLine(result);
+ Assertion.Assert(result.IndexOf("|x,y |") != -1);
+ Assertion.Assert(result.IndexOf("|x2,y2 |") != -1);
+ Assertion.Assert(result.IndexOf("|x3 ,y3 |") != -1);
+ Assertion.Assert(result.IndexOf("|x4, y4 |") != -1);
+ }
+ }
+ }
}
