diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs index e15b75020f9d..5a849a3042e7 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs @@ -144,9 +144,6 @@ public static IEnumerable ProjectData new object[] { "dotnet.new", "1.0.0", null, "dotnet.new.resources", null, dotnetNewSatelliteAssemblies, null, null, null }, new object[] { "simple.dependencies", "1.0.0", null, "simple.dependencies", null, null, null, null, resolvedNuGetFiles }, }; - - - } } @@ -190,11 +187,16 @@ public void ItDoesntCreateReferenceAssembliesWhenNoCompilationOptions() .RuntimeLibraries .SelectMany(l => l.Dependencies) .Should() - .NotBeEmpty() - .And - .NotContain(d => d.Name == "System.NotConflicting") - .And - .NotContain(d => d.Name == "System.Collections.NonGeneric.Reference"); + .BeEmpty(); + } + + [Fact] + public void ItDoesntCreateKeepUnneededRuntimeReferences() + { + DependencyContext dependencyContext = BuildDependencyContextWithReferenceAssemblies(useCompilationOptions: false); + + dependencyContext.RuntimeLibraries.Count.Should().Be(1); + dependencyContext.RuntimeLibraries[0].Name.Should().Be("simple.dependencies"); // This is the entrypoint } [Fact] @@ -213,6 +215,188 @@ public void ItHandlesReferenceAndPackageReferenceNameCollisions() .Contain(c => c.Name == "System.Collections.NonGeneric.Reference.Reference" && c.Type == "referenceassembly"); } + // If an assembly is in withResources, it has to be a key in dependencies, even with an empty list. + private static DependencyContext BuildDependencyContextFromDependenciesWithResources(Dictionary> dependencies, List withResources, List references, bool dllReference) + { + string mainProjectName = "simpleApp"; + LockFile lockFile = TestLockFiles.GetLockFile(mainProjectName); + + SingleProjectInfo mainProject = SingleProjectInfo.Create( + "/usr/Path", + mainProjectName, + ".dll", + "1.0.0", + []); + string mainProjectDirectory = Path.GetDirectoryName(mainProject.ProjectPath); + + + ITaskItem[] referencePaths = dllReference ? references.Select(reference => + new MockTaskItem($"/usr/Path/{reference}.dll", new Dictionary { + { "CopyLocal", "false" }, + { "FusionName", $"{reference}, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null" }, + { "Version", "" }, + })).ToArray() : []; + + ProjectContext projectContext = lockFile.CreateProjectContext( + FrameworkConstants.CommonFrameworks.Net10_0.GetShortFolderName(), + runtime: null, + platformLibraryName: Constants.DefaultPlatformLibrary, + runtimeFrameworks: null, + isSelfContained: false); + + if (!dllReference) + { + projectContext.LockFile.ProjectFileDependencyGroups.Add(new ProjectFileDependencyGroup(string.Empty, references)); + } + + Dictionary referenceProjectInfos = new(); + + foreach (KeyValuePair> kvp in dependencies) + { + projectContext.LockFileTarget.Libraries = projectContext.LockFileTarget.Libraries.Concat([ + new LockFileTargetLibrary() + { + Name = kvp.Key, + Version = new NuGetVersion(4, 0, 0), + Type = withResources.Contains(kvp.Key) ? "project" : "unrealType", + Dependencies = kvp.Value.Select(n => new PackageDependency(n)).ToList() + }]).ToList(); + + if (withResources.Contains(kvp.Key)) + { + var fullPath = Path.GetFullPath(Path.Combine(mainProjectDirectory, kvp.Key)); + lockFile.Libraries = lockFile.Libraries.Concat([new LockFileLibrary() + { + Name = kvp.Key, + Version = new NuGetVersion(4, 0, 0), + Type = "project", + MSBuildProject = fullPath + }]).ToList(); + + referenceProjectInfos.Add(fullPath, SingleProjectInfo.Create(kvp.Key, kvp.Key, ".dll", "4.0.0", + [new MockTaskItem($"{kvp.Key}.resource", new Dictionary() { + { "Culture", "en-us" }, + { "TargetPath", $"{kvp.Key}.resource" } + })])); + } + } + + CompilationOptions compilationOptions = CreateCompilationOptions(); + + return new DependencyContextBuilder(mainProject, includeRuntimeFileVersions: false, runtimeGraph: null, projectContext: projectContext, libraryLookup: new LockFileLookup(lockFile)) + .WithReferenceAssemblies(ReferenceInfo.CreateReferenceInfos(referencePaths)) + .WithCompilationOptions(compilationOptions) + .WithReferenceProjectInfos(referenceProjectInfos) + .Build(); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DirectReferenceToPackageWithNoAssets(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources([], [], ["System.A"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(1); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void IndirectReferenceToPackageWithNoAssets(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources(new Dictionary>() { + { "System.A", ["System.B"] } + }, ["System.A"], ["System.A"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(2); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.A")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void PackageWithNoAssetsReferencesPackageWithNoAssets(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources(new Dictionary>() { + { "System.A", ["System.B"] }, + { "System.B", [] } + }, [], ["System.A"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(1); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void PackageWithNoAssetsReferencesPackageWithAssets(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources(new Dictionary>() { + { "System.A", ["System.B"] }, + { "System.B", [] } + }, ["System.B"], ["System.A"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(3); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.A")); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.B")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void PackageWithNoAssetsReferencesPackageReferencesByOtherPackage(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources(new Dictionary>() + { + { "System.A", ["System.B"] }, + { "System.B", [] }, + }, ["System.B"], ["System.A", "System.B"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(2); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.B")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void PackageWithNoAssetsReferencesPackageWithAssetsWithOtherReferencer(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources(new Dictionary>() + { + { "System.A", ["System.B"] }, + { "System.B", [] }, + { "System.C", ["System.B"] } + }, ["System.B", "System.C"], ["System.A", "System.C"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(3); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.C")); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.B")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void TwoPackagesWithNoAssetsReferencePackageWithAssets(bool dllReference) + { + DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources(new Dictionary>() + { + { "System.A", ["System.B"] }, + { "System.C", ["System.B"] }, + { "System.B", [] } + }, ["System.B"], ["System.A", "System.C"], dllReference); + Save(dependencyContext); + dependencyContext.RuntimeLibraries.Count.Should().Be(3); + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.B")); + if (dependencyContext.RuntimeLibraries.Any(x => x.Name.Equals("System.A"))) + { + dependencyContext.RuntimeLibraries.Should().NotContain(x => x.Name.Equals("System.C")); + } + else + { + dependencyContext.RuntimeLibraries.Should().Contain(x => x.Name.Equals("System.C")); + } + } + private DependencyContext BuildDependencyContextWithReferenceAssemblies(bool useCompilationOptions) { string mainProjectName = "simple.dependencies"; diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/LockFiles/simpleApp.project.lock.json b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/LockFiles/simpleApp.project.lock.json new file mode 100644 index 000000000000..d4da29f8956d --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/LockFiles/simpleApp.project.lock.json @@ -0,0 +1,67 @@ +{ + "version": 3, + "targets": { + "net10.0": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + "net10.0": [] + }, + "packageFolders": { + "C:\\Users\\nmytelka\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\git\\repro\\consoletest\\consoletest.csproj", + "projectName": "consoletest", + "projectPath": "C:\\git\\repro\\consoletest\\consoletest.csproj", + "packagesPath": "C:\\Users\\username\\.nuget\\packages\\", + "outputPath": "C:\\git\\repro\\consoletest\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [], + "configFilePaths": [ + "C:\\Users\\username\\AppData\\Roaming\\NuGet\\NuGet.Config" + ], + "originalTargetFrameworks": [ + "net10.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net10.0": { + "targetAlias": "net10.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "10.0.100" + }, + "frameworks": { + "net10.0": { + "targetAlias": "net10.0", + "imports": [ + "net472", + "net481" + ], + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\git\\sdk\\artifacts\\bin\\redist\\Debug\\dotnet\\sdk\\10.0.100-dev\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs b/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs index afe5c207085e..0bf96474fc13 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs @@ -260,7 +260,7 @@ public DependencyContext Build(string[] userRuntimeAssemblies = null) { CalculateExcludedLibraries(); - List runtimeLibraries = new(); + List runtimeLibraries = new(); if (_includeMainProjectInDepsFile) { @@ -287,23 +287,106 @@ public DependencyContext Build(string[] userRuntimeAssemblies = null) foreach (var directReference in directAndDependencyReferences) { - var runtimeLibrary = new RuntimeLibrary( + var runtimeLibrary = new ModifiableRuntimeLibrary(new RuntimeLibrary( type: "reference", name: GetReferenceLibraryName(directReference), version: directReference.Version, hash: string.Empty, - runtimeAssemblyGroups: new[] { new RuntimeAssetGroup(string.Empty, new[] { CreateRuntimeFile(directReference.FileName, directReference.FullPath) }) }, - nativeLibraryGroups: new RuntimeAssetGroup[] { }, + runtimeAssemblyGroups: [new RuntimeAssetGroup(string.Empty, [CreateRuntimeFile(directReference.FileName, directReference.FullPath)])], + nativeLibraryGroups: [], resourceAssemblies: CreateResourceAssemblies(directReference.ResourceAssemblies), - dependencies: Enumerable.Empty(), + dependencies: [], path: null, hashPath: null, runtimeStoreManifestName: null, - serviceable: false); + serviceable: false)); runtimeLibraries.Add(runtimeLibrary); } + /* + * We now need to modify runtimeLibraries to eliminate those that don't have any runtime assets. We follow the following steps: + * 0. Construct a reverse dependencies list: all runtimeLibraries that depend on this one + * 1. If runtimeAssemblyGroups, nativeLibraryGroups, dependencies, and resourceAssemblies are all empty, remove this runtimeLibrary as well as any dependencies on it. + * 2. Add all runtimeLibraries to a list of to-be-processed libraries called libraryCandidatesForRemoval + * 3. libraryCandidatesForRemoval.Pop() --> if there are no runtimeAssemblyGroups, nativeLibraryGroups, or resourceAssemblies, and either dependencies is empty or all + * dependencies have something else that depends on them, remove it (and from libraryCandidatesForRemoval), adding everything that depends on this to + * libraryCandidatesForRemoval if it isn't already there + * Repeat 3 until libraryCandidatesForRemoval is empty + */ + + // Rather than adding the main project's dependencies, we added references to them, i.e., Foo.Reference.dll + // instead of Foo.dll. This adds Foo.dll as a reference directly so another reference can be removed if it + // isn't necessary because of a direct reference from the main project. + var referenceNameToRealName = new Dictionary(); + if (_includeMainProjectInDepsFile) + { + var mainProjectReferences = _directReferences; + if (IncludeCompilationLibraries && _referenceAssemblies != null) + { + if (mainProjectReferences == null) + { + mainProjectReferences = _referenceAssemblies; + } + else + { + mainProjectReferences = mainProjectReferences.Concat(_referenceAssemblies); + } + } + + if (mainProjectReferences != null) + { + foreach (var directReference in mainProjectReferences) + { + referenceNameToRealName[GetReferenceLibraryName(directReference)] = directReference.Name; + } + } + } + + var libraries = runtimeLibraries.ToDictionary(lib => lib.Library.Name, lib => lib); + foreach (var reference in runtimeLibraries) + { + foreach (var dependency in reference.Library.Dependencies) + { + var name = referenceNameToRealName.TryGetValue(dependency.Name, out var realName) ? realName : dependency.Name; + if (libraries.TryGetValue(name, out var dep)) + { + dep.Dependents.Add(reference.Library.Name); + } + } + } + + var unprocessedLibraries = runtimeLibraries.ToHashSet(); + while (unprocessedLibraries.Any()) + { + var lib = unprocessedLibraries.First(); + unprocessedLibraries.Remove(lib); + + if (lib.Library.RuntimeAssemblyGroups.Count == 0 && lib.Library.NativeLibraryGroups.Count == 0 && lib.Library.ResourceAssemblies.Count == 0) + { + if (lib.Library.Dependencies.All(d => !libraries.TryGetValue(d.Name, out var dependency) || dependency.Dependents.Count > 1)) + { + runtimeLibraries.Remove(lib); + libraries.Remove(lib.Library.Name); + foreach (var dependency in lib.Library.Dependencies) + { + if (libraries.TryGetValue(dependency.Name, out ModifiableRuntimeLibrary value)) + { + value.Dependents.Remove(lib.Library.Name); + } + } + + foreach (var dependent in lib.Dependents) + { + if (libraries.TryGetValue(dependent, out var dep)) + { + unprocessedLibraries.Add(dep); + } + } + } + } + } + List compilationLibraries = new(); if (IncludeCompilationLibraries) { @@ -388,7 +471,6 @@ public DependencyContext Build(string[] userRuntimeAssemblies = null) // // Otherwise, it is the set of all runtimes compatible with (inheriting) // the target runtime-identifier. - var runtimeFallbackGraph = (_runtimeGraph == null || _runtimeIdentifier == null) ? new RuntimeFallbacks[] { } : @@ -397,15 +479,29 @@ public DependencyContext Build(string[] userRuntimeAssemblies = null) .Where(expansion => expansion.Contains(_runtimeIdentifier)) .Select(expansion => new RuntimeFallbacks(expansion.First(), expansion.Skip(1))); // ExpandRuntime return runtime itself as first item. + var libraryNames = runtimeLibraries.Select(lib => lib.Library.Name).Concat(compilationLibraries.Select(lib => lib.Name)).ToHashSet(); + return new DependencyContext( targetInfo, _compilationOptions ?? CompilationOptions.Default, compilationLibraries, - runtimeLibraries, + runtimeLibraries.Select(library => new RuntimeLibrary( + library.Library.Type, + library.Library.Name, + library.Library.Version, + library.Library.Hash, + library.Library.RuntimeAssemblyGroups, + library.Library.NativeLibraryGroups, + library.Library.ResourceAssemblies, + library.Library.Dependencies.Where(dependency => libraryNames.Contains(dependency.Name)).ToList(), + library.Library.Serviceable, + library.Library.Path, + library.Library.HashPath, + library.Library.RuntimeStoreManifestName)), runtimeFallbackGraph); } - private RuntimeLibrary GetProjectRuntimeLibrary() + private ModifiableRuntimeLibrary GetProjectRuntimeLibrary() { RuntimeAssetGroup[] runtimeAssemblyGroups = new[] { new RuntimeAssetGroup(string.Empty, _mainProjectInfo.OutputName) }; @@ -420,7 +516,7 @@ private RuntimeLibrary GetProjectRuntimeLibrary() } } - return new RuntimeLibrary( + return new ModifiableRuntimeLibrary(new RuntimeLibrary( type: "project", name: _mainProjectInfo.Name, version: _mainProjectInfo.Version, @@ -432,7 +528,7 @@ private RuntimeLibrary GetProjectRuntimeLibrary() path: null, hashPath: null, runtimeStoreManifestName: GetRuntimeStoreManifestName(_mainProjectInfo.Name, _mainProjectInfo.Version), - serviceable: false); + serviceable: false)); } private List GetProjectDependencies() @@ -479,11 +575,11 @@ private List GetProjectDependencies() return dependencies; } - private IEnumerable GetRuntimePackLibraries() + private IEnumerable GetRuntimePackLibraries() { if (_runtimePackAssets == null) { - return Enumerable.Empty(); + return []; } return _runtimePackAssets.Select(runtimePack => { @@ -495,20 +591,20 @@ private IEnumerable GetRuntimePackLibraries() runtimePack.Value.Where(asset => asset.AssetType == AssetType.Native) .Select(asset => CreateRuntimeFile(asset.DestinationSubPath, asset.SourcePath))); - return new RuntimeLibrary( + return new ModifiableRuntimeLibrary(new RuntimeLibrary( type: "runtimepack", name: runtimePack.Key, version: runtimePack.Value.First().PackageVersion, hash: string.Empty, - runtimeAssemblyGroups: new[] { runtimeAssemblyGroup }, - nativeLibraryGroups: new[] { nativeLibraryGroup }, - resourceAssemblies: Enumerable.Empty(), - dependencies: Enumerable.Empty(), - serviceable: false); + runtimeAssemblyGroups: [runtimeAssemblyGroup], + nativeLibraryGroups: [nativeLibraryGroup], + resourceAssemblies: [], + dependencies: [], + serviceable: false)); }); } - private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, string[] userRuntimeAssemblies) + private ModifiableRuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, string[] userRuntimeAssemblies) { GetCommonLibraryProperties(library, out string hash, @@ -584,7 +680,7 @@ private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, string[] use } - var runtimeLibrary = new RuntimeLibrary( + var runtimeLibrary = new ModifiableRuntimeLibrary(new RuntimeLibrary( type: library.Type, name: library.Name, version: library.Version.ToString(), @@ -596,7 +692,7 @@ private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, string[] use path: path, hashPath: hashPath, runtimeStoreManifestName: GetRuntimeStoreManifestName(library.Name, library.Version.ToString()), - serviceable: serviceable); + serviceable: serviceable)); return runtimeLibrary; } @@ -887,5 +983,18 @@ private struct LibraryDependency public string Name { get; set; } public NuGetVersion MinVersion { get; set; } } + + private class ModifiableRuntimeLibrary + { + // Dependents are assemblies that depend on this library, as opposed to dependencies which are libraries that this one depends on + public HashSet Dependents { get; set; } + public RuntimeLibrary Library { get; set; } + + public ModifiableRuntimeLibrary(RuntimeLibrary library) + { + this.Dependents = new(); + this.Library = library; + } + } } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PackageReferenceConverter.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PackageReferenceConverter.cs index d9771b8e1a8e..cf7a45d5c81d 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PackageReferenceConverter.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PackageReferenceConverter.cs @@ -9,7 +9,7 @@ namespace Microsoft.NET.Build.Tasks { internal static class PackageReferenceConverter { - public static IEnumerable GetPackageIds(ITaskItem[] packageReferences) + public static IEnumerable GetPackageIds(IEnumerable packageReferences) { if (packageReferences == null) { diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs index 7b47bc1b87d4..89019d37050d 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs @@ -107,10 +107,58 @@ public void Method1() } + [Theory] + [InlineData("RazorSimpleMvc22", "netcoreapp2.2", "SimpleMvc22")] + [InlineData("DesktopReferencingNetStandardLibrary", "net46", "Library")] + public void PackageReferences_with_private_assets_do_not_appear_in_deps_file(string asset, string targetFramework, string exeName) + { + var testAsset = _testAssetsManager + .CopyTestAsset(asset) + .WithSource(); + + var buildCommand = new BuildCommand(testAsset); + buildCommand.Execute().Should().Pass(); + + using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(targetFramework).FullName, exeName + ".deps.json"))) + { + var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream); + if (asset.Equals("DesktopReferencingNetStandardLibrary")) + { + dependencyContext.CompileLibraries.Any(l => l.Name.Equals("Library")).Should().BeTrue(); + dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("Library")).Should().BeTrue(); + } + else + { + dependencyContext.CompileLibraries.Any(l => l.Name.Equals("Nerdbank.GitVersioning")).Should().BeTrue(); + dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("Nerdbank.GitVersioning")).Should().BeFalse(); + } + } + } + + [Fact] + public void PackageWithoutAssets_ShouldNotShowUpInDepsJson() + { + var testProject = new TestProject() + { + TargetFrameworks = ToolsetInfo.CurrentTargetFramework + }; + testProject.PackageReferences.Add(new TestPackageReference("Nerdbank.GitVersioning", "3.6.146")); + + var testAsset = _testAssetsManager.CreateTestProject(testProject); + + var buildCommand = new BuildCommand(testAsset); + buildCommand.Execute().Should().Pass(); + + using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(ToolsetInfo.CurrentTargetFramework).FullName, "PackageWithoutAssets_ShouldNotShowUpInDepsJson.deps.json"))) + { + var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream); + dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("Nerdbank.GitVersioning")).Should().BeFalse(); + } + } + [WindowsOnlyFact] public void It_can_reference_a_netstandard2_library_and_exchange_types() { - var netStandardLibrary = new TestProject() { Name = "NETStandardLibrary", diff --git a/test/TestAssets/TestProjects/RazorSimpleMvc22/SimpleMvc22.csproj b/test/TestAssets/TestProjects/RazorSimpleMvc22/SimpleMvc22.csproj index 9d0b31e16588..f231a0c16c81 100644 --- a/test/TestAssets/TestProjects/RazorSimpleMvc22/SimpleMvc22.csproj +++ b/test/TestAssets/TestProjects/RazorSimpleMvc22/SimpleMvc22.csproj @@ -18,6 +18,7 @@ +