[xbuild] Fix #40094, part 2/2: AssignProjectConfiguration - Fallback to
authorAnkit Jain <ankit.jain@xamarin.com>
Wed, 6 Apr 2016 18:16:33 +0000 (14:16 -0400)
committerAnkit Jain <ankit.jain@xamarin.com>
Wed, 6 Apr 2016 18:40:31 +0000 (14:40 -0400)
.. project path for lookup, if lookup by guid fails.

Fixes bxc #40094 .

mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/AssignProjectConfiguration.cs
mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/AssignProjectConfigurationTest.cs

index 6fd7954ab42c949f141c90ef3aeeec886a16c22d..bb85df584df4eb0e8f41e58f61c9a855bacec375 100644 (file)
@@ -41,6 +41,8 @@ namespace Microsoft.Build.Tasks {
                ITaskItem[]     assignedProjects;
                string          solutionConfigurationContents;
                ITaskItem[]     unassignedProjects;
+               Dictionary<Guid, string> guidToConfigPlatform;
+               Dictionary<string, string> absolutePathToConfigPlatform;
        
                public AssignProjectConfiguration ()
                {
@@ -53,10 +55,10 @@ namespace Microsoft.Build.Tasks {
                                return true;
 
                        XmlReader xr = null;
-                       Dictionary<Guid, string> guidToConfigPlatform = null;
+                       guidToConfigPlatform = new Dictionary<Guid, string> ();
+                       absolutePathToConfigPlatform = new Dictionary<string, string> ();
                        try {
                                xr = XmlReader.Create (new StringReader (solutionConfigurationContents));
-                               guidToConfigPlatform = new Dictionary<Guid, string> ();
 
                                xr.Read ();
                                while (!xr.EOF) {
@@ -65,12 +67,20 @@ namespace Microsoft.Build.Tasks {
                                                continue;
 
                                        string guid_str = xr.GetAttribute ("Project");
+                                       string abs_path = xr.GetAttribute ("AbsolutePath");
                                        string config_str = xr.ReadString ();
 
+                                       if (String.IsNullOrEmpty (config_str))
+                                               continue;
+
                                        Guid guid;
-                                       if (!String.IsNullOrEmpty (guid_str) && !String.IsNullOrEmpty (config_str) &&
-                                               TryParseGuid (guid_str, out guid))
+                                       if (TryParseGuid (guid_str, out guid))
                                                guidToConfigPlatform [guid] = config_str;
+
+                                       if (!String.IsNullOrEmpty (abs_path)) {
+                                               abs_path = Path.GetFullPath (abs_path);
+                                               absolutePathToConfigPlatform [abs_path] = config_str;
+                                       }
                                }
                        } catch (XmlException xe) {
                                Log.LogError ("XmlException while parsing SolutionConfigurationContents: {0}",
@@ -84,32 +94,22 @@ namespace Microsoft.Build.Tasks {
                        List<ITaskItem> tempAssignedProjects = new List<ITaskItem> ();
                        List<ITaskItem> tempUnassignedProjects = new List<ITaskItem> ();
                        foreach (ITaskItem item in ProjectReferences) {
-                               string config;
-
-                               string guid_str = item.GetMetadata ("Project");
+                               string config = GetConfigPlatformFromProjectReference (item);
 
-                               Guid guid = Guid.Empty;
-                               if (!string.IsNullOrEmpty(guid_str) && !TryParseGuid (guid_str, out guid)) {
-                                       Log.LogError ("Project reference '{0}' has invalid or missing guid for metadata 'Project'.",
-                                                       item.ItemSpec);
-                                       return false;
+                               if (String.IsNullOrEmpty (config)) {
+                                       tempUnassignedProjects.Add (item);
+                                       continue;
                                }
 
-                               if (guid != Guid.Empty && guidToConfigPlatform.TryGetValue (guid, out config)) {
-                                       string [] parts = config.Split (new char [] {'|'}, 2);
+                               string [] parts = config.Split (new char [] {'|'}, 2);
 
-                                       ITaskItem new_item = new TaskItem (item);
+                               ITaskItem new_item = new TaskItem (item);
 
-                                       new_item.SetMetadata ("SetConfiguration", "Configuration=" + parts [0]);
-                                       new_item.SetMetadata ("SetPlatform", "Platform=" +
-                                                       ((parts.Length > 1) ? parts [1] : String.Empty));
+                               new_item.SetMetadata ("SetConfiguration", "Configuration=" + parts [0]);
+                               new_item.SetMetadata ("SetPlatform", "Platform=" +
+                                               ((parts.Length > 1) ? parts [1] : String.Empty));
 
-                                       tempAssignedProjects.Add (new_item);
-                               } else {
-                                       Log.LogWarning ("Project reference '{0}' could not be resolved.",
-                                                       item.ItemSpec);
-                                       tempUnassignedProjects.Add (item);
-                               }
+                               tempAssignedProjects.Add (new_item);
                        }
 
                        assignedProjects = tempAssignedProjects.ToArray ();
@@ -118,9 +118,29 @@ namespace Microsoft.Build.Tasks {
                        return true;
                }
 
+               string GetConfigPlatformFromProjectReference (ITaskItem item)
+               {
+                       string guid_str = item.GetMetadata ("Project");
+                       string proj_full_path = item.GetMetadata ("FullPath");
+
+                       string config;
+                       Guid guid = Guid.Empty;
+                       if (TryParseGuid (guid_str, out guid) && guidToConfigPlatform.TryGetValue (guid, out config))
+                               return config;
+
+                       string abs_path = item.GetMetadata ("FullPath");
+                       if (absolutePathToConfigPlatform.TryGetValue (abs_path, out config))
+                               return config;
+
+                       return null;
+               }
+
                bool TryParseGuid (string guid_str, out Guid guid)
                {
                        guid = Guid.Empty;
+                       if (String.IsNullOrEmpty (guid_str))
+                               return false;
+
                        try {
                                guid = new Guid (guid_str);
                        } catch (ArgumentNullException) {
index f7d25591a8ce8973f4046ed5dbb53331841463c1..be1ea2c0fb787a177fcd0c7f659e97df04b10427 100644 (file)
@@ -32,6 +32,7 @@ using Microsoft.Build.Framework;
 using Microsoft.Build.Tasks;
 using Microsoft.Build.Utilities;
 using NUnit.Framework;
+using System.IO;
 using System.Text;
 
 namespace MonoTests.Microsoft.Build.Tasks
@@ -58,22 +59,73 @@ namespace MonoTests.Microsoft.Build.Tasks
                                "{DAE34193-B5C7-4488-A911-29EE15C84CBE}"
                        };
 
-                       CreateAndCheckProject (guids, project_ref_guids, new string[] {
-                                       "AssignedProjects : foo0.csproj;foo1.csproj;foo2.csproj;foo3.csproj: SetConfig: Configuration=Release",
+                       CreateAndCheckProject (guids, new bool[] {true, true, true, true, true, true},
+                                       project_ref_guids, new string[] {
+                                       "AssignedProjects : foo0.csproj;foo1.csproj;foo2.csproj;foo3.csproj;foo4.csproj: SetConfig: Configuration=Release",
                                        "AssignedProjects : foo0.csproj: SetPlatform: Platform=AnyCPU0",
                                        "AssignedProjects : foo1.csproj: SetPlatform: Platform=AnyCPU1",
                                        "AssignedProjects : foo2.csproj: SetPlatform: Platform=AnyCPU2",
                                        "AssignedProjects : foo3.csproj: SetPlatform: Platform=AnyCPU3",
-                                       "UnassignedProjects : foo4.csproj"},
+                                       "AssignedProjects : foo4.csproj: SetPlatform: Platform=AnyCPU4",
+                                       "UnassignedProjects : "},
                                        true,
                                         "A1#");
                }
 
                [Test]
-               public void TestInvalidProjectGuid ()
+               public void TestNoGuidAndNoAbsolutePathFound()
                {
                        string[] guids = new string[] {
+                               "asd"
+                       };
+
+                       string[] project_ref_guids = new string[] {
+                               "{DAE34193-B5C7-4488-A911-29EE15C84CB8}",
+                               "invalid guid",
+                               ""
+                       };
+
+                       CreateAndCheckProject (guids, new bool[]{false},
+                                       project_ref_guids,
+                                       new string[] {
+                                               "AssignedProjects : : SetConfig: ",
+                                               "AssignedProjects : : SetPlatform: ",
+                                               "UnassignedProjects : foo0.csproj;foo1.csproj;foo2.csproj"
+                                       },
+                                       true, "A1#");
+               }
+
+               [Test]
+               public void TestInvalidProjectGuidWithAbsolutePath ()
+               {
+                       string[] guids = new string[] {
+                               null, // no AbsPath
+                               "another invalid guid", // has AbsPath
+                       };
+
+                       string[] project_ref_guids = new string[] {
+                               "1234zxc", // this won't match because no AbsPath
+                               "xzxoiu",  // match with the second project, foo1.csproj
                                "{23F291D9-78DF-4133-8CF2-78CE104DDE63}",
+                               "badref"   // no corresponding project at all
+                       };
+
+                       CreateAndCheckProject (guids, new bool[]{false, true},
+                                       project_ref_guids,
+                                       new string[] {
+                                               "AssignedProjects : foo1.csproj: SetConfig: Configuration=Release",
+                                               "AssignedProjects : foo1.csproj: SetPlatform: Platform=AnyCPU1",
+                                               "UnassignedProjects : foo0.csproj;foo2.csproj;foo3.csproj"
+                                       },
+                                       true, "A1#");
+               }
+
+               [Test]
+               public void TestNoGuidWithAbsolutePath ()
+               {
+                       string[] guids = new string[] {
+                               "",
+                               null
                        };
 
                        string[] project_ref_guids = new string[] {
@@ -82,7 +134,14 @@ namespace MonoTests.Microsoft.Build.Tasks
                                "invalid guid"
                        };
 
-                       CreateAndCheckProject (guids, project_ref_guids, null, false, "A1#");
+                       CreateAndCheckProject (guids, new bool[]{true, false},
+                                       project_ref_guids,
+                                       new string[] {
+                                               "AssignedProjects : foo0.csproj: SetConfig: Configuration=Release",
+                                               "AssignedProjects : foo0.csproj: SetPlatform: Platform=AnyCPU0",
+                                               "UnassignedProjects : foo1.csproj;foo2.csproj"
+                                       },
+                                       true, "A1#");
                }
 
                [Test]
@@ -97,7 +156,8 @@ namespace MonoTests.Microsoft.Build.Tasks
                                "{23F291D9-78DF-4133-8CF2-78CE104DDE63}"
                        };
 
-                       CreateAndCheckProject (guids, project_ref_guids,
+                       CreateAndCheckProject (guids, new bool[]{false, true},
+                               project_ref_guids,
                                new string [] {
                                        "AssignedProjects : foo1.csproj: SetConfig: Configuration=Release",
                                        "AssignedProjects : foo1.csproj: SetPlatform: Platform=AnyCPU0",
@@ -106,14 +166,14 @@ namespace MonoTests.Microsoft.Build.Tasks
                }
 
 
-               void CreateAndCheckProject (string[] guids, string[] project_ref_guids, string[] messages, bool build_result, string prefix)
+               void CreateAndCheckProject (string[] guids, bool[] set_project_paths, string[] project_ref_guids, string[] messages, bool build_result, string prefix)
                {
                        Engine engine = new Engine (Consts.BinPath);
                        Project project = engine.CreateNewProject ();
                        TestMessageLogger testLogger = new TestMessageLogger ();
                        engine.RegisterLogger (testLogger);
 
-                       string projectString = CreateProject (guids, project_ref_guids);
+                       string projectString = CreateProject (guids, set_project_paths, project_ref_guids);
                        project.LoadXml (projectString);
 
                        try {
@@ -131,12 +191,12 @@ namespace MonoTests.Microsoft.Build.Tasks
                        }
                }
 
-               string CreateProject (string[] guids, string[] project_ref_guids)
+               string CreateProject (string[] guids, bool[] set_project_paths, string[] project_ref_guids)
                {
                        StringBuilder sb = new StringBuilder ();
                        sb.Append (@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">");
                        sb.Append ("\n" + GetUsingTask ("AssignProjectConfiguration"));
-                       sb.AppendFormat (@"<PropertyGroup>{0}</PropertyGroup>", CreateSolutionConfigurationProperty (guids, "Release|AnyCPU"));
+                       sb.AppendFormat (@"<PropertyGroup>{0}</PropertyGroup>", CreateSolutionConfigurationProperty (guids, set_project_paths, "Release|AnyCPU"));
                        sb.Append (CreateProjectReferencesItemGroup (project_ref_guids));
 
                        sb.Append ("\n\t<Target Name=\"1\">\n");
@@ -154,13 +214,19 @@ namespace MonoTests.Microsoft.Build.Tasks
                        return sb.ToString ();
                }
 
-               string CreateSolutionConfigurationProperty (string[] guids, string config_str)
+               string CreateSolutionConfigurationProperty (string[] guids, bool[] set_project_paths, string config_str)
                {
+                       string abs_proj_path_prefix = Path.GetFullPath ("foo");
                        StringBuilder sb = new StringBuilder ();
                        sb.Append ("\n<CurrentSolutionConfigurationContents>\n");
                                sb.Append ("\t<foo xmlns=\"\">\n");
                                for (int i = 0; i < guids.Length; i++) {
-                                       sb.AppendFormat ("\t\t<bar Project=\"{0}\">{1}{2}</bar>\n",
+                                       sb.Append ("\t\t<bar");
+                                       if (guids[i] != null)
+                                               sb.AppendFormat (" Project=\"{0}\"", guids[i]);
+                                       if (set_project_paths[i])
+                                               sb.AppendFormat (" AbsolutePath=\"{0}{1}.csproj\" ", abs_proj_path_prefix, i);
+                                       sb.AppendFormat (">{1}{2}</bar>\n",
                                                guids[i], config_str, i);
                                }
                                sb.Append ("\t</foo>\n");
@@ -173,8 +239,12 @@ namespace MonoTests.Microsoft.Build.Tasks
                {
                        StringBuilder sb = new StringBuilder ();
                        sb.Append ("\n<ItemGroup>\n");
-                       for (int i = 0; i < guids.Length; i ++)
-                               sb.AppendFormat ("\t<ProjectReference Include=\"foo{1}.csproj\"><Project>{0}</Project></ProjectReference>\n", guids [i], i);
+                       for (int i = 0; i < guids.Length; i ++) {
+                               sb.AppendFormat ("\t<ProjectReference Include=\"foo{0}.csproj\">", i);
+                               if (guids[i] != null)
+                                       sb.AppendFormat ("<Project>{0}</Project>", guids[i]);
+                               sb.Append ("</ProjectReference>\n");
+                       }
                        sb.Append ("</ItemGroup>\n");
                        return sb.ToString ();
                }