Fix duplicate dependency issue (#2597)

* Fix duplicate dependency issue
If a package has the same name as a framework assembly in the dependency
graph, we usually replace it with the framework assembly if the package
provides no assets. If the framework assembly wasn't resolved, it would
skip this logic and end up adding dupes to the list, which blows up later on.
This is a tactical fix to solve the issue, we need to do some more thinking
to determine how we want to resolve conflicts between framework assemblies,
packages and dlls with the same name.
This commit is contained in:
David Fowler 2016-04-21 09:05:55 -07:00
parent 8313400465
commit 4af795b9e8
5 changed files with 62 additions and 14 deletions

View file

@ -0,0 +1,10 @@
namespace TestMicrosoftCSharpReference
{
public class Program
{
public static int Main(string[] args)
{
return 0;
}
}
}

View file

@ -0,0 +1,17 @@
{
"version": "1.0.0",
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50",
"dependencies": {
"Microsoft.NETCore.App": "1.0.0-rc2-*"
}
},
"net99": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-rc2-24018"
}
}
}
}

View file

@ -36,6 +36,8 @@ namespace Microsoft.DotNet.ProjectModel
public override IEnumerable<LockFileItem> CompileTimeAssemblies => FilterPlaceholders(base.CompileTimeAssemblies);
public bool HasCompileTimePlaceholder => base.CompileTimeAssemblies.Any(a => PackageDependencyProvider.IsPlaceholderFile(a));
private static IEnumerable<LockFileItem> FilterPlaceholders(IEnumerable<LockFileItem> items)
{
return items.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a));

View file

@ -377,22 +377,28 @@ namespace Microsoft.DotNet.ProjectModel
// To make them work seamlessly on those platforms, we fill the gap with a reference
// assembly (if available)
var package = library as PackageDescription;
if (package != null && package.Resolved && !package.CompileTimeAssemblies.Any())
if (package != null &&
package.Resolved &&
package.HasCompileTimePlaceholder &&
!TargetFramework.IsPackageBased)
{
var replacement = referenceAssemblyDependencyResolver.GetDescription(new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly), TargetFramework);
if (replacement?.Resolved == true)
var newKey = new LibraryKey(library.Identity.Name, LibraryType.ReferenceAssembly);
var dependency = new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly);
// If the framework assembly can't be resolved then mark it as unresolved but still replace the package
// dependency
var replacement = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ??
UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
requiresFrameworkAssemblies = true;
// Remove the original package reference
libraries.Remove(pair.Key);
// Insert a reference assembly key if there isn't one
if (!libraries.ContainsKey(newKey))
{
requiresFrameworkAssemblies = true;
// Remove the original package reference
libraries.Remove(pair.Key);
// Insert a reference assembly key if there isn't one
var key = new LibraryKey(replacement.Identity.Name, LibraryType.ReferenceAssembly);
if (!libraries.ContainsKey(key))
{
libraries[key] = replacement;
}
libraries[newKey] = replacement;
}
}
}

View file

@ -65,5 +65,18 @@ namespace Microsoft.DotNet.ProjectModel.Tests
Assert.Equal(4, context.RootProject.Dependencies.Count());
}
[Fact]
public void NoDuplicateReferencesWhenFrameworkMissing()
{
var instance = TestAssetsManager.CreateTestInstance("TestMicrosoftCSharpReferenceMissingFramework")
.WithLockFiles();
var context = new ProjectContextBuilder().WithProjectDirectory(instance.TestRoot)
.WithTargetFramework("net99")
.Build();
context.LibraryManager.GetLibraries().ToDictionary(l => l.Identity.Name);
}
}
}