From eb07877f179e6243c84cf578ab0a9d08957908a5 Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Thu, 5 Aug 2021 14:15:28 +0200 Subject: [PATCH 01/10] Add Microsoft.IO.Redist. --- eng/Packages.props | 1 + src/Directory.BeforeCommon.targets | 5 +++++ .../MSBuild.Engine.Corext/MsBuild.Engine.Corext.nuspec | 2 ++ src/Package/MSBuild.VSSetup/files.swr | 2 ++ 4 files changed, 10 insertions(+) diff --git a/eng/Packages.props b/eng/Packages.props index b4e087118a4..903336148c6 100644 --- a/eng/Packages.props +++ b/eng/Packages.props @@ -13,6 +13,7 @@ + diff --git a/src/Directory.BeforeCommon.targets b/src/Directory.BeforeCommon.targets index 913c97b1281..ce322f9833b 100644 --- a/src/Directory.BeforeCommon.targets +++ b/src/Directory.BeforeCommon.targets @@ -142,4 +142,9 @@ $(IntermediateOutputPath)\$(AssemblyName).xml + + $(DefineConstants);FEATURE_MSIOREDIST + true + + diff --git a/src/Package/MSBuild.Engine.Corext/MsBuild.Engine.Corext.nuspec b/src/Package/MSBuild.Engine.Corext/MsBuild.Engine.Corext.nuspec index 2918e172a5c..04a42dbfce4 100644 --- a/src/Package/MSBuild.Engine.Corext/MsBuild.Engine.Corext.nuspec +++ b/src/Package/MSBuild.Engine.Corext/MsBuild.Engine.Corext.nuspec @@ -31,6 +31,7 @@ + @@ -87,6 +88,7 @@ + diff --git a/src/Package/MSBuild.VSSetup/files.swr b/src/Package/MSBuild.VSSetup/files.swr index 67e5764974d..a91e00f9f34 100644 --- a/src/Package/MSBuild.VSSetup/files.swr +++ b/src/Package/MSBuild.VSSetup/files.swr @@ -32,6 +32,7 @@ folder InstallDir:\MSBuild\Current\Bin file source=$(X86BinPath)Microsoft.Build.Framework.tlb file source=$(X86BinPath)Microsoft.Build.Tasks.Core.dll vs.file.ngenApplications="[installDir]\Common7\IDE\vsn.exe" vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 file source=$(X86BinPath)Microsoft.Build.Utilities.Core.dll vs.file.ngenApplications="[installDir]\Common7\IDE\vsn.exe" vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 + file source=$(X86BinPath)Microsoft.IO.Redist.dll vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 file source=$(X86BinPath)MSBuild.exe vs.file.ngenArchitecture=x86 vs.file.ngenPriority=1 file source=$(X86BinPath)MSBuild.exe.config file source=$(TaskHostBinPath)MSBuildTaskHost.exe vs.file.ngenArchitecture=x86 @@ -184,6 +185,7 @@ folder InstallDir:\MSBuild\Current\Bin\amd64 file source=$(X86BinPath)System.Memory.dll vs.file.ngenArchitecture=all file source=$(X86BinPath)System.Text.Json.dll vs.file.ngenArchitecture=all file source=$(X86BinPath)Microsoft.Bcl.AsyncInterfaces.dll vs.file.ngenArchitecture=all + file source=$(X86BinPath)Microsoft.IO.Redist.dll vs.file.ngenArchitecture=all file source=$(X86BinPath)System.Text.Encodings.Web.dll vs.file.ngenArchitecture=all file source=$(X86BinPath)System.Threading.Tasks.Extensions.dll vs.file.ngenArchitecture=all file source=$(X86BinPath)System.Numerics.Vectors.dll vs.file.ngenArchitecture=all From eb73956558aa426a8e62fcf9a48f9f5f9fbce0dc Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Thu, 5 Aug 2021 14:38:31 +0200 Subject: [PATCH 02/10] Add Microsoft.IO.Redist to Deploy-MSBuild.ps1. --- scripts/Deploy-MSBuild.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/Deploy-MSBuild.ps1 b/scripts/Deploy-MSBuild.ps1 index 07b58d1f82d..f97b9ad94f5 100644 --- a/scripts/Deploy-MSBuild.ps1 +++ b/scripts/Deploy-MSBuild.ps1 @@ -98,6 +98,7 @@ if ($runtime -eq "Desktop") { FileToCopy "$bootstrapBinDirectory\Microsoft.Bcl.AsyncInterfaces.dll" FileToCopy "$bootstrapBinDirectory\Microsoft.Data.Entity.targets" + FileToCopy "$bootstrapBinDirectory\Microsoft.IO.Redist.dll" FileToCopy "$bootstrapBinDirectory\Microsoft.ServiceModel.targets" FileToCopy "$bootstrapBinDirectory\Microsoft.WinFx.targets" FileToCopy "$bootstrapBinDirectory\Microsoft.WorkflowBuildExtensions.targets" From 81311bdbcf551036d93889f0ada5acc23258deff Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Mon, 16 Aug 2021 16:56:56 +0200 Subject: [PATCH 03/10] Use Microsoft.IO to for enumeration in ManagedFileSystem. --- ...Microsoft.Build.Engine.OM.UnitTests.csproj | 5 ++--- src/Build/Microsoft.Build.csproj | 2 ++ ...Microsoft.Build.Framework.UnitTests.csproj | 1 + src/Framework/Properties/AssemblyInfo.cs | 1 + src/MSBuild/MSBuild.csproj | 1 + src/Shared/FileSystem/ManagedFileSystem.cs | 19 +++++++++++++++++++ src/Tasks/Microsoft.Build.Tasks.csproj | 2 ++ .../Microsoft.Build.Utilities.csproj | 1 + 8 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj b/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj index 18ad711bac4..2b992d079d3 100644 --- a/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj +++ b/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj @@ -20,6 +20,8 @@ + + @@ -35,9 +37,6 @@ - - true - EncodingStringWriter.cs diff --git a/src/Build/Microsoft.Build.csproj b/src/Build/Microsoft.Build.csproj index d08e337c5da..f7540863381 100644 --- a/src/Build/Microsoft.Build.csproj +++ b/src/Build/Microsoft.Build.csproj @@ -36,6 +36,8 @@ + + diff --git a/src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj b/src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj index b73c360d59d..4358e5a16a8 100644 --- a/src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj +++ b/src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Framework/Properties/AssemblyInfo.cs b/src/Framework/Properties/AssemblyInfo.cs index 5ab3c12ac9a..1329f5ea505 100644 --- a/src/Framework/Properties/AssemblyInfo.cs +++ b/src/Framework/Properties/AssemblyInfo.cs @@ -44,6 +44,7 @@ [assembly: InternalsVisibleTo("MSBuild, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.Build.Conversion.Core, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("Microsoft.Build.Engine.OM.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] [assembly: InternalsVisibleTo("Microsoft.Build.Engine.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] [assembly: InternalsVisibleTo("Microsoft.Build.Utilities.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] [assembly: InternalsVisibleTo("Microsoft.Build.CommandLine.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] diff --git a/src/MSBuild/MSBuild.csproj b/src/MSBuild/MSBuild.csproj index 93185ce820a..17594f48d2f 100644 --- a/src/MSBuild/MSBuild.csproj +++ b/src/MSBuild/MSBuild.csproj @@ -229,6 +229,7 @@ + diff --git a/src/Shared/FileSystem/ManagedFileSystem.cs b/src/Shared/FileSystem/ManagedFileSystem.cs index 6d8bd32fb4e..6391a36d25d 100644 --- a/src/Shared/FileSystem/ManagedFileSystem.cs +++ b/src/Shared/FileSystem/ManagedFileSystem.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using Microsoft.Build.Utilities; using System; using System.Collections.Generic; using System.IO; @@ -40,17 +41,35 @@ public byte[] ReadFileAllBytes(string path) public virtual IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) { +#if FEATURE_MSIOREDIST + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? Microsoft.IO.Directory.EnumerateFiles(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateFiles(path, searchPattern, searchOption); +#else return Directory.EnumerateFiles(path, searchPattern, searchOption); +#endif } public virtual IEnumerable EnumerateDirectories(string path, string searchPattern, SearchOption searchOption) { +#if FEATURE_MSIOREDIST + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? Microsoft.IO.Directory.EnumerateDirectories(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateDirectories(path, searchPattern, searchOption); +#else return Directory.EnumerateDirectories(path, searchPattern, searchOption); +#endif } public virtual IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption) { +#if FEATURE_MSIOREDIST + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? Microsoft.IO.Directory.EnumerateFileSystemEntries(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); +#else return Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); +#endif } public FileAttributes GetAttributes(string path) diff --git a/src/Tasks/Microsoft.Build.Tasks.csproj b/src/Tasks/Microsoft.Build.Tasks.csproj index f7c4b9555f1..69933efefbf 100644 --- a/src/Tasks/Microsoft.Build.Tasks.csproj +++ b/src/Tasks/Microsoft.Build.Tasks.csproj @@ -988,6 +988,8 @@ + + diff --git a/src/Utilities/Microsoft.Build.Utilities.csproj b/src/Utilities/Microsoft.Build.Utilities.csproj index 09634e72315..da7f065bffe 100644 --- a/src/Utilities/Microsoft.Build.Utilities.csproj +++ b/src/Utilities/Microsoft.Build.Utilities.csproj @@ -21,6 +21,7 @@ + From e3976159de085ec5ec60961fcba0a654a58d047c Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Wed, 18 Aug 2021 14:31:47 +0200 Subject: [PATCH 04/10] Fix outdated unit test. --- src/Shared/UnitTests/FileMatcher_Tests.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Shared/UnitTests/FileMatcher_Tests.cs b/src/Shared/UnitTests/FileMatcher_Tests.cs index d8cf2eeed4c..471e1536b63 100644 --- a/src/Shared/UnitTests/FileMatcher_Tests.cs +++ b/src/Shared/UnitTests/FileMatcher_Tests.cs @@ -12,6 +12,7 @@ using Microsoft.Build.Shared.FileSystem; using Xunit; using Xunit.Abstractions; +using Microsoft.Build.Utilities; namespace Microsoft.Build.UnitTests { @@ -1244,13 +1245,20 @@ public void IllegalPaths() [Fact] [PlatformSpecific(TestPlatforms.Windows)] // Nothing's too long for Unix [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp)] - public void IllegalTooLongPath() + public void IllegalTooLongPathOptOutWave17_0() { - string longString = new string('X', 500) + "*"; // need a wildcard to do anything - string[] result = FileMatcher.Default.GetFiles(@"c:\", longString); + using (var env = TestEnvironment.Create()) + { + ChangeWaves.ResetStateForTests(); + env.SetEnvironmentVariable("MSBUILDDISABLEFEATURESFROMVERSION", ChangeWaves.Wave17_0.ToString()); + BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(); - Assert.Equal(longString, result[0]); // Does not throw + string longString = new string('X', 500) + "*"; // need a wildcard to do anything + string[] result = FileMatcher.Default.GetFiles(@"c:\", longString); + Assert.Equal(longString, result[0]); // Does not throw + ChangeWaves.ResetStateForTests(); + } // Not checking that GetFileSpecMatchInfo returns the illegal-path flag, // not certain that won't break something; this fix is merely to avoid a crash. } From c80ababb79fbe020a636cc21dc3001639374ddb0 Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Thu, 19 Aug 2021 11:03:00 +0200 Subject: [PATCH 05/10] Fix Microsoft.IO.Redist version & ngen settings. --- eng/Packages.props | 2 +- src/Package/MSBuild.VSSetup/files.swr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Packages.props b/eng/Packages.props index 903336148c6..1a2171602ba 100644 --- a/eng/Packages.props +++ b/eng/Packages.props @@ -13,7 +13,7 @@ - + diff --git a/src/Package/MSBuild.VSSetup/files.swr b/src/Package/MSBuild.VSSetup/files.swr index a91e00f9f34..fc7164e4899 100644 --- a/src/Package/MSBuild.VSSetup/files.swr +++ b/src/Package/MSBuild.VSSetup/files.swr @@ -32,7 +32,7 @@ folder InstallDir:\MSBuild\Current\Bin file source=$(X86BinPath)Microsoft.Build.Framework.tlb file source=$(X86BinPath)Microsoft.Build.Tasks.Core.dll vs.file.ngenApplications="[installDir]\Common7\IDE\vsn.exe" vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 file source=$(X86BinPath)Microsoft.Build.Utilities.Core.dll vs.file.ngenApplications="[installDir]\Common7\IDE\vsn.exe" vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 - file source=$(X86BinPath)Microsoft.IO.Redist.dll vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 + file source=$(X86BinPath)Microsoft.IO.Redist.dll vs.file.ngenApplications="[installDir]\Common7\IDE\vsn.exe" vs.file.ngenApplications="[installDir]\MSBuild\Current\Bin\MSBuild.exe" vs.file.ngenArchitecture=all vs.file.ngenPriority=1 file source=$(X86BinPath)MSBuild.exe vs.file.ngenArchitecture=x86 vs.file.ngenPriority=1 file source=$(X86BinPath)MSBuild.exe.config file source=$(TaskHostBinPath)MSBuildTaskHost.exe vs.file.ngenArchitecture=x86 From 55addd2f5f894a8e5697d734b35cdd4848489699 Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Fri, 17 Sep 2021 15:34:20 +0200 Subject: [PATCH 06/10] Improve an obscure error message. --- src/Shared/FileSystem/ManagedFileSystem.cs | 55 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/Shared/FileSystem/ManagedFileSystem.cs b/src/Shared/FileSystem/ManagedFileSystem.cs index 6391a36d25d..7a12229975b 100644 --- a/src/Shared/FileSystem/ManagedFileSystem.cs +++ b/src/Shared/FileSystem/ManagedFileSystem.cs @@ -42,9 +42,24 @@ public byte[] ReadFileAllBytes(string path) public virtual IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? Microsoft.IO.Directory.EnumerateFiles(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) - : Directory.EnumerateFiles(path, searchPattern, searchOption); + try + { + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? Microsoft.IO.Directory.EnumerateFiles(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateFiles(path, searchPattern, searchOption); + } + // Microsoft.IO.Redist has a dependency on System.Buffers and if it is not found these lines throw an exception. + // However, FileMatcher class that calls it do not allow to fail on IO exceptions. + // We rethrow it to make it fail with a proper error message and call stack. + catch (FileLoadException ex) + { + throw new InvalidOperationException("Could not load file or assembly.", ex); + } + // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it has FusionLog. + catch (FileNotFoundException ex) when (ex.FusionLog != null) + { + throw new InvalidOperationException("Could not load file or assembly.", ex); + } #else return Directory.EnumerateFiles(path, searchPattern, searchOption); #endif @@ -53,9 +68,24 @@ public virtual IEnumerable EnumerateFiles(string path, string searchPatt public virtual IEnumerable EnumerateDirectories(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + try + { + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) ? Microsoft.IO.Directory.EnumerateDirectories(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) : Directory.EnumerateDirectories(path, searchPattern, searchOption); + } + // Microsoft.IO.Redist has a dependency on System.Buffers and if it is not found these lines throw an exception. + // However, FileMatcher class that calls it do not allow to fail on IO exceptions. + // We rethrow it to make it fail with a proper error message and call stack. + catch (FileLoadException ex) + { + throw new InvalidOperationException("Could not load file or assembly.", ex); + } + // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it has FusionLog. + catch (FileNotFoundException ex) when (ex.FusionLog != null) + { + throw new InvalidOperationException("Could not load file or assembly.", ex); + } #else return Directory.EnumerateDirectories(path, searchPattern, searchOption); #endif @@ -64,9 +94,24 @@ public virtual IEnumerable EnumerateDirectories(string path, string sear public virtual IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + try + { + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) ? Microsoft.IO.Directory.EnumerateFileSystemEntries(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) : Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); + } + // Microsoft.IO.Redist has a dependency on System.Buffers and if it is not found these lines throw an exception. + // However, FileMatcher class that calls it do not allow to fail on IO exceptions. + // We rethrow it to make it fail with a proper error message and call stack. + catch (FileLoadException ex) + { + throw new InvalidOperationException("Could not load file or assembly.", ex); + } + // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it has FusionLog. + catch (FileNotFoundException ex) when (ex.FusionLog != null) + { + throw new InvalidOperationException("Could not load file or assembly.", ex); + } #else return Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); #endif From 1a37ff2b4f5d4f83445eccd4c32fb50cba2dd4c5 Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:32:44 +0200 Subject: [PATCH 07/10] Move try-catch block to a separate function. --- src/Shared/FileSystem/ManagedFileSystem.cs | 70 ++++++++-------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/src/Shared/FileSystem/ManagedFileSystem.cs b/src/Shared/FileSystem/ManagedFileSystem.cs index 7a12229975b..9ba49ffccdf 100644 --- a/src/Shared/FileSystem/ManagedFileSystem.cs +++ b/src/Shared/FileSystem/ManagedFileSystem.cs @@ -39,27 +39,39 @@ public byte[] ReadFileAllBytes(string path) return File.ReadAllBytes(path); } - public virtual IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) - { #if FEATURE_MSIOREDIST + private IEnumerable HandleFileLoadException( + Func> enumerateFunctionDelegate, + string path, + string searchPattern, + Microsoft.IO.SearchOption searchOption + ) + { try { - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? Microsoft.IO.Directory.EnumerateFiles(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) - : Directory.EnumerateFiles(path, searchPattern, searchOption); + return enumerateFunctionDelegate(path, searchPattern, searchOption); } - // Microsoft.IO.Redist has a dependency on System.Buffers and if it is not found these lines throw an exception. - // However, FileMatcher class that calls it do not allow to fail on IO exceptions. + // Microsoft.IO.Redist has a dependency on System.Buffers and if System.Buffers assembly is not found the line above throws an exception. + // However, FileMatcher class (that in most cases calls the enumeration) does not allow to fail on a IO-related exception. Such behavior hides the actual exception and makes it obscure. // We rethrow it to make it fail with a proper error message and call stack. catch (FileLoadException ex) { throw new InvalidOperationException("Could not load file or assembly.", ex); } - // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it has FusionLog. + // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it should have FusionLog. catch (FileNotFoundException ex) when (ex.FusionLog != null) { throw new InvalidOperationException("Could not load file or assembly.", ex); } + } +#endif + + public virtual IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) + { +#if FEATURE_MSIOREDIST + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? HandleFileLoadException(Microsoft.IO.Directory.EnumerateFiles, path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateFiles(path, searchPattern, searchOption); #else return Directory.EnumerateFiles(path, searchPattern, searchOption); #endif @@ -68,24 +80,9 @@ public virtual IEnumerable EnumerateFiles(string path, string searchPatt public virtual IEnumerable EnumerateDirectories(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - try - { - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? Microsoft.IO.Directory.EnumerateDirectories(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) - : Directory.EnumerateDirectories(path, searchPattern, searchOption); - } - // Microsoft.IO.Redist has a dependency on System.Buffers and if it is not found these lines throw an exception. - // However, FileMatcher class that calls it do not allow to fail on IO exceptions. - // We rethrow it to make it fail with a proper error message and call stack. - catch (FileLoadException ex) - { - throw new InvalidOperationException("Could not load file or assembly.", ex); - } - // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it has FusionLog. - catch (FileNotFoundException ex) when (ex.FusionLog != null) - { - throw new InvalidOperationException("Could not load file or assembly.", ex); - } + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? HandleFileLoadException(Microsoft.IO.Directory.EnumerateDirectories, path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateDirectories(path, searchPattern, searchOption); #else return Directory.EnumerateDirectories(path, searchPattern, searchOption); #endif @@ -94,24 +91,9 @@ public virtual IEnumerable EnumerateDirectories(string path, string sear public virtual IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - try - { - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? Microsoft.IO.Directory.EnumerateFileSystemEntries(path, searchPattern, (Microsoft.IO.SearchOption)searchOption) - : Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); - } - // Microsoft.IO.Redist has a dependency on System.Buffers and if it is not found these lines throw an exception. - // However, FileMatcher class that calls it do not allow to fail on IO exceptions. - // We rethrow it to make it fail with a proper error message and call stack. - catch (FileLoadException ex) - { - throw new InvalidOperationException("Could not load file or assembly.", ex); - } - // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it has FusionLog. - catch (FileNotFoundException ex) when (ex.FusionLog != null) - { - throw new InvalidOperationException("Could not load file or assembly.", ex); - } + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + ? HandleFileLoadException(Microsoft.IO.Directory.EnumerateFileSystemEntries, path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + : Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); #else return Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); #endif From fc9d8b162a5fb7478f6c7986e8f29d1afdfd477f Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Thu, 7 Oct 2021 13:40:07 +0200 Subject: [PATCH 08/10] Address PR comments. --- src/Shared/FileSystem/ManagedFileSystem.cs | 28 ++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Shared/FileSystem/ManagedFileSystem.cs b/src/Shared/FileSystem/ManagedFileSystem.cs index 9ba49ffccdf..69ca0f81e05 100644 --- a/src/Shared/FileSystem/ManagedFileSystem.cs +++ b/src/Shared/FileSystem/ManagedFileSystem.cs @@ -40,7 +40,7 @@ public byte[] ReadFileAllBytes(string path) } #if FEATURE_MSIOREDIST - private IEnumerable HandleFileLoadException( + private static IEnumerable HandleFileLoadException( Func> enumerateFunctionDelegate, string path, string searchPattern, @@ -56,12 +56,12 @@ Microsoft.IO.SearchOption searchOption // We rethrow it to make it fail with a proper error message and call stack. catch (FileLoadException ex) { - throw new InvalidOperationException("Could not load file or assembly.", ex); + throw new InvalidOperationException(ex.Message, ex); } // Sometimes FileNotFoundException is thrown when there is an assembly load failure. In this case it should have FusionLog. catch (FileNotFoundException ex) when (ex.FusionLog != null) { - throw new InvalidOperationException("Could not load file or assembly.", ex); + throw new InvalidOperationException(ex.Message, ex); } } #endif @@ -70,8 +70,13 @@ public virtual IEnumerable EnumerateFiles(string path, string searchPatt { #if FEATURE_MSIOREDIST return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? HandleFileLoadException(Microsoft.IO.Directory.EnumerateFiles, path, searchPattern, (Microsoft.IO.SearchOption)searchOption) - : Directory.EnumerateFiles(path, searchPattern, searchOption); + ? HandleFileLoadException( + (path, searchPattern, searchOption) => Microsoft.IO.Directory.EnumerateFiles(path, searchPattern, searchOption), + path, + searchPattern, + (Microsoft.IO.SearchOption)searchOption + ) + : Directory.EnumerateFiles(path, searchPattern, searchOption); #else return Directory.EnumerateFiles(path, searchPattern, searchOption); #endif @@ -81,7 +86,12 @@ public virtual IEnumerable EnumerateDirectories(string path, string sear { #if FEATURE_MSIOREDIST return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? HandleFileLoadException(Microsoft.IO.Directory.EnumerateDirectories, path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + ? HandleFileLoadException( + (path, searchPattern, searchOption) => Microsoft.IO.Directory.EnumerateDirectories(path, searchPattern, searchOption), + path, + searchPattern, + (Microsoft.IO.SearchOption)searchOption + ) : Directory.EnumerateDirectories(path, searchPattern, searchOption); #else return Directory.EnumerateDirectories(path, searchPattern, searchOption); @@ -92,7 +102,11 @@ public virtual IEnumerable EnumerateFileSystemEntries(string path, strin { #if FEATURE_MSIOREDIST return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? HandleFileLoadException(Microsoft.IO.Directory.EnumerateFileSystemEntries, path, searchPattern, (Microsoft.IO.SearchOption)searchOption) + ? HandleFileLoadException( + (path, searchPattern, searchOption) => Microsoft.IO.Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption), + path, + searchPattern, (Microsoft.IO.SearchOption)searchOption + ) : Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); #else return Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption); From 5e1ae3f13af0fc7036d08cd2bdaa91b4e269dde9 Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:33:27 +0200 Subject: [PATCH 09/10] Remove IVT to Microsoft.Build.Engine.OM.UnitTests. --- .../Microsoft.Build.Engine.OM.UnitTests.csproj | 3 +++ src/Framework/Properties/AssemblyInfo.cs | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj b/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj index 2b992d079d3..378c5127883 100644 --- a/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj +++ b/src/Build.OM.UnitTests/Microsoft.Build.Engine.OM.UnitTests.csproj @@ -37,6 +37,9 @@ + + true + EncodingStringWriter.cs diff --git a/src/Framework/Properties/AssemblyInfo.cs b/src/Framework/Properties/AssemblyInfo.cs index 1329f5ea505..5ab3c12ac9a 100644 --- a/src/Framework/Properties/AssemblyInfo.cs +++ b/src/Framework/Properties/AssemblyInfo.cs @@ -44,7 +44,6 @@ [assembly: InternalsVisibleTo("MSBuild, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.Build.Conversion.Core, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] -[assembly: InternalsVisibleTo("Microsoft.Build.Engine.OM.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] [assembly: InternalsVisibleTo("Microsoft.Build.Engine.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] [assembly: InternalsVisibleTo("Microsoft.Build.Utilities.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] [assembly: InternalsVisibleTo("Microsoft.Build.CommandLine.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")] From d6b2109bef8ba582dc31a08985be4cbbffd4ea4c Mon Sep 17 00:00:00 2001 From: AR-May <67507805+AR-May@users.noreply.github.com> Date: Thu, 14 Oct 2021 13:36:16 +0200 Subject: [PATCH 10/10] Workaround the sanity check breaking. --- src/Shared/FileSystem/ManagedFileSystem.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Shared/FileSystem/ManagedFileSystem.cs b/src/Shared/FileSystem/ManagedFileSystem.cs index 69ca0f81e05..d5d80a07e35 100644 --- a/src/Shared/FileSystem/ManagedFileSystem.cs +++ b/src/Shared/FileSystem/ManagedFileSystem.cs @@ -17,6 +17,20 @@ internal class ManagedFileSystem : IFileSystem public static ManagedFileSystem Singleton() => ManagedFileSystem.Instance; + private static bool ShouldUseMicrosoftIO + { + get + { +#if !MICROSOFT_BUILD_ENGINE_OM_UNITTESTS + return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0); +#else + // We need to mock usage of ChangeWaves class, + // because Microsoft.Build.Engine.OM.UnitTests should not have access to internals of Microsoft.Build.Framework. + return true; +#endif + } + } + protected ManagedFileSystem() { } public TextReader ReadFile(string path) @@ -69,7 +83,7 @@ Microsoft.IO.SearchOption searchOption public virtual IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + return ShouldUseMicrosoftIO ? HandleFileLoadException( (path, searchPattern, searchOption) => Microsoft.IO.Directory.EnumerateFiles(path, searchPattern, searchOption), path, @@ -85,7 +99,7 @@ public virtual IEnumerable EnumerateFiles(string path, string searchPatt public virtual IEnumerable EnumerateDirectories(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + return ShouldUseMicrosoftIO ? HandleFileLoadException( (path, searchPattern, searchOption) => Microsoft.IO.Directory.EnumerateDirectories(path, searchPattern, searchOption), path, @@ -101,7 +115,7 @@ public virtual IEnumerable EnumerateDirectories(string path, string sear public virtual IEnumerable EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption) { #if FEATURE_MSIOREDIST - return ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) + return ShouldUseMicrosoftIO ? HandleFileLoadException( (path, searchPattern, searchOption) => Microsoft.IO.Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption), path,