| File: MergeConfigurationProperties.cs | Web Access |
| Project: src\sdk\src\StaticWebAssetsSdk\Tasks\Microsoft.NET.Sdk.StaticWebAssets.Tasks.csproj (Microsoft.NET.Sdk.StaticWebAssets.Tasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using System.Text.RegularExpressions; using Microsoft.AspNetCore.StaticWebAssets.Tasks.Utils; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Microsoft.AspNetCore.StaticWebAssets.Tasks; [MSBuildMultiThreadableTask] public class MergeConfigurationProperties : Task, IMultiThreadableTask { [Required] public ITaskItem[] CandidateConfigurations { get; set; } [Required] public ITaskItem[] ProjectReferences { get; set; } [Output] public ITaskItem[] ProjectConfigurations { get; set; } public TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback; public override bool Execute() { try { ProjectConfigurations = new ITaskItem[CandidateConfigurations.Length]; for (var i = 0; i < CandidateConfigurations.Length; i++) { var configuration = CandidateConfigurations[i]; var foundProjectReference = FindMatchingProject(configuration); if (foundProjectReference == null) { Log.LogError( "Unable to find a project reference for project configuration item '{0}'", configuration.ItemSpec); return false; } var entry = new TaskItem(configuration.ItemSpec, new Dictionary<string, string> { ["Version"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.Version)), ["Source"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.Source)), ["GetBuildAssetsTargets"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.GetBuildAssetsTargets)), ["AdditionalBuildProperties"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.AdditionalBuildProperties)), ["AdditionalBuildPropertiesToRemove"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.AdditionalBuildPropertiesToRemove)), ["GetPublishAssetsTargets"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.GetPublishAssetsTargets)), ["AdditionalPublishProperties"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.AdditionalPublishProperties)), ["AdditionalPublishPropertiesToRemove"] = configuration.GetMetadata(nameof(StaticWebAssetsManifest.ReferencedProjectConfiguration.AdditionalPublishPropertiesToRemove)), }); var additionalBuildProperties = string.Join( ";", configuration.GetMetadata("AdditionalBuildProperties"), foundProjectReference.GetMetadata("SetConfiguration"), foundProjectReference.GetMetadata("SetPlatform"), foundProjectReference.GetMetadata("SetTargetFramework")); CleanupMetadata(entry, "AdditionalBuildProperties", additionalBuildProperties); var buildPropertiesToRemove = string.Join( ";", configuration.GetMetadata("AdditionalBuildPropertiesToRemove"), foundProjectReference.GetMetadata("GlobalPropertiesToRemove"), foundProjectReference.GetMetadata("UndefineProperties")); CleanupMetadata(entry, "AdditionalBuildPropertiesToRemove", buildPropertiesToRemove); var additionalPublishProperties = string.Join( ";", configuration.GetMetadata("AdditionalPublishProperties"), foundProjectReference.GetMetadata("SetConfiguration"), foundProjectReference.GetMetadata("SetPlatform"), foundProjectReference.GetMetadata("SetTargetFramework")); CleanupMetadata(entry, "AdditionalPublishProperties", additionalPublishProperties); var publishPropertiesToRemove = string.Join( ";", configuration.GetMetadata("AdditionalPublishPropertiesToRemove"), foundProjectReference.GetMetadata("GlobalPropertiesToRemove"), foundProjectReference.GetMetadata("UndefineProperties")); CleanupMetadata(entry, "AdditionalPublishPropertiesToRemove", publishPropertiesToRemove); ProjectConfigurations[i] = entry; } } catch (Exception ex) { Log.LogErrorFromException(ex, showStackTrace: true, showDetail: true, file: null); } return !Log.HasLoggedErrors; static void CleanupMetadata(TaskItem entry, string metadataName, string metadataValue) { metadataValue = Regex.Replace(metadataValue, ";{2,}", ";"); metadataValue = metadataValue.Trim(';'); entry.SetMetadata(metadataName, metadataValue); } } private ITaskItem FindMatchingProject(ITaskItem configuration) { for (var j = 0; j < ProjectReferences.Length; j++) { var projectReference = ProjectReferences[j]; var referenceMetadata = projectReference.GetMetadata("MSBuildSourceProjectFile"); // All project references should define MSBuildSourceProjectFile but in the ASP.NET Core some special (malformed) references do not. // We can be more lenient here and fallback to the project reference ItemSpec if not present. referenceMetadata = !string.IsNullOrEmpty(referenceMetadata) ? referenceMetadata : projectReference.ItemSpec; var configurationFullPath = configuration.GetMetadata("FullPath"); var projectReferenceFullPath = Path.GetFullPath((string)TaskEnvironment.GetAbsolutePath(referenceMetadata)); var matchPath = string.Equals( configurationFullPath, projectReferenceFullPath, OSPath.PathComparison); if (matchPath) { Log.LogMessage(MessageImportance.Low, "Found project reference '{0}' for configuration item '{1}'.", configurationFullPath, projectReferenceFullPath); return projectReference; } else { Log.LogMessage(MessageImportance.Low, "Rejected project reference '{0}' for configuration item '{1}' because paths don't match.", configurationFullPath, projectReferenceFullPath); } } return null; } }