Skip to content

Commit 15006a6

Browse files
authored
Merge pull request #4 from kzu/dev
Dev > Main
2 parents 5e85677 + 12b3cd7 commit 15006a6

File tree

11 files changed

+629
-197
lines changed

11 files changed

+629
-197
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using Microsoft.Build.Framework;
6+
using Microsoft.Build.Utilities;
7+
8+
namespace NuGetizer.Tasks
9+
{
10+
public class InferImplicitPackageReference : Task
11+
{
12+
[Required]
13+
public ITaskItem[] PackageReferences { get; set; } = Array.Empty<ITaskItem>();
14+
15+
[Required]
16+
public ITaskItem[] PackageDependencies { get; set; } = Array.Empty<ITaskItem>();
17+
18+
[Output]
19+
public ITaskItem[] ImplicitPackageReferences { get; set; } = Array.Empty<ITaskItem>();
20+
21+
public override bool Execute()
22+
{
23+
var packages = new ConcurrentDictionary<PackageIdentity, List<PackageIdentity>>();
24+
Func<string, PackageIdentity> parse = value =>
25+
{
26+
var parts = value.Split('/');
27+
return new PackageIdentity(parts[0], parts[1]);
28+
};
29+
30+
// Build the list of parent>child relationships.
31+
foreach (var dependency in PackageDependencies.Where(x => x.ItemSpec.Contains('/')))
32+
{
33+
var identity = parse(dependency.ItemSpec);
34+
var parent = dependency.GetMetadata("ParentPackage");
35+
if (!string.IsNullOrEmpty(parent))
36+
{
37+
packages.GetOrAdd(parse(parent), _ => new List<PackageIdentity>())
38+
.Add(identity);
39+
}
40+
}
41+
42+
var inferred = new HashSet<PackageIdentity>();
43+
44+
foreach (var reference in PackageReferences.Where(x =>
45+
"all".Equals(x.GetMetadata("PrivateAssets"), StringComparison.OrdinalIgnoreCase) &&
46+
// Unless explicitly set to Pack=false
47+
(!x.TryGetBoolMetadata("Pack", out var pack) || pack != false) &&
48+
// NETCore/NETStandard are implicitly defined, we never need to bring them as deps.
49+
!(bool.TryParse(x.GetMetadata("IsImplicitlyDefined"), out var isImplicit) && isImplicit)))
50+
{
51+
var identity = new PackageIdentity(reference.ItemSpec, reference.GetMetadata("Version"));
52+
foreach (var dependency in FindDependencies(identity, packages))
53+
{
54+
inferred.Add(dependency);
55+
}
56+
}
57+
58+
ImplicitPackageReferences = inferred
59+
.Select(x => new TaskItem(
60+
x.Id,
61+
new Dictionary<string, string>
62+
{
63+
{ "Version", x.Version } ,
64+
{ "PrivateAssets", "all" },
65+
}))
66+
.ToArray();
67+
68+
return true;
69+
}
70+
71+
IEnumerable<PackageIdentity> FindDependencies(PackageIdentity identity, IDictionary<PackageIdentity, List<PackageIdentity>> packages)
72+
{
73+
if (packages.TryGetValue(identity, out var dependencies))
74+
{
75+
foreach (var dependency in dependencies)
76+
{
77+
yield return dependency;
78+
foreach (var child in FindDependencies(dependency, packages))
79+
{
80+
yield return child;
81+
}
82+
}
83+
}
84+
}
85+
86+
class PackageIdentity
87+
{
88+
public PackageIdentity(string id, string version)
89+
=> (Id, Version)
90+
= (id, version);
91+
92+
public string Id { get; }
93+
public string Version { get; }
94+
95+
public override bool Equals(object obj)
96+
=> obj is PackageIdentity dependency &&
97+
dependency.Id == Id &&
98+
dependency.Version == Version;
99+
100+
public override int GetHashCode() => Tuple.Create(Id, Version).GetHashCode();
101+
102+
public override string ToString() => Id + "/" + Version;
103+
}
104+
}
105+
}

src/NuGetizer.Tasks/NuGetizer.Inference.targets

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Copyright (c) .NET Foundation. All rights reserved.
1010
***********************************************************************************************
1111
-->
1212
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
13+
<UsingTask TaskName="NuGetizer.Tasks.InferImplicitPackageReference" AssemblyFile="NuGetizer.Tasks.dll" />
1314

1415
<PropertyGroup>
1516
<!-- The Kind of primary output (build, symbols and doc) set if PackBuildOutput = true -->
@@ -36,6 +37,7 @@ Copyright (c) .NET Foundation. All rights reserved.
3637
<GetPackageContentsDependsOn>
3738
$(GetPackageContentsDependsOn);
3839
_BuildOutputFrameworkSpecific;
40+
_SetDefaultPackageReferencePack;
3941
InferPackageContents
4042
</GetPackageContentsDependsOn>
4143
</PropertyGroup>
@@ -59,15 +61,24 @@ Copyright (c) .NET Foundation. All rights reserved.
5961
</_ReferenceRelatedPaths>
6062
</ItemDefinitionGroup>
6163

62-
<Target Name="_BuildOutputFrameworkSpecific" Returns="$(BuildOutputFrameworkSpecific)">
64+
<Target Name="_BuildOutputFrameworkSpecific" Condition="'$(BuildOutputFrameworkSpecific)' == ''" Returns="$(BuildOutputFrameworkSpecific)">
6365
<!-- Determine whether primary output is framework specific -->
64-
<ItemGroup Condition="'$(BuildOutputFrameworkSpecific)' == ''">
66+
<ItemGroup>
6567
<_BuildOutputKindFrameworkSpecific Include="@(PackageItemKind->'%(FrameworkSpecific)')" Condition="'%(Identity)' == '$(BuildOutputKind)'" />
6668
</ItemGroup>
67-
<PropertyGroup Condition="'$(BuildOutputFrameworkSpecific)' == ''">
69+
<PropertyGroup>
6870
<BuildOutputFrameworkSpecific>@(_BuildOutputKindFrameworkSpecific)</BuildOutputFrameworkSpecific>
6971
</PropertyGroup>
7072
</Target>
73+
74+
<Target Name="_SetDefaultPackageReferencePack" Condition="'$(BuildOutputKind)' == 'build'"
75+
BeforeTargets="InferPrimaryOutputDependencies;InferPackageContents">
76+
<ItemGroup>
77+
<PackageReference Update="@(PackageReference)"
78+
Condition="$([MSBuild]::ValueOrDefault('%(Identity)', '').StartsWith('Microsoft.Build')) and '%(Pack)' != 'true'"
79+
Pack="false" />
80+
</ItemGroup>
81+
</Target>
7182

7283
<Target Name="InferPackageContents" DependsOnTargets="$(InferPackageContentsDependsOn)" Returns="@(PackageFile)">
7384
<!-- Ensure TargetPath -->
@@ -132,7 +143,7 @@ Copyright (c) .NET Foundation. All rights reserved.
132143
Condition="'%(_NoneToInfer.CopyToOutputDirectory)' == '' or '%(_NoneToInfer.CopyToOutputDirectory)' == 'Never'">
133144
<Kind Condition="'%(_NoneToInfer.Kind)' == ''">None</Kind>
134145
</_InferredPackageFile>
135-
146+
136147
<_InferredPackageFile Include="@(PackageReference)"
137148
Condition="'%(PackageReference.Identity)' != 'NuGetizer' and
138149
'%(PackageReference.Identity)' != 'NETStandard.Library' and
@@ -145,7 +156,9 @@ Copyright (c) .NET Foundation. All rights reserved.
145156
it also includes mscorlib which we don't need
146157
TBD: maybe include ResolvedFrom=ImplicitlyExpandDesignTimeFacades too? -->
147158
<_InferredPackageFile Include="@(ReferencePath->'%(OriginalItemSpec)')"
148-
Condition="'$(PackFrameworkReferences)' == 'true' and '%(ReferencePath.ResolvedFrom)' == '{TargetFrameworkDirectory}' and '%(ReferencePath.Pack)' != 'false'">
159+
Condition="'$(PackFrameworkReferences)' == 'true' and
160+
'%(ReferencePath.ResolvedFrom)' == '{TargetFrameworkDirectory}' and
161+
'%(ReferencePath.Pack)' != 'false'">
149162
<Kind>FrameworkReference</Kind>
150163
</_InferredPackageFile>
151164
</ItemGroup>
@@ -165,47 +178,60 @@ Copyright (c) .NET Foundation. All rights reserved.
165178
</ItemGroup>
166179
</Target>
167180

168-
<Target Name="_CollectPrimaryOutputRelatedFiles" DependsOnTargets="BuildOnlySettings;ResolveReferences" Returns="@(_PrimaryOutputRelatedFile)">
181+
<Target Name="_CollectPrimaryOutputDependencies" DependsOnTargets="BuildOnlySettings;ResolveReferences" Returns="@(ImplicitPackageReference)">
169182
<ItemGroup>
170183
<_PrimaryOutputRelatedFile Include="@(ReferencePath);@(_ReferenceRelatedPaths)"
171184
Condition="'%(NuGetPackageId)' != 'NETStandard.Library' and
172185
'%(Facade)' != 'true' and
173186
'%(FrameworkFile)' != 'true' and
174187
'%(Pack)' != 'false'"/>
188+
<_PrivateAssetsPackageReference Include="@(PackageReference -> WithMetadataValue('PrivateAssets', 'all'))"
189+
Condition="'%(PackageReference.IsImplicitlyDefined)' != 'true' and '%(PackageReference.Pack)' != 'false'"/>
175190
</ItemGroup>
191+
<InferImplicitPackageReference Condition="'@(_PrivateAssetsPackageReference)' != '' and '@(PackageDependencies)' != ''"
192+
PackageReferences="@(_PrivateAssetsPackageReference)"
193+
PackageDependencies="@(PackageDependencies)">
194+
<Output TaskParameter="ImplicitPackageReferences" ItemName="ImplicitPackageReference" />
195+
</InferImplicitPackageReference>
176196
</Target>
197+
198+
<Target Name="_ResolvePackageDependencies" Condition="'$(UsingMicrosoftNETSdk)' == 'true'" DependsOnTargets="RunResolvePackageDependencies" />
177199

178200
<Target Name="InferPrimaryOutputDependencies"
179201
Inputs="@(_PrimaryOutputRelatedFile)"
180202
Outputs="%(_PrimaryOutputRelatedFile.NuGetPackageId)"
181203
Returns="@(_InferredPackageFile)"
182-
DependsOnTargets="_CollectPrimaryOutputRelatedFiles">
204+
DependsOnTargets="_ResolvePackageDependencies;_CollectPrimaryOutputDependencies">
205+
183206
<ItemGroup>
184207
<_NuGetPackageId Include="@(_PrimaryOutputRelatedFile -> '%(NuGetPackageId)')" Condition="'%(NuGetPackageId)' != 'NETStandard.Library'" />
185208
</ItemGroup>
186209
<PropertyGroup>
187210
<_NuGetPackageId>@(_NuGetPackageId -> Distinct())</_NuGetPackageId>
188211
</PropertyGroup>
189212
<ItemGroup>
190-
<_PrimaryPackageReference Include="@(PackageReference)" Condition="'$(_NuGetPackageId)' != '' and '%(Identity)' == '$(_NuGetPackageId)'" />
213+
<_PrimaryPackageReference Include="@(PackageReference);@(ImplicitPackageReference)" Condition="'$(_NuGetPackageId)' != '' and '%(Identity)' == '$(_NuGetPackageId)'" />
191214
</ItemGroup>
215+
192216
<PropertyGroup>
193217
<_PrivateAssets>@(_PrimaryPackageReference -> '%(PrivateAssets)')</_PrivateAssets>
218+
<_ShouldPack>@(_PrimaryPackageReference -> '%(Pack)')</_ShouldPack>
194219
<_ShouldIncludeAssetsRegex>$(_NuGetPackageId)\\.+\\$(_PrivateAssets)\\.*</_ShouldIncludeAssetsRegex>
195220
</PropertyGroup>
196221

197-
<ItemGroup Condition="'$(_PrivateAssets)' == 'all'">
222+
<ItemGroup Condition="'$(_ShouldPack)' != 'false' and '$(_PrivateAssets)' == 'all'">
198223
<_InferredPackageFile Include="@(_PrimaryOutputRelatedFile)" Condition="'%(_PrimaryOutputRelatedFile.FrameworkFile)' != 'true'">
199224
<Kind>$(BuildOutputKind)</Kind>
200225
<FrameworkSpecific>$(BuildOutputFrameworkSpecific)</FrameworkSpecific>
201226
</_InferredPackageFile>
202227
</ItemGroup>
203228

204-
<ItemGroup Condition="'$(_PrivateAssets)' != 'all' and '$(_PrivateAssets)' != 'none' and '$(_PrivateAssets)' != ''">
229+
<ItemGroup Condition="'$(_ShouldPack)' != 'false' and '$(_PrivateAssets)' != 'all' and '$(_PrivateAssets)' != 'none' and '$(_PrivateAssets)' != ''">
205230
<!-- In this case, we only add files that have a matching path to the private assets value.
206231
i.e. for Mono.Options, PrivateAssets=lib, we'll include the file if its full path contains
207232
'Mono.Options\*\lib\*', meaning the file is a lib. -->
208-
<_InferredPackageFile Include="@(_PrimaryOutputRelatedFile)" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(_PrimaryOutputRelatedFile.FullPath)', '$(_ShouldIncludeAssetsRegex)', 'RegexOptions.IgnoreCase')) == 'true'">
233+
<_InferredPackageFile Include="@(_PrimaryOutputRelatedFile)"
234+
Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(_PrimaryOutputRelatedFile.FullPath)', '$(_ShouldIncludeAssetsRegex)', 'RegexOptions.IgnoreCase')) == 'true'">
209235
<Kind>$(BuildOutputKind)</Kind>
210236
<FrameworkSpecific>$(BuildOutputFrameworkSpecific)</FrameworkSpecific>
211237
</_InferredPackageFile>

src/NuGetizer.Tasks/NuGetizer.Tasks.csproj

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010
<ItemGroup>
1111
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="all" />
1212
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.9.20" PrivateAssets="all" />
13-
<PackageReference Include="NuGet.Common" Version="5.7.0" PrivateAssets="all" />
14-
<PackageReference Include="NuGet.Frameworks" Version="5.7.0" PrivateAssets="all" />
1513
<PackageReference Include="NuGet.Packaging" Version="5.7.0" PrivateAssets="all" />
1614
<PackageReference Include="NuGet.ProjectManagement" Version="4.2.0" PrivateAssets="all" />
17-
<PackageReference Include="NuGet.Versioning" Version="5.7.0" PrivateAssets="all" />
1815
<PackageReference Include="ThisAssembly" Version="0.10.6" PrivateAssets="all" />
1916
</ItemGroup>
2017

@@ -26,9 +23,7 @@
2623
<None Update="@(None)" CopyToOutputDirectory="PreserveNewest" Pack="true" />
2724
<None Update="NuGetizer.MultiTargeting.props" PackagePath="buildMultiTargeting\NuGetizer.props" />
2825
<None Update="NuGetizer.MultiTargeting.targets" PackagePath="buildMultiTargeting\NuGetizer.targets" />
29-
<None Include="NuGetizer.PackageMetadata.targets;dotnet-nugetize.props;dotnet-nugetize.targets"
30-
PackagePath="buildMultiTargeting\%(Filename)%(Extension)"
31-
Pack="true" />
26+
<None Include="NuGetizer.PackageMetadata.targets;dotnet-nugetize.props;dotnet-nugetize.targets" PackagePath="buildMultiTargeting\%(Filename)%(Extension)" Pack="true" />
3227
<None Include="..\..\img\nugetizer-256.png" Link="icon.png" PackagePath="icon.png" />
3328
</ItemGroup>
3429

src/NuGetizer.Tasks/dotnet-nugetize.targets

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ Copyright (c) .NET Foundation. All rights reserved.
2323
<PackageMetadata Update="@(PackageMetadata)" Nuspec="$(_AbsoluteNuspecFile)" NuPkg="@(PackageTargetPath)" />
2424
<PackageContent Include="@(_PackageContent)" Exclude="@(PackageMetadata)" />
2525
</ItemGroup>
26-
<WriteItemsToFile Overwrite="false" Items="@(PackageMetadata)" ItemName="PackageMetadata" File="$(dotnet-nugetize)" />
27-
<WriteItemsToFile Overwrite="false" Items="@(PackageContent)" ItemName="PackageContent" File="$(dotnet-nugetize)" />
26+
<WriteItemsToFile Condition="'@(PackageMetadata)' != ''" Overwrite="false" Items="@(PackageMetadata)" ItemName="PackageMetadata" File="$(dotnet-nugetize)" />
27+
<WriteItemsToFile Condition="'@(PackageContent)' != ''" Overwrite="false" Items="@(PackageContent)" ItemName="PackageContent" File="$(dotnet-nugetize)" />
2828
</Target>
2929

3030
</Project>

0 commit comments

Comments
 (0)