Merge pull request #2137 from dotnet/pakrym/redirects

Handle duplicated assemblies in binding redirects
This commit is contained in:
Pavel Krymets 2016-03-30 15:35:15 -07:00
commit d3289d916f
4 changed files with 93 additions and 14 deletions

View file

@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
private static SHA1 Sha1 { get; } = SHA1.Create();
internal static XDocument GenerateBindingRedirects(this IEnumerable<LibraryExport> dependencies, XDocument document)
public static XDocument GenerateBindingRedirects(this IEnumerable<LibraryExport> dependencies, XDocument document)
{
var redirects = CollectRedirects(dependencies);
@ -107,23 +107,34 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
return element;
}
private static AssemblyRedirect[] CollectRedirects(IEnumerable<LibraryExport> dependencies)
internal static AssemblyRedirect[] CollectRedirects(IEnumerable<LibraryExport> dependencies)
{
var allRuntimeAssemblies = dependencies
var runtimeAssemblies = dependencies
.SelectMany(d => d.RuntimeAssemblyGroups.GetDefaultAssets())
.Select(GetAssemblyInfo)
.ToArray();
.Select(GetAssemblyInfo);
var assemblyLookup = allRuntimeAssemblies.ToDictionary(r => r.Identity.ToLookupKey());
return CollectRedirects(runtimeAssemblies);
}
internal static AssemblyRedirect[] CollectRedirects(IEnumerable<AssemblyReferenceInfo> runtimeAssemblies)
{
var assemblyLookup = runtimeAssemblies.ToLookup(r => r.Identity.ToLookupKey());
var redirectAssemblies = new HashSet<AssemblyRedirect>();
foreach (var assemblyReferenceInfo in allRuntimeAssemblies)
foreach (var assemblyReferenceInfo in assemblyLookup)
{
foreach (var referenceIdentity in assemblyReferenceInfo.References)
// Using .First here is not exactly valid, but we don't know which one gets copied to
// output so we just use first
var references = assemblyReferenceInfo.First().References;
foreach (var referenceIdentity in references)
{
AssemblyReferenceInfo targetAssemblyIdentity;
if (assemblyLookup.TryGetValue(referenceIdentity.ToLookupKey(), out targetAssemblyIdentity)
&& targetAssemblyIdentity.Identity.Version != referenceIdentity.Version)
var targetAssemblies = assemblyLookup[referenceIdentity.ToLookupKey()];
if (!targetAssemblies.Any())
{
continue;
}
var targetAssemblyIdentity = targetAssemblies.First();
if (targetAssemblyIdentity.Identity.Version != referenceIdentity.Version)
{
if (targetAssemblyIdentity.Identity.PublicKeyToken != null)
{
@ -200,7 +211,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
return hex.ToString();
}
private struct AssemblyRedirect
internal struct AssemblyRedirect
{
public AssemblyRedirect(AssemblyIdentity from, AssemblyIdentity to)
{
@ -213,7 +224,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
public AssemblyIdentity To { get; set; }
}
private struct AssemblyIdentity
internal struct AssemblyIdentity
{
public AssemblyIdentity(string name, Version version, string culture, string publicKeyToken)
{
@ -239,7 +250,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
}
}
private struct AssemblyReferenceInfo
internal struct AssemblyReferenceInfo
{
public AssemblyReferenceInfo(AssemblyIdentity identity, AssemblyIdentity[] references)
{

View file

@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("dotnet-compile.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.Cli.Compiler.Common;
using Xunit;
using FluentAssertions;
using AssemblyReferenceInfo = Microsoft.DotNet.Cli.Compiler.Common.BindingRedirectGenerator.AssemblyReferenceInfo;
using AssemblyIdentity = Microsoft.DotNet.Cli.Compiler.Common.BindingRedirectGenerator.AssemblyIdentity;
namespace Microsoft.DotNet.Tools.Compiler.Tests
{
public class BindingRedirectGeneratorTests
{
[Fact]
public void ResolvesDuplicatesUsingFirstOccurence()
{
var hash = "01234qwerty";
var redirects = BindingRedirectGenerator.CollectRedirects(new[]
{
new AssemblyReferenceInfo(
new AssemblyIdentity("A", new Version(1, 5), "en-US", hash),
new []
{
new AssemblyIdentity("B", new Version(1, 1), "en-US", hash),
}
),
new AssemblyReferenceInfo(
new AssemblyIdentity("B", new Version(1, 4), "en-US", hash), new AssemblyIdentity[] {}
),
new AssemblyReferenceInfo(
new AssemblyIdentity("B", new Version(1, 5), "en-US", hash), new AssemblyIdentity[] {}
),
new AssemblyReferenceInfo(
new AssemblyIdentity("C", new Version(1, 5), "en-US", hash),
new []
{
new AssemblyIdentity("B", new Version(1, 3), "en-US", hash),
}
)
});
redirects.Should().HaveCount(2);
redirects.Should().Contain(r =>
r.From.Version == new Version(1, 1) &&
r.From.Name == "B" &&
r.To.Version == new Version(1, 4) &&
r.To.Name == "B"
);
redirects.Should().Contain(r =>
r.From.Version == new Version(1, 3) &&
r.From.Name == "B" &&
r.To.Version == new Version(1, 4) &&
r.To.Name == "B"
);
}
}
}

View file

@ -1,9 +1,15 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
"Microsoft.DotNet.Cli.Utils": {
"target": "project"
},
"Microsoft.DotNet.Compiler.Common": {
"target": "project"
},
"dotnet": {
"target": "project"
},