diff --git a/src/Microsoft.DotNet.ProjectJsonMigration/Transforms/ItemTransformApplicator.cs b/src/Microsoft.DotNet.ProjectJsonMigration/Transforms/ItemTransformApplicator.cs index 258fbe9e5..9fabbc316 100644 --- a/src/Microsoft.DotNet.ProjectJsonMigration/Transforms/ItemTransformApplicator.cs +++ b/src/Microsoft.DotNet.ProjectJsonMigration/Transforms/ItemTransformApplicator.cs @@ -273,8 +273,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms mergedItem.UnionExcludes(existingItem.Excludes()); mergedItem.UnionExcludes(item.Excludes()); - mergedItem.AddMetadata(existingItem.Metadata); - mergedItem.AddMetadata(item.Metadata); + mergedItem.AddMetadata(MergeMetadata(existingItem.Metadata, item.Metadata)); item.RemoveIncludes(commonIncludes); existingItem.RemoveIncludes(commonIncludes); @@ -289,6 +288,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms return mergeResult; } + private ICollection MergeMetadata( + ICollection existingMetadataElements, + ICollection newMetadataElements) + { + var mergedMetadata = new List(existingMetadataElements); + + foreach (var newMetadata in newMetadataElements) + { + var existingMetadata = mergedMetadata.FirstOrDefault(m => + m.Name.Equals(newMetadata.Name, StringComparison.OrdinalIgnoreCase)); + if (existingMetadata == null) + { + mergedMetadata.Add(newMetadata); + } + else + { + MergeMetadata(existingMetadata, newMetadata); + } + } + + return mergedMetadata; + } + + public void MergeMetadata(ProjectMetadataElement existingMetadata, ProjectMetadataElement newMetadata) + { + if (existingMetadata.Value != newMetadata.Value) + { + existingMetadata.Value = string.Join(";", new [] { existingMetadata.Value, newMetadata.Value }); + } + } + private IEnumerable FindExistingItemsWithSameCondition( ProjectItemElement item, ProjectRootElement project, diff --git a/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigratePackOptions.cs b/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigratePackOptions.cs index a76aa7d28..e88dd1816 100644 --- a/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigratePackOptions.cs +++ b/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigratePackOptions.cs @@ -260,6 +260,40 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests contentItems.First().GetMetadataWithName("PackagePath").Value.Should().BeEmpty(); } + [Fact] + public void Migrating_same_file_with_multiple_mappings_string_joins_the_mappings_in_PackagePath() + { + var mockProj = RunPackOptionsRuleOnPj(@" + { + ""packOptions"": { + ""files"": { + ""include"": [""path/to/some/file.cs""], + ""mappings"": { + ""other/path/file.cs"": ""path/to/some/file.cs"", + ""different/path/file1.cs"": ""path/to/some/file.cs"" + } + } + } + }"); + + var expectedPackagePath = string.Join( + ";", + new [] { + Path.Combine("different", "path"), + Path.Combine("other", "path") + }); + + var contentItems = mockProj.Items + .Where(item => item.ItemType.Equals("Content", StringComparison.Ordinal)) + .Where(item => + item.GetMetadataWithName("Pack").Value == "true" && + item.GetMetadataWithName("PackagePath") != null); + + contentItems.Count().Should().Be(1); + contentItems.First().Include.Should().Be(@"path\to\some\file.cs"); + contentItems.First().GetMetadataWithName("PackagePath").Value.Should().Be(expectedPackagePath); + } + private ProjectRootElement RunPackOptionsRuleOnPj(string packOptions, string testDirectory = null) { testDirectory = testDirectory ?? Temp.CreateDirectory().Path;