From dec4a0627ff89b8c4eb19dcd31aa9096eed122e2 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 23 Feb 2016 02:34:27 -0800 Subject: [PATCH] Fix asset copy on publish when lock file instance is shared - Don't mutate the library target when making a package description. #1528 --- .../Compilation/LibraryExporter.cs | 6 +-- .../PackageDescription.cs | 21 ++++++++- .../ProjectContextBuilder.cs | 2 +- .../Resolution/PackageDependencyProvider.cs | 9 ++-- src/dotnet/commands/dotnet-restore/Program.cs | 2 +- .../PackageDependencyProviderTests.cs | 44 +++++++++++++++++++ 6 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index b995b6791..706d16ab0 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -157,13 +157,13 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private LibraryExport ExportPackage(PackageDescription package) { var nativeLibraries = new List(); - PopulateAssets(package, package.Target.NativeLibraries, nativeLibraries); + PopulateAssets(package, package.NativeLibraries, nativeLibraries); var runtimeAssemblies = new List(); - PopulateAssets(package, package.Target.RuntimeAssemblies, runtimeAssemblies); + PopulateAssets(package, package.RuntimeAssemblies, runtimeAssemblies); var compileAssemblies = new List(); - PopulateAssets(package, package.Target.CompileTimeAssemblies, compileAssemblies); + PopulateAssets(package, package.CompileTimeAssemblies, compileAssemblies); var sourceReferences = new List(); foreach (var sharedSource in GetSharedSources(package)) diff --git a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs index 9fcd6f7f2..b66d8a941 100644 --- a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs +++ b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs @@ -1,8 +1,11 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; +using System.Linq; using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Resolution; namespace Microsoft.DotNet.ProjectModel { @@ -27,7 +30,21 @@ namespace Microsoft.DotNet.ProjectModel Target = lockFileLibrary; } - public LockFileTargetLibrary Target { get; set; } - public LockFilePackageLibrary Library { get; set; } + private LockFileTargetLibrary Target { get; } + + public LockFilePackageLibrary Library { get; } + + public IEnumerable RuntimeAssemblies => FilterPlaceholders(Target.RuntimeAssemblies); + + public IEnumerable CompileTimeAssemblies => FilterPlaceholders(Target.CompileTimeAssemblies); + + public IEnumerable ResourceAssemblies => Target.ResourceAssemblies; + + public IEnumerable NativeLibraries => Target.NativeLibraries; + + private IEnumerable FilterPlaceholders(IList items) + { + return items.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a)); + } } } diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs index 9f0a20c90..720e13dca 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs @@ -285,7 +285,7 @@ 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.Target.CompileTimeAssemblies.Any()) + if (package != null && package.Resolved && !package.CompileTimeAssemblies.Any()) { var replacement = referenceAssemblyDependencyResolver.GetDescription(new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly), TargetFramework); if (replacement?.Resolved == true) diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs index 56022fb66..611c2604b 100644 --- a/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs +++ b/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs @@ -42,10 +42,6 @@ namespace Microsoft.DotNet.ProjectModel.Resolution var path = _packagePathResolver.GetInstallPath(package.Name, package.Version); - // Remove place holders - targetLibrary.CompileTimeAssemblies = targetLibrary.CompileTimeAssemblies.Where(item => !IsPlaceholderFile(item.Path)).ToList(); - targetLibrary.RuntimeAssemblies = targetLibrary.RuntimeAssemblies.Where(item => !IsPlaceholderFile(item.Path)).ToList(); - // If the package's compile time assemblies is for a portable profile then, read the assembly metadata // and turn System.* references into reference assembly dependencies PopulateLegacyPortableDependencies(targetFramework, dependencies, path, targetLibrary); @@ -66,6 +62,11 @@ namespace Microsoft.DotNet.ProjectModel.Resolution foreach (var assembly in targetLibrary.CompileTimeAssemblies) { + if (IsPlaceholderFile(assembly)) + { + continue; + } + // (ref/lib)/{tfm}/{assembly} var pathParts = assembly.Path.Split(Path.DirectorySeparatorChar); diff --git a/src/dotnet/commands/dotnet-restore/Program.cs b/src/dotnet/commands/dotnet-restore/Program.cs index 6ea9454ee..d26d7d1da 100644 --- a/src/dotnet/commands/dotnet-restore/Program.cs +++ b/src/dotnet/commands/dotnet-restore/Program.cs @@ -159,7 +159,7 @@ namespace Microsoft.DotNet.Tools.Restore var depsPath = Path.Combine( toolDescription.Path, - Path.GetDirectoryName(toolDescription.Target.RuntimeAssemblies.First().Path), + Path.GetDirectoryName(toolDescription.RuntimeAssemblies.First().Path), toolDescription.Identity.Name + FileNameSuffixes.Deps); var calculator = context.GetOutputPaths(Constants.DefaultConfiguration, buidBasePath: null, outputPath: context.ProjectDirectory); diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs new file mode 100644 index 000000000..26e005dcf --- /dev/null +++ b/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Resolution; +using NuGet.Frameworks; +using NuGet.Versioning; +using Xunit; + +namespace Microsoft.DotNet.ProjectModel.Tests +{ + public class PackageDependencyProviderTests + { + [Fact] + public void GetDescriptionShouldNotModifyTarget() + { + var provider = new PackageDependencyProvider("/foo/packages", new FrameworkReferenceResolver("/foo/references")); + var package = new LockFilePackageLibrary(); + package.Name = "Something"; + package.Version = NuGetVersion.Parse("1.0.0"); + package.Files.Add("lib/dotnet/_._"); + package.Files.Add("runtimes/any/native/Microsoft.CSharp.CurrentVersion.targets"); + + var target = new LockFileTargetLibrary(); + target.Name = "Something"; + target.Version = package.Version; + + target.RuntimeAssemblies.Add("lib/dotnet/_._"); + target.CompileTimeAssemblies.Add("lib/dotnet/_._"); + target.NativeLibraries.Add("runtimes/any/native/Microsoft.CSharp.CurrentVersion.targets"); + + var p1 = provider.GetDescription(NuGetFramework.Parse("dnxcore50"), package, target); + var p2 = provider.GetDescription(NuGetFramework.Parse("dnxcore50"), package, target); + + Assert.True(p1.Compatible); + Assert.True(p2.Compatible); + + Assert.Empty(p1.CompileTimeAssemblies); + Assert.Empty(p1.RuntimeAssemblies); + + Assert.Empty(p2.CompileTimeAssemblies); + Assert.Empty(p2.RuntimeAssemblies); + } + } +}