[Microsoft.Build.Utilities] Fix the escaping/unescaping of ItemSpec
authorAlan McGovern <alan@xamarin.com>
Tue, 28 Jan 2014 20:40:25 +0000 (15:40 -0500)
committerAlan McGovern <alan@xamarin.com>
Tue, 28 Jan 2014 20:40:25 +0000 (15:40 -0500)
This should hopefully fix compilation of projects using files with
names like 'foo@2x.png' in various places like embedded resources
or content items which must be copied to the output directory.

With tests.

mcs/class/Microsoft.Build.Utilities/Makefile
mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/TaskItem.cs
mcs/class/Microsoft.Build.Utilities/Test/Microsoft.Build.Utilities/TaskItemTest.cs

index 79888a2a3b4491391527253aa3414c3178094379..0951df6adba0913037273067e21faf575badef62 100644 (file)
@@ -13,7 +13,7 @@ LIB_MCS_FLAGS = \
        /r:System.dll                           \
        /r:$(XBUILD_FRAMEWORK)
 
-TEST_MCS_FLAGS = /r:$(XBUILD_FRAMEWORK) -r:System.dll -r:System.Core.dll
+TEST_MCS_FLAGS = /r:$(XBUILD_ENGINE) /r:$(XBUILD_FRAMEWORK) -r:System.dll -r:System.Core.dll
 
 include $(XBUILD_DIR)/xbuild_test.make
 include ../../build/library.make
index a65cb37bedddb3eba5e452150e61e25efcc57529..bbda9528245513330dfa14e26b3eb0ec5068db6c 100644 (file)
@@ -64,7 +64,6 @@ namespace Microsoft.Build.Utilities
                        if (itemSpec == null)
                                throw new ArgumentNullException ("itemSpec");
                        
-                       this.itemSpec = itemSpec;
                        this.metadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
 
                        // FIXME: hack
@@ -108,9 +107,9 @@ namespace Microsoft.Build.Utilities
                public string GetMetadata (string metadataName)
                {
                        if (ReservedNameUtils.IsReservedMetadataName (metadataName))
-                               return ReservedNameUtils.GetReservedMetadata (ItemSpec, metadataName, metadata);
+                               return MSBuildUtils.Unescape (ReservedNameUtils.GetReservedMetadata (ItemSpec, metadataName, metadata));
                        else if (metadata.Contains (metadataName))
-                               return (string) metadata [metadataName];
+                               return MSBuildUtils.Unescape ((string)metadata [metadataName]);
                        else
                                return String.Empty;
                }
@@ -153,8 +152,8 @@ namespace Microsoft.Build.Utilities
                }
                
                public string ItemSpec {
-                       get { return itemSpec; }
-                       set { itemSpec = value; }
+                       get { return MSBuildUtils.Unescape (itemSpec); }
+                       set { itemSpec = MSBuildUtils.Escape (value); }
                }
 
                public int MetadataCount {
index 2032f7c3572d078d072f5862028890a77b9d3613..8f23aaba4e9e54dd57ffdd02bcb600bc92bc0dfb 100644 (file)
@@ -28,6 +28,7 @@
 using System;
 using System.Collections;
 using System.Collections.Specialized;
+using System.IO;
 using Microsoft.Build.Framework;
 using Microsoft.Build.Utilities;
 using NUnit.Framework;
@@ -115,6 +116,50 @@ namespace MonoTests.Microsoft.Build.Utilities {
                        new TaskItem ("itemspec", null);
                }
 
+               [Test]
+               public void TestCtor_EscapedSpecialChar ()
+               {
+                       // If we instantiate with the *escaped* metadata, it's unescaped automatically
+                       var metadata = "foo@2x.png";
+                       var escapedMetadata = global::Microsoft.Build.BuildEngine.Utilities.Escape ("foo@2x.png");
+                       var item = new TaskItem (escapedMetadata);
+                       item.SetMetadata ("mine", escapedMetadata);
+
+                       Assert.AreEqual (metadata, item.ItemSpec, "#1");
+                       Assert.AreEqual (metadata, item.GetMetadata ("Identity"), "#2");
+                       Assert.AreEqual (Path.GetFileNameWithoutExtension (metadata), item.GetMetadata ("FileName"), "#3");
+                       Assert.IsTrue (item.GetMetadata ("FullPath").EndsWith (metadata), "#4");
+                       Assert.AreEqual (metadata, item.GetMetadata ("mine"), "#5");
+               }
+
+               [Test]
+               public void TestCtor_EscapedSpecialChar_BrokenEscaping ()
+               {
+                       // This is badly escaped, but MSBuild does not care.
+                       var metadata = "foo%4@2x.png";
+                       var item = new TaskItem (metadata);
+
+                       Assert.AreEqual (metadata, item.ItemSpec, "#1");
+                       Assert.AreEqual (metadata, item.GetMetadata ("Identity"), "#2");
+                       Assert.AreEqual (Path.GetFileNameWithoutExtension (metadata), item.GetMetadata ("FileName"), "#3");
+                       Assert.IsTrue (item.GetMetadata ("FullPath").EndsWith (metadata), "#4");
+               }
+
+               [Test]
+               public void TestCtor_UnescapedSpecialChar ()
+               {
+                       // If we instantiate with unescaped metadata, we get the same value back
+                       var metadata = "foo@2x.png";
+                       var item = new TaskItem (metadata);
+                       item.SetMetadata ("mine", metadata);
+
+                       Assert.AreEqual (metadata, item.ItemSpec, "#1");
+                       Assert.AreEqual (metadata, item.GetMetadata ("Identity"), "#2");
+                       Assert.AreEqual (Path.GetFileNameWithoutExtension (metadata), item.GetMetadata ("FileName"), "#3");
+                       Assert.IsTrue (item.GetMetadata ("FullPath").EndsWith (metadata), "#4");
+                       Assert.AreEqual (metadata, item.GetMetadata ("mine"), "#5");
+               }
+
                [Test]
                public void TestCopyConstructor ()
                {