Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev > Main #9

Merged
merged 13 commits into from
Oct 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ item metadata. It can also be turned off by default for all items of a given typ
The basic item metadata that drive pack inference are:

1. **Pack**: *true*/*false*, determines whether inference applies to the item at all.
2. **PackagePath**: final path within the package.
2. **PackagePath**: final path within the package. Can be a directory path ending in `\` and in that case the item's *RelativeDir*, *Filename* and *Extension* will be appended automatically. Linked files are also supported automatically.

If the item does **not** provide a *PackagePath*, and *Pack* is not *false*, the inference targets wil try to determine the right value, based on the following additional metadata:

Expand Down Expand Up @@ -136,7 +136,7 @@ This even works transitively, so if you use *PrivateAssets=all* on package refer

As usual, you can change this default behavior by using `Pack=false` metadata.

### Project References
### ProjectReference

Unlike SDK Pack that [considers project references as package references by default](https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#project-to-project-references), NuGetizer has an explicit contract between projects: the `GetPackageContents` target. This target is invoked when packing project references, and it returns whatever the referenced project exposes as package contents (including the inference rules above). If the project is *packable* (that is, it produces a package, denoted by the presence of a `PackageId` property), it will be packed as a dependency/package reference instead.

Expand Down Expand Up @@ -181,6 +181,8 @@ Package: Sample.1.0.0.nupkg
sample.pdb
```

Finally, you can focedly turn a project reference build output into a private asset even if it defines a `PackageId` by adding `PrivateAssets=all`. This is very useful for build and analyzer packages, which typically reference the main library project too, but need its output as private, since neither can use dependencies at run-time.

### dotnet-nugetize

Carefully tweaking your packages until they look exactly the way you want them should not be a tedious and slow process. Even requiring your project to be built between changes can be costly and reduce the speed at which you can iterate on the packaging aspects of the project. Also, generating the final `.nupkg`, opening it in a tool and inspecting its content, is also not ideal for rapid iteration.
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<MakeDir Directories="$(PackageOutputPath)" Condition="'$(PackageOutputPath)' != '' And !Exists('$(PackageOutputPath)')" />
</Target>

<Target Name="UpdatePackageMetadata" BeforeTargets="PrepareForBuild;GetAssemblyVersion;GenerateNuspec;Pack" Condition="$(IsPackable) And '$(RepositoryUrl)' != '' And '$(SourceRevisionId)' != ''">
<Target Name="UpdatePackageMetadata" BeforeTargets="PrepareForBuild;GetAssemblyVersion;GetPackageMetadata;GenerateNuspec;Pack" Condition="$(IsPackable) And '$(RepositoryUrl)' != '' And '$(SourceRevisionId)' != ''">
<PropertyGroup>
<Description>
$(Description)
Expand Down
27 changes: 24 additions & 3 deletions src/NuGetizer.Tasks/AssignPackagePath.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using static ThisAssembly.Strings;
using NuGet.Packaging;
using static ThisAssembly.Strings;

namespace NuGetizer.Tasks
{
Expand All @@ -31,6 +32,9 @@ public class AssignPackagePath : Task

public override bool Execute()
{
if (Environment.GetEnvironmentVariable("DEBUG_NUGETIZER") == "1")
Debugger.Break();

var kindMap = KnownFolders.ToDictionary(
kind => kind.ItemSpec,
StringComparer.OrdinalIgnoreCase);
Expand Down Expand Up @@ -79,8 +83,25 @@ ITaskItem EnsurePackagePath(ITaskItem file, IDictionary<string, ITaskItem> kindM
}

// If PackagePath already specified, we're done.
if (!string.IsNullOrEmpty(file.GetMetadata("PackagePath")))
if (file.TryGetMetadata("PackagePath", out var packagePath))
{
// If PackagePath ends in directory separator, we assume
// the file/path needs to be appended too.
if (packagePath.EndsWith("\\"))
{
if (file.TryGetMetadata("Link", out var link))
packagePath = Path.Combine(packagePath, link);
else
packagePath = Path.Combine(packagePath,
file.GetMetadata("RelativeDir"),
file.GetMetadata("FileName") +
file.GetMetadata("Extension"));

output.SetMetadata("PackagePath", packagePath);
}

return output;
}

// If a packaging project is requesting the package path assignment,
// perform it regardless of whether there is a PackageId on the items,
Expand Down Expand Up @@ -180,7 +201,7 @@ ITaskItem EnsurePackagePath(ITaskItem file, IDictionary<string, ITaskItem> kindM
// If we have no known package folder, files go to their RelativeDir location.
// This allows custom packaging paths such as "workbooks", "docs" or whatever, which aren't prohibited by
// the format.
var packagePath = string.IsNullOrEmpty(packageFolder) ?
packagePath = string.IsNullOrEmpty(packageFolder) ?
// File goes to the determined target path (or the root of the package), such as a readme.txt
targetPath :
frameworkSpecific ?
Expand Down
11 changes: 8 additions & 3 deletions src/NuGetizer.Tasks/CreatePackage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
Expand Down Expand Up @@ -41,6 +42,9 @@ public class CreatePackage : Task

public override bool Execute()
{
if (Environment.GetEnvironmentVariable("DEBUG_NUGETIZER") == "1")
Debugger.Break();

try
{
if (bool.TryParse(EmitPackage, out var emitPkg) && emitPkg)
Expand Down Expand Up @@ -78,8 +82,8 @@ public Manifest Execute(Stream output)
public Manifest CreateManifest()
{
var metadata = new ManifestMetadata();
metadata.Id = Manifest.GetMetadata(nameof(MetadataName.PackageId));

metadata.Id = Manifest.GetNullableMetadata(MetadataName.PackageId) ?? Manifest.GetMetadata("Id");

if (Manifest.TryGetMetadata(nameof(ManifestMetadata.Version), out var version))
metadata.Version = NuGetVersion.Parse(Manifest.GetMetadata(MetadataName.Version));
Expand All @@ -102,7 +106,7 @@ public Manifest CreateManifest()
if (Manifest.TryGetMetadata("Copyright", out var copyright))
metadata.Copyright = copyright;

if (Manifest.TryGetBoolMetadata("RequireLicenseAcceptance", out var requireLicenseAcceptance) &&
if (Manifest.TryGetBoolMetadata("RequireLicenseAcceptance", out var requireLicenseAcceptance) &&
requireLicenseAcceptance)
metadata.RequireLicenseAcceptance = requireLicenseAcceptance;

Expand Down Expand Up @@ -185,6 +189,7 @@ void GeneratePackage(Stream output = null)

if (output == null)
{
Directory.CreateDirectory(Path.GetDirectoryName(TargetPath));
using var stream = File.Create(TargetPath);
builder.Save(stream);
}
Expand Down
2 changes: 1 addition & 1 deletion src/NuGetizer.Tasks/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
using System.Runtime.Versioning;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NuGetizer.Tasks;
using NuGet.Frameworks;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGetizer.Tasks;

namespace NuGetizer
{
Expand Down
8 changes: 4 additions & 4 deletions src/NuGetizer.Tasks/InferImplicitPackageReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public override bool Execute()

var inferred = new HashSet<PackageIdentity>();

foreach (var reference in PackageReferences.Where(x =>
foreach (var reference in PackageReferences.Where(x =>
"all".Equals(x.GetMetadata("PrivateAssets"), StringComparison.OrdinalIgnoreCase) &&
// Unless explicitly set to Pack=false
(!x.TryGetBoolMetadata("Pack", out var pack) || pack != false) &&
Expand All @@ -58,8 +58,8 @@ public override bool Execute()
ImplicitPackageReferences = inferred
.Select(x => new TaskItem(
x.Id,
new Dictionary<string, string>
{
new Dictionary<string, string>
{
{ "Version", x.Version } ,
{ "PrivateAssets", "all" },
}))
Expand Down Expand Up @@ -92,7 +92,7 @@ public PackageIdentity(string id, string version)
public string Id { get; }
public string Version { get; }

public override bool Equals(object obj)
public override bool Equals(object obj)
=> obj is PackageIdentity dependency &&
dependency.Id == Id &&
dependency.Version == Version;
Expand Down
4 changes: 3 additions & 1 deletion src/NuGetizer.Tasks/NuGetizer.Shared.targets
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Copyright (c) .NET Foundation. All rights reserved.
</PropertyGroup>

<PropertyGroup Label="Hidden">
<!-- Matches the SDK Pack default when set to true. -->
<PackageId Condition="'$(IsPackable)' == 'true' and '$(PackageId)' == ''">$(AssemblyName)</PackageId>

<IsPackable Condition="'$(IsPackable)' == '' and '$(PackageId)' != ''">true</IsPackable>
<IsPackable Condition="'$(IsPackable)' == '' and '$(PackageId)' == ''">false</IsPackable>
<!-- When the project is building a package, AssignPackagePath always assigns a PackagePath, regardless of the project PackageId -->
Expand Down Expand Up @@ -236,7 +239,6 @@ Copyright (c) .NET Foundation. All rights reserved.
</PropertyGroup>

<Target Name="Pack" DependsOnTargets="$(PackDependsOn)" Returns="@(_PackageTargetPath)" Condition="'$(IsPackable)' == 'true'">
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists('$(PackageOutputPath)')" />
<ItemGroup Condition="'@(NuspecFile)' == ''">
<NuspecFile Include="$(NuspecFile)" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/NuGetizer.Tasks/NuGetizer.Tasks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.9.20" PrivateAssets="all" />
<PackageReference Include="NuGet.Packaging" Version="5.7.0" PrivateAssets="all" />
<PackageReference Include="NuGet.ProjectManagement" Version="4.2.0" PrivateAssets="all" />
<PackageReference Include="ThisAssembly" Version="0.10.6" PrivateAssets="all" />
<PackageReference Include="ThisAssembly" Version="1.0.0-alpha" />
</ItemGroup>

<ItemGroup>
Expand Down
41 changes: 28 additions & 13 deletions src/NuGetizer.Tasks/NuGetizer.targets
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Copyright (c) .NET Foundation. All rights reserved.
item containing the manifest information will also be returned, as

Identity=$(PackageId)
%(PackFolder)=metadata
%(PackFolder)=Metadata
... all manifest values as metadata items ...

All items returned from this target contain a %(PackageId) metadata
Expand Down Expand Up @@ -81,21 +81,22 @@ Copyright (c) .NET Foundation. All rights reserved.
<!-- If packaging the project, provide the metadata as a non-file item -->
<ItemGroup>
<PackageFile Include="@(PackageMetadata)">
<PackFolder>metadata</PackFolder>
<PackFolder>Metadata</PackFolder>
<PackageId>$(PackageId)</PackageId>
<Platform>$(Platform)</Platform>
<TargetFrameworkMoniker Condition="'$(IsPackagingProject)' != 'true'">$(TargetFrameworkMoniker)</TargetFrameworkMoniker>
</PackageFile>
</ItemGroup>
</Target>

<Target Name="_GetReferencedPackageContents"
Condition="'$(_SupportsProjectReferences)' == 'true'"
DependsOnTargets="$(_GetReferencedPackageContentsDependsOn)"
Returns="@(PackageFile)">
<Target Name="_GetReferencedPackageContents"
Condition="'$(_SupportsProjectReferences)' == 'true'"
DependsOnTargets="$(_GetReferencedPackageContentsDependsOn)"
Returns="@(PackageFile)">

<Error Condition="'@(_NonNuGetizedProjectReference)' != ''"
Code="NG0011"
Text="Some project references cannot be properly packaged. Please install the NuGetizer package on the following projects: @(_NonNuGetizedProjectReference)." />
Code="NG0011"
Text="Some project references cannot be properly packaged. Please install the NuGetizer package on the following projects: @(_NonNuGetizedProjectReference)." />

<!--
PackageId metadata on all PackageFile items means we can tell appart which ones came from which dependencies
Expand All @@ -107,30 +108,36 @@ Copyright (c) .NET Foundation. All rights reserved.
<MSBuild Projects="@(_NuGetizedProjectReference)"
Targets="GetPackageContents"
BuildInParallel="$(BuildInParallel)"
Properties="%(_NuGetizedProjectReference.SetConfiguration); %(_NuGetizedProjectReference.SetPlatform); BuildingPackage=$(BuildingPackage); DesignTimeBuild=false"
Properties="%(_NuGetizedProjectReference.SetConfiguration);
%(_NuGetizedProjectReference.SetPlatform);
BuildingPackage=$(BuildingPackage);
DesignTimeBuild=false"
Condition="'@(ProjectReferenceWithConfiguration)' != '' and '@(_NuGetizedProjectReference)' != ''"
RemoveProperties="%(_NuGetizedProjectReference.GlobalPropertiesToRemove)">
<Output TaskParameter="TargetOutputs" ItemName="_ReferencedPackageContent" />
</MSBuild>

<ItemGroup>
<_ReferencedPackageDependency Include="@(_ReferencedPackageContent)"
Condition="'%(_ReferencedPackageContent.PackageId)' != '$(PackageId)' and '%(_ReferencedPackageContent.PackFolder)' == 'metadata'">
Condition="'%(_ReferencedPackageContent.PackageId)' != '$(PackageId)' and
'%(_ReferencedPackageContent.PackFolder)' == 'Metadata'">
<!-- For consistency, annotate like the rest -->
<PackageId Condition="'$(IsPackable)' == 'true'">$(PackageId)</PackageId>
<TargetFrameworkMoniker Condition="'$(IsPackagingProject)' != 'true'">$(TargetFrameworkMoniker)</TargetFrameworkMoniker>
<PackFolder>Dependency</PackFolder>
</_ReferencedPackageDependency>
<!-- Remove the referenced package actual contents if it provides a manifest, since it will be a dependency in that case. -->
<_PackageContentFromDependency Include="@(_ReferencedPackageContent)"
Condition="'%(_ReferencedPackageContent.PackageId)' != '' and '%(_ReferencedPackageContent.PackageId)' != '$(PackageId)'" />
Condition="'%(_ReferencedPackageContent.PackageId)' != '' and
'%(_ReferencedPackageContent.PackageId)' != '$(PackageId)'" />
<_ReferencedPackageContent Remove="@(_PackageContentFromDependency)" />
</ItemGroup>

<!-- Always annotate package contents with the original target framework and moniker -->
<CreateItem Include="@(_ReferencedPackageContent)" PreserveExistingMetadata="true"
Condition="'@(_ReferencedPackageContent)' != ''"
AdditionalMetadata="OriginalTargetFramework=%(_ReferencedPackageContent.TargetFramework);OriginalTargetFrameworkMoniker=%(_ReferencedPackageContent.TargetFrameworkMoniker)">
AdditionalMetadata="OriginalTargetFramework=%(_ReferencedPackageContent.TargetFramework);
OriginalTargetFrameworkMoniker=%(_ReferencedPackageContent.TargetFrameworkMoniker)">
<Output TaskParameter="Include" ItemName="_ReferencedPackageContentWithOriginalValues"/>
</CreateItem>

Expand Down Expand Up @@ -192,14 +199,22 @@ Copyright (c) .NET Foundation. All rights reserved.
<PropertyGroup>
<_ShouldPack>%(_MSBuildProjectReferenceExistent.Pack)</_ShouldPack>
<_IsNuGetized>%(_ReferencedProjectTargetPath.IsNuGetized)</_IsNuGetized>
<_PrivateAssets>%(_MSBuildProjectReferenceExistent.PrivateAssets)</_PrivateAssets>
</PropertyGroup>

<!-- Only process references that aren't excluded from Pack -->
<ItemGroup Condition="'$(_ShouldPack)' != 'false'">
<!-- We will fail for this first group: project references that aren't excluded from packaging, yet haven't been nugetized -->
<_NonNuGetizedProjectReference Include="@(_MSBuildProjectReferenceExistent)" Condition="'$(_IsNuGetized)' != 'true'" />
<!-- We will only process for packaging the project references that haven't been excluded from packaging and are nugetized -->
<_NuGetizedProjectReference Include="@(_MSBuildProjectReferenceExistent)" Condition="'$(_IsNuGetized)' == 'true'" />
<_NuGetizedProjectReference Include="@(_MSBuildProjectReferenceExistent)" Condition="'$(_IsNuGetized)' == 'true'">
<!-- By flagging PrivateAssets=all nugetized references as IsPackable=false, we cause its assets to be
packed together with the build output, instead of referenced as a dependency.
This works because default value for IsPackable checks for '' before defaulting
to whether there is a PackageId property.
Also, passing our own PackFolder causes it to be the overriden default for the referenced project. -->
<AdditionalProperties Condition="'$(_PrivateAssets)' == 'all'">IsPackable=false;PackFolder=$(PackFolder)</AdditionalProperties>
</_NuGetizedProjectReference>
</ItemGroup>

</Target>
Expand Down
Loading