Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Add private assets from package reference
Browse files Browse the repository at this point in the history
Fixes NuGet/Home#5103

This is only performed for resolved NuGet artifacts that have
one of the specified values in the referenced NuGet specification at
https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-assets.

This minimizes the impact of the new inference and preserves existing behavior.
  • Loading branch information
kzu committed Jun 9, 2017
1 parent 0f8fa8f commit 5141dcb
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 40 deletions.
5 changes: 3 additions & 2 deletions build.proj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<RunCodeAnalysis Condition=" '$(RunCodeAnalysis)' == ''">false</RunCodeAnalysis>
<IntermediateOutputPath>.nuget\</IntermediateOutputPath>
<PackagesPath>$(IntermediateOutputPath)packages</PackagesPath>
<CommonBuildProperties>WarningLevel=0;NoWarn=1591;Out=$(Out);Configuration=$(Configuration);RunCodeAnalysis=$(RunCodeAnalysis);PackageOutputPath=$(Out);NuGetBuildTasksPackTargets=NO-SDK-PACK</CommonBuildProperties>
<CommonBuildProperties>WarningLevel=0;NoWarn=1591;Out=$(Out);Configuration=$(Configuration);RunCodeAnalysis=$(RunCodeAnalysis);PackageOutputPath=$(Out)</CommonBuildProperties>
<DefaultImportance Condition=" '$(DefaultImportance)' == '' ">high</DefaultImportance>
<PS>%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe</PS>
</PropertyGroup>
Expand Down Expand Up @@ -47,7 +47,7 @@

<Target Name="Package">
<MakeDir Directories="$(Out)" Condition="!Exists('$(Out)')" />
<MSBuild Projects="src\Build\NuGet.Build.Packaging.Tasks\NuGet.Build.Packaging.Tasks.csproj" Targets="Pack" Properties="$(CommonBuildProperties);PackOnBuild=true" />
<MSBuild Projects="src\Build\NuGet.Build.Packaging.Tasks\NuGet.Build.Packaging.Tasks.csproj" Targets="Pack" Properties="$(CommonBuildProperties);PackOnBuild=true;NuGetBuildTasksPackTargets=NO-SDK-PACK" />
<MSBuild Projects="src\VisualStudio\NuGet.Packaging.VisualStudio.15\NuGet.Packaging.VisualStudio.15.csproj" Properties="$(CommonBuildProperties);PackOnBuild=true" />
<ItemGroup>
<OutputFile Include="$(Out)\*.nupkg" />
Expand Down Expand Up @@ -79,6 +79,7 @@
<NuGetRestore Include="src\Build\NuGet.Build.Packaging.Tests\Scenarios\given_a_multi_platform_solution\forms.sln" />
<NuGetRestore Include="src\Build\NuGet.Build.Packaging.Tests\Scenarios\given_a_library_with_json_dependencies\project.json" />
<MSBuildRestore Include="src\Build\NuGet.Build.Packaging.Tests\Scenarios\given_a_packaging_project_with_netstandard\a.nuproj" />
<MSBuildRestore Include="src\Build\NuGet.Build.Packaging.Tests\Scenarios\given_a_library_with_private_assets_reference\a.csproj" />

<MSBuildRestore Include="external\ApiIntersect\ApiIntersect.sln" />
<MSBuildRestore Include="src\Build\NuGet.Build.Packaging.sln" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,22 @@ Copyright (c) .NET Foundation. All rights reserved.
<PropertyGroup>
<GetPackageContentsDependsOn>
$(GetPackageContentsDependsOn);
_PrimaryOutputFrameworkSpecific;
InferPackageContents
</GetPackageContentsDependsOn>
</PropertyGroup>

<Target Name="InferPackageContents" DependsOnTargets="$(InferPackageContentsDependsOn)" Returns="@(PackageFile)">
<Target Name="_PrimaryOutputFrameworkSpecific" Returns="$(PrimaryOutputFrameworkSpecific)">
<!-- Determine whether primary output is framework specific -->
<ItemGroup Condition="'$(PrimaryOutputFrameworkSpecific)' == ''">
<_PrimaryOutputKind Include="@(PackageItemKind->'%(FrameworkSpecific)')" Condition="'%(Identity)' == '$(PrimaryOutputKind)'" />
</ItemGroup>
<PropertyGroup Condition="'$(PrimaryOutputFrameworkSpecific)' == ''">
<PrimaryOutputFrameworkSpecific>@(_PrimaryOutputKind)</PrimaryOutputFrameworkSpecific>
</PropertyGroup>
</Target>

<Target Name="InferPackageContents" DependsOnTargets="$(InferPackageContentsDependsOn)" Returns="@(PackageFile)">
<!-- Ensure TargetPath -->
<AssignTargetPath Files="@(Content)" RootFolder="$(MSBuildProjectDirectory)"
Condition="'%(Content.Pack)' == 'true' or
Expand Down Expand Up @@ -125,7 +128,7 @@ Copyright (c) .NET Foundation. All rights reserved.
</_InferredPackageFile>


<_InferredPackageFile Include="@(PackageReference)" Condition="'%(Identity)' != 'NuGet.Build.Packaging'">
<_InferredPackageFile Include="@(PackageReference)" Condition="'%(PackageReference.Identity)' != 'NuGet.Build.Packaging' and '%(PackageReference.PrivateAssets)' != 'all'">
<Kind>Dependency</Kind>
</_InferredPackageFile>

Expand Down Expand Up @@ -153,19 +156,62 @@ Copyright (c) .NET Foundation. All rights reserved.
</ItemGroup>
</Target>

<Target Name="_CollectPrimaryOutputRelatedFiles" DependsOnTargets="BuildOnlySettings;ResolveReferences" Returns="@(_PrimaryOutputRelatedFile)">
<ItemGroup>
<_PrimaryOutputRelatedFile Include="@(ReferencePath);@(_ReferenceRelatedPaths)" />
</ItemGroup>
</Target>

<Target Name="InferPrimaryOutputDependencies"
Inputs="@(_PrimaryOutputRelatedFile)"
Outputs="%(_PrimaryOutputRelatedFile.NuGetPackageId)"
Returns="@(_InferredPackageFile)"
DependsOnTargets="_CollectPrimaryOutputRelatedFiles">
<ItemGroup>
<_NuGetPackageId Include="@(_PrimaryOutputRelatedFile -> '%(NuGetPackageId)')" />
</ItemGroup>
<PropertyGroup>
<_NuGetPackageId>@(_NuGetPackageId -> Distinct())</_NuGetPackageId>
</PropertyGroup>
<ItemGroup>
<_PrimaryPackageReference Include="@(PackageReference)" Condition="'$(_NuGetPackageId)' != '' and '%(Identity)' == '$(_NuGetPackageId)'" />
</ItemGroup>
<PropertyGroup>
<_PrivateAssets>@(_PrimaryPackageReference -> '%(PrivateAssets)')</_PrivateAssets>
</PropertyGroup>

<ItemGroup Condition="'$(_PrivateAssets)' == 'all'">
<_InferredPackageFile Include="@(_PrimaryOutputRelatedFile)" Condition="'%(_PrimaryOutputRelatedFile.FrameworkFile)' != 'true'">
<Kind>$(PrimaryOutputKind)</Kind>
<FrameworkSpecific>$(PrimaryOutputFrameworkSpecific)</FrameworkSpecific>
</_InferredPackageFile>
</ItemGroup>

<ItemGroup Condition="'$(_PrivateAssets)' != 'all' and '$(_PrivateAssets)' != 'none' and '$(_PrivateAssets)' != ''">
<!-- In this case, we only add files that have a matching path to the private assets value.
i.e. for Mono.Options, PrivateAssets=lib, we'll include the file if its full path contains
'Mono.Options\*\lib\*', meaning the file is a lib. -->
<_InferredPackageFile Include="@(_PrimaryOutputRelatedFile)" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(_PrimaryOutputRelatedFile.FullPath)', '$(_NuGetPackageId)\\.+\\$(_PrivateAssets)\\.*')) == 'true'">
<Kind>$(PrimaryOutputKind)</Kind>
<FrameworkSpecific>$(PrimaryOutputFrameworkSpecific)</FrameworkSpecific>
</_InferredPackageFile>
</ItemGroup>
</Target>

<Target Name="_SetInferPackageContentsDependsOn" AfterTargets="_SetPropertiesFromCapabilities">
<PropertyGroup>
<!-- NOTE: this avoids taking dependencies on targets that are only available when the project supports the concept of references -->
<_SupportsReferences Condition="
$(_AllProjectCapabilities.Contains('AssemblyReferences')) or
$(_AllProjectCapabilities.Contains('COMReferences')) or
$(_AllProjectCapabilities.Contains('ProjectReferences')) or
$(_AllProjectCapabilities.Contains('PackageReferences')) or
$(_AllProjectCapabilities.Contains('WinRTReferences')) or
$(_AllProjectCapabilities.Contains('SDKReferences'))">true</_SupportsReferences>

<!-- Only depend on ResolveReferences if we need to include framework references -->
<InferPackageContentsDependsOn Condition="'$(IncludeFrameworkReferencesInPackage)' == 'true' and '$(_SupportsReferences)' == 'true'">
ResolveReferences
<InferPackageContentsDependsOn Condition="'$(_SupportsReferences)' == 'true'">
ResolveReferences;
InferPrimaryOutputDependencies
</InferPackageContentsDependsOn>
<InferPackageContentsDependsOn>
$(InferPackageContentsDependsOn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,12 @@
<Import Project="$(OutputPath)NuGet.Build.Packaging.targets"
Condition="'$(PackOnBuild)' == 'true' and Exists('$(OutputPath)NuGet.Build.Packaging.targets')" />

<Target Name="AddBuiltOutput" BeforeTargets="GetPackageContents" DependsOnTargets="AllProjectOutputGroups" Returns="@(PackageFile)">
<Target Name="CleanContents" BeforeTargets="GetPackageContents" DependsOnTargets="InferPackageContents" Returns="@(PackageFile)">
<ItemGroup>
<PackageFile Include="$(OutputPath)ICSharpCode.Decompiler.dll">
<PackagePath>build\ICSharpCode.Decompiler.dll</PackagePath>
</PackageFile>
<PackageFile Include="$(OutputPath)ICSharpCode.NRefactory.CSharp.dll">
<PackagePath>build\ICSharpCode.NRefactory.CSharp.dll</PackagePath>
</PackageFile>
<PackageFile Include="$(OutputPath)ICSharpCode.NRefactory.dll">
<PackagePath>build\ICSharpCode.NRefactory.dll</PackagePath>
</PackageFile>
<PackageFile Include="$(OutputPath)Mono.Cecil.dll">
<PackagePath>build\Mono.Cecil.dll</PackagePath>
</PackageFile>
<PackageFile Include="$(OutputPath)Mono.Options.dll">
<PackagePath>build\Mono.Options.dll</PackagePath>
</PackageFile>
<PackageFile Remove="@(PackageFile)" Condition="
$([System.String]::new('%(PackageFile.NuGetPackageId)').StartsWith('Microsoft')) or
$([System.String]::new('%(PackageFile.NuGetPackageId)').StartsWith('Newtonsoft')) or
$([System.String]::new('%(PackageFile.NuGetPackageId)').StartsWith('NuGet'))" />
</ItemGroup>
</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<Target Name="Pack" DependsOnTargets="$(PackDependsOn)" Returns="@(PackageTargetPath)" Condition="'$(IsPackable)' == 'true'">
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists('$(PackageOutputPath)')" />
<PropertyGroup>
<NuspecFile Condition="'$(EmitNuspec)' == 'true' And '$(NuspecFile)' ==''">$(OutputPath)\$(PackageId).nuspec</NuspecFile>
<NuspecFile Condition="'$(EmitNuspec)' == 'true' And '$(NuspecFile)' == ''">$(OutputPath)\$(PackageId).nuspec</NuspecFile>
</PropertyGroup>
<CreatePackage Manifest="@(PackageTargetPath)" NuspecFile="$(NuspecFile)" Contents="@(_PackageContent)" TargetPath="@(PackageTargetPath->'%(FullPath)')">
<Output TaskParameter="OutputPackage" ItemName="_PackageTargetPath" />
Expand Down
18 changes: 12 additions & 6 deletions src/Build/NuGet.Build.Packaging.Tests/Builder.NuGetizer.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using NuGet.Build.Packaging;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
Expand Down Expand Up @@ -53,12 +55,16 @@ public static TargetResult BuildScenario(string scenarioName, object properties
logger = new TestOutputLogger(null);
}

if (properties != null)
return new TargetResult(Build(projectOrSolution, target,
properties: properties.GetType().GetProperties().ToDictionary(prop => prop.Name, prop => prop.GetValue(properties).ToString()),
logger: logger), target, logger);
else
return new TargetResult(Build(projectOrSolution, target, logger: logger), target, logger);
var buildProps = properties?.GetType().GetProperties()
.ToDictionary(prop => prop.Name, prop => prop.GetValue(properties).ToString())
?? new Dictionary<string, string>();

buildProps[nameof(ThisAssembly.Project.Properties.NuGetRestoreTargets)] = ThisAssembly.Project.Properties.NuGetRestoreTargets;
buildProps[nameof(ThisAssembly.Project.Properties.NuGetTargets)] = ThisAssembly.Project.Properties.NuGetTargets;

return new TargetResult(Build(projectOrSolution, target,
properties: buildProps,
logger: logger), target, logger);
}

public class TargetResult : ITargetResult
Expand Down
15 changes: 8 additions & 7 deletions src/Build/NuGet.Build.Packaging.Tests/CreatePackageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ public void when_creating_package_with_non_framework_secific_dependency_then_con

Assert.NotNull(manifest);
Assert.Equal(2, manifest.Metadata.DependencyGroups.Count());
Assert.Equal(NuGetFramework.UnsupportedFramework, manifest.Metadata.DependencyGroups.First().TargetFramework);
Assert.True(
manifest.Metadata.DependencyGroups.First().TargetFramework == NuGetFramework.AnyFramework ||
manifest.Metadata.DependencyGroups.First().TargetFramework == NuGetFramework.UnsupportedFramework);

Assert.Equal(NuGetFramework.Parse(".NETFramework,Version=v4.5"), manifest.Metadata.DependencyGroups.Last().TargetFramework);

Assert.Equal(1, manifest.Metadata.DependencyGroups.First().Packages.Count());
Expand Down Expand Up @@ -212,11 +215,12 @@ public void when_creating_package_with_any_framework_secific_dependency_then_con

var manifest = ExecuteTask();

//Process.Start("notepad.exe", task.NuspecFile);

Assert.NotNull(manifest);
Assert.Equal(2, manifest.Metadata.DependencyGroups.Count());
Assert.Equal(NuGetFramework.UnsupportedFramework, manifest.Metadata.DependencyGroups.First().TargetFramework);
Assert.True(
manifest.Metadata.DependencyGroups.First().TargetFramework == NuGetFramework.AnyFramework ||
manifest.Metadata.DependencyGroups.First().TargetFramework == NuGetFramework.UnsupportedFramework);

Assert.Equal(NuGetFramework.Parse(".NETFramework,Version=v4.5"), manifest.Metadata.DependencyGroups.Last().TargetFramework);

Assert.Equal(1, manifest.Metadata.DependencyGroups.First().Packages.Count());
Expand Down Expand Up @@ -274,9 +278,6 @@ public void when_creating_package_with_empty_dependency_groups_then_succeeds()

var manifest = ExecuteTask();

//if (Debugger.IsAttached)
// Process.Start("notepad.exe", task.NuspecFile);

Assert.NotNull(manifest);
Assert.Equal(4, manifest.Metadata.DependencyGroups.Count());
Assert.All(manifest.Metadata.DependencyGroups, d => Assert.Empty(d.Packages));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<TargetFramework>net46</TargetFramework>
<SignAssembly>false</SignAssembly>
<PublicSign>false</PublicSign>
<NuGetBuildTasksPackTargets>NO-SDK-PACK</NuGetBuildTasksPackTargets>
</PropertyGroup>
<ItemGroup>
<Reference Include="NuGet.Build.Packaging.Tasks">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
</PropertyGroup>

<ItemGroup>
<ThisAssemblyProjectProperty Include="NuGetRestoreTargets" />
<ThisAssemblyProjectProperty Include="NuGetTargets" />
</ItemGroup>

<Target Name="CopyScenarioFiles" AfterTargets="Build">
<ItemGroup>
<ScenarioFile Include="Scenarios\**\*.*" Exclude="Scenarios\**\bin\**\*.*;Scenarios\**\obj\**\*.*" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" Condition="'$(IsPortable)' != 'true'" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets"
Condition="'$(IsPortable)' == 'true'" />
<!-- Ensure we get proper NuGet behavior always -->
<Import Project="$(NuGetRestoreTargets)" Condition="'$(IsRestoreTargetsFileLoaded)' != 'true' and '$(NuGetRestoreTargets)' != ''" />
<Import Project="$(NuGetTargets)" Condition="'$(ResolveNuGetPackageAssetsDependsOn)' == '' and '$(NuGetTargets)' != ''" />

<Import Project="$(NuGetTargetsPath)\NuGet.Build.Packaging.targets" Condition="'$(NuGetBuildPackagingTargetsImported)' != 'true' and Exists('$(NuGetTargetsPath)\NuGet.Build.Packaging.targets')" />

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Scenario.props))\Scenario.props" />
<PropertyGroup>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Options">
<Version>*</Version>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>*</Version>
<PrivateAssets>lib</PrivateAssets>
</PackageReference>
<PackageReference Include="xunit">
<Version>*</Version>
</PackageReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Scenario.targets))\Scenario.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Linq;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Xunit;
using Xunit.Abstractions;

namespace NuGet.Build.Packaging
{
public class given_a_library_with_private_assets_reference
{
ITestOutputHelper output;

public given_a_library_with_private_assets_reference(ITestOutputHelper output)
{
this.output = output;
}

[Fact]
public void when_getting_package_contents_then_contains_private_assets_as_primary_output()
{
Builder.BuildScenario(nameof(given_a_library_with_private_assets_reference), target: "Restore", output: output);
var result = Builder.BuildScenario(nameof(given_a_library_with_private_assets_reference), output: output);

result.AssertSuccess(output);

Assert.DoesNotContain(result.Items, item => item.Matches(new
{
Kind = PackageItemKind.Dependency,
Identity = "Mono.Options",
}));
Assert.Contains(result.Items, item => item.Matches(new
{
Kind = PackageItemKind.Lib,
Filename = "Mono.Options",
NuGetSourceType = "Package",
NuGetPackageId = "Mono.Options",
}));
}

[Fact]
public void when_getting_package_contents_then_contains_private_lib_assets_as_primary_output_and_also_package_reference()
{
Builder.BuildScenario(nameof(given_a_library_with_private_assets_reference), target: "Restore", output: output);
var result = Builder.BuildScenario(nameof(given_a_library_with_private_assets_reference), output: output);

result.AssertSuccess(output);

Assert.Contains(result.Items, item => item.Matches(new
{
Kind = PackageItemKind.Dependency,
Identity = "Newtonsoft.Json",
}));
Assert.Contains(result.Items, item => item.Matches(new
{
Kind = PackageItemKind.Lib,
Filename = "Newtonsoft.Json",
NuGetSourceType = "Package",
NuGetPackageId = "Newtonsoft.Json",
}));
}

[Fact]
public void when_getting_package_contents_then_contains_dependency_for_non_private_assets_reference()
{
Builder.BuildScenario(nameof(given_a_library_with_private_assets_reference), target: "Restore", output: output);
var result = Builder.BuildScenario(nameof(given_a_library_with_private_assets_reference), output: output);

result.AssertSuccess(output);

Assert.Contains(result.Items, item => item.Matches(new
{
Kind = PackageItemKind.Dependency,
Identity = "xunit",
}));
Assert.DoesNotContain(result.Items, item => item.Matches(new
{
Kind = PackageItemKind.Lib,
Filename = "xunit",
NuGetSourceType = "Package",
NuGetPackageId = "xunit",
}));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,5 @@ public void when_getting_contents_from_packaging_project_then_referenced_outputs
PackagePath = @"lib\net45\c.xml",
}));
}


}
}
2 changes: 1 addition & 1 deletion src/NuGet.Build.Packaging.Shared.targets
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<Import Project="NuGet.Build.Packaging.props" Condition=" '$(NuGetPackagingPropsImported)' != 'true' " />

<ItemGroup>
<PackageReference Include="MSBuilder.ThisAssembly.Project" Version="0.3.3" PrivateAssets="all" />
<PackageReference Include="MSBuilder.ThisAssembly.Project" Version="0.3.4" PrivateAssets="all" />
<ThisAssemblyProjectProperty Include="PackageVersion" />
</ItemGroup>

Expand Down

0 comments on commit 5141dcb

Please sign in to comment.