Skip to content
Open
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
115 changes: 115 additions & 0 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack/GetPackOutputItemsLogic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable enable

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NuGet.Commands;
using NuGet.Common;
using NuGet.Versioning;

namespace NuGet.Build.Tasks.Pack
{
public static class GetPackOutputItemsLogic
{
public static void GetOutputFilePaths(IOutputFilePathProvider source, IOutputFilePath output)
{
var packageId = source.PackageId;
var packageVersion = source.PackageVersion;

if (!string.IsNullOrWhiteSpace(source.NuspecFile))
{
bool hasVersionInNuspecProperties = false;
bool hasIdInNuspecProperties = false;
if (source.NuspecProperties != null && source.NuspecProperties.Length > 0)
{
PackArgs packArgs = new PackArgs() { Version = packageVersion };
PackTaskLogic.SetPackArgsPropertiesFromNuspecProperties(packArgs, MSBuildStringUtility.TrimAndExcludeNullOrEmpty(source.NuspecProperties));
// If the logic depends only on checking for a non-null value, it may incorrectly detect cases where the parsing logic changes the version based on a key other than the "version" key.
if (packArgs.Properties.ContainsKey("version"))
{
packageVersion = packArgs.Version;
hasVersionInNuspecProperties = true;
}
if (packArgs.Properties.TryGetValue("id", out var idTemp))
{
packageId = idTemp;
hasIdInNuspecProperties = true;
}
}

var nuspecReader = new NuGet.Packaging.NuspecReader(source.NuspecFile);
if (!hasIdInNuspecProperties)
{
packageId = nuspecReader.GetId();
}
if (!hasVersionInNuspecProperties)
{
packageVersion = nuspecReader.GetVersion().ToNormalizedString();
}
}

if (!NuGetVersion.TryParse(packageVersion, out var versionTemp))
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
Strings.InvalidPackageVersion,
packageVersion));
}
NuGetVersion version = versionTemp!;

var symbolPackageFormat = PackArgs.GetSymbolPackageFormat(MSBuildStringUtility.TrimAndGetNullForEmpty(source.SymbolPackageFormat));
var nupkgFileName = PackCommandRunner.GetOutputFileName(packageId, version!, isNupkg: true, symbols: false, symbolPackageFormat: symbolPackageFormat, excludeVersion: source.OutputFileNamesWithoutVersion);
var nuspecFileName = PackCommandRunner.GetOutputFileName(packageId, version!, isNupkg: false, symbols: false, symbolPackageFormat: symbolPackageFormat, excludeVersion: source.OutputFileNamesWithoutVersion);

var outputs = new List<ITaskItem>();

output.OutputNupkgFilePath = Path.Combine(source.PackageOutputPath, nupkgFileName);
output.OutputNuspecFilePath = Path.Combine(source.NuspecOutputPath, nuspecFileName);

outputs.Add(new TaskItem(output.OutputNupkgFilePath));
outputs.Add(new TaskItem(output.OutputNuspecFilePath));

if (source.IncludeSource || source.IncludeSymbols)
{
var nupkgSymbolsFileName = PackCommandRunner.GetOutputFileName(packageId, version, isNupkg: true, symbols: true, symbolPackageFormat: symbolPackageFormat, excludeVersion: source.OutputFileNamesWithoutVersion);
var nuspecSymbolsFileName = PackCommandRunner.GetOutputFileName(packageId, version, isNupkg: false, symbols: true, symbolPackageFormat: symbolPackageFormat, excludeVersion: source.OutputFileNamesWithoutVersion);

output.OutputNupkgSymbolsFilePath = Path.Combine(source.PackageOutputPath, nupkgSymbolsFileName);
output.OutputNuspecSymbolsFilePath = Path.Combine(source.NuspecOutputPath, nuspecSymbolsFileName);

outputs.Add(new TaskItem(output.OutputNupkgSymbolsFilePath));
outputs.Add(new TaskItem(output.OutputNuspecSymbolsFilePath));
}

output.OutputPackItems = outputs.ToArray();
}

public static IOutputFilePath GetOutputFilePaths(IOutputFilePathProvider source)
{
var output = new GetPackOutputItemsTask();
Copy(source, output);
GetOutputFilePaths(source, output);
return output;
}

public static void Copy(IOutputFilePathProvider source, IOutputFilePathProvider destination)
{
destination.PackageId = source.PackageId;
destination.PackageVersion = source.PackageVersion;
destination.PackageOutputPath = source.PackageOutputPath;
destination.NuspecOutputPath = source.NuspecOutputPath;
destination.NuspecFile = source.NuspecFile;
destination.NuspecProperties = source.NuspecProperties;
destination.IncludeSource = source.IncludeSource;
destination.IncludeSymbols = source.IncludeSymbols;
destination.SymbolPackageFormat = source.SymbolPackageFormat;
destination.OutputFileNamesWithoutVersion = source.OutputFileNamesWithoutVersion;
}
}
}
49 changes: 13 additions & 36 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack/GetPackOutputItemsTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,11 @@

#nullable disable

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NuGet.Commands;
using NuGet.Common;
using NuGet.Versioning;

namespace NuGet.Build.Tasks.Pack
{
public class GetPackOutputItemsTask : Microsoft.Build.Utilities.Task
public class GetPackOutputItemsTask : Microsoft.Build.Utilities.Task, IOutputFilePathProvider, IOutputFilePath
{
[Required]
public string PackageId { get; set; }
Expand All @@ -29,47 +21,32 @@ public class GetPackOutputItemsTask : Microsoft.Build.Utilities.Task
[Required]
public string NuspecOutputPath { get; set; }

public string NuspecFile { get; set; }

public string[] NuspecProperties { get; set; }

public bool IncludeSymbols { get; set; }

public bool IncludeSource { get; set; }

public string SymbolPackageFormat { get; set; }

public bool OutputFileNamesWithoutVersion { get; set; }

/// <summary>
/// Output items
/// </summary>
[Output]
public ITaskItem[] OutputPackItems { get; set; }

public string OutputNupkgFilePath { get; set; }
public string OutputNuspecFilePath { get; set; }
public string OutputNupkgSymbolsFilePath { get; set; }
public string OutputNuspecSymbolsFilePath { get; set; }

public override bool Execute()
{
NuGetVersion version;
if (!NuGetVersion.TryParse(PackageVersion, out version))
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
Strings.InvalidPackageVersion,
PackageVersion));
}

var symbolPackageFormat = PackArgs.GetSymbolPackageFormat(MSBuildStringUtility.TrimAndGetNullForEmpty(SymbolPackageFormat));
var nupkgFileName = PackCommandRunner.GetOutputFileName(PackageId, version, isNupkg: true, symbols: false, symbolPackageFormat: symbolPackageFormat);
var nuspecFileName = PackCommandRunner.GetOutputFileName(PackageId, version, isNupkg: false, symbols: false, symbolPackageFormat: symbolPackageFormat);

var outputs = new List<ITaskItem>();
outputs.Add(new TaskItem(Path.Combine(PackageOutputPath, nupkgFileName)));
outputs.Add(new TaskItem(Path.Combine(NuspecOutputPath, nuspecFileName)));

if (IncludeSource || IncludeSymbols)
{
var nupkgSymbolsFileName = PackCommandRunner.GetOutputFileName(PackageId, version, isNupkg: true, symbols: true, symbolPackageFormat: symbolPackageFormat);
var nuspecSymbolsFileName = PackCommandRunner.GetOutputFileName(PackageId, version, isNupkg: false, symbols: true, symbolPackageFormat: symbolPackageFormat);

outputs.Add(new TaskItem(Path.Combine(PackageOutputPath, nupkgSymbolsFileName)));
outputs.Add(new TaskItem(Path.Combine(NuspecOutputPath, nuspecSymbolsFileName)));
}

OutputPackItems = outputs.ToArray();
GetPackOutputItemsLogic.GetOutputFilePaths(this, this);
return true;
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack/IOutputFilePath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable disable

using Microsoft.Build.Framework;

namespace NuGet.Build.Tasks.Pack
{
public interface IOutputFilePath
{
[Output]
public ITaskItem[] OutputPackItems { get; set; }

public string OutputNupkgFilePath { get; set; }
public string OutputNuspecFilePath { get; set; }
public string OutputNupkgSymbolsFilePath { get; set; }
public string OutputNuspecSymbolsFilePath { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable disable

using Microsoft.Build.Framework;

namespace NuGet.Build.Tasks.Pack
{
public interface IOutputFilePathProvider
{
[Required]
string PackageId { get; set; }

[Required]
string PackageVersion { get; set; }

[Required]
string PackageOutputPath { get; set; }

[Required]
string NuspecOutputPath { get; set; }

string NuspecFile { get; set; }

string[] NuspecProperties { get; set; }

bool IncludeSource { get; set; }

bool IncludeSymbols { get; set; }

string SymbolPackageFormat { get; set; }

bool OutputFileNamesWithoutVersion { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace NuGet.Build.Tasks.Pack
{
public class PackTask : Microsoft.Build.Utilities.Task, IPackTaskRequest<ITaskItem>
public class PackTask : Microsoft.Build.Utilities.Task, IPackTaskRequest<ITaskItem>, IOutputFilePathProvider
{
private readonly IEnvironmentVariableReader _environmentVariableReader;

Expand Down
30 changes: 22 additions & 8 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,7 @@ public PackArgs GetPackArgs(IPackTaskRequest<IMSBuildItem> request)

if (!string.IsNullOrEmpty(request.NuspecFile))
{
if (request.NuspecProperties != null && request.NuspecProperties.Any())
{
packArgs.Properties.AddRange(ParsePropertiesAsDictionary(request.NuspecProperties));
if (packArgs.Properties.TryGetValue("version", out var version))
{
packArgs.Version = version;
}
}
SetPackArgsPropertiesFromNuspecProperties(packArgs, request.NuspecProperties);
}
else
{
Expand Down Expand Up @@ -1172,6 +1165,27 @@ private static IDictionary<string, string> ParsePropertiesAsDictionary(string[]
return dictionary;
}

internal static void SetPackArgsPropertiesFromNuspecProperties(PackArgs packArgs, string[] nuspecProperties)
{
if (nuspecProperties == null || !nuspecProperties.Any())
{
return;
}

packArgs.Properties.AddRange(ParsePropertiesAsDictionary(nuspecProperties));
if (packArgs.Properties.TryGetValue("version", out var packageVersion))
{
if (!NuGetVersion.TryParse(packageVersion, out var version))
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
Strings.InvalidPackageVersion,
packageVersion));
}
packArgs.Version = version.ToNormalizedString();
}
}

private HashSet<string> InitOutputExtensions(IEnumerable<string> outputExtensions)
{
return new HashSet<string>(outputExtensions.Distinct(StringComparer.OrdinalIgnoreCase));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,21 @@ Copyright (c) .NET Foundation. All rights reserved.

<!-- 'PackageOutputAbsolutePath' and 'NuspecOutputAbsolutePath' will be provided by '_GetAbsoluteOutputPathsForPack' target -->

<ConvertToAbsolutePath Condition="$(NuspecFile) != ''" Paths="$(NuspecFile)">
<Output TaskParameter="AbsolutePaths" PropertyName="NuspecFileAbsolutePath" />
</ConvertToAbsolutePath>

<GetPackOutputItemsTask
PackageOutputPath="$(PackageOutputAbsolutePath)"
NuspecOutputPath="$(NuspecOutputAbsolutePath)"
NuspecFile="$(NuspecFileAbsolutePath)"
NuspecProperties="$(NuspecProperties)"
PackageId="$(PackageId)"
PackageVersion="$(PackageVersion)"
IncludeSymbols="$(IncludeSymbols)"
IncludeSource="$(IncludeSource)"
SymbolPackageFormat="$(SymbolPackageFormat)">

SymbolPackageFormat="$(SymbolPackageFormat)"
OutputFileNamesWithoutVersion="$(OutputFileNamesWithoutVersion)">
<Output
TaskParameter="OutputPackItems"
ItemName="_OutputPackItems" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable enable

using System.Collections.Generic;
using System.Linq;
using NuGet.Test.Utility;
using Xunit;
using Xunit.Abstractions;

namespace NuGet.Build.Tasks.Pack.Test
{
public class GetPackOutputItemsTaskTests
{
private readonly ITestOutputHelper _testOutputHelper;

public static IEnumerable<object[]> PackageFileNameTestCases => PackageFileNameTestCase.TestCases;

public GetPackOutputItemsTaskTests(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}

// This unit test verifies that GetPackOutputItemsTask outputs the expected file name.
[Theory]
[MemberData(nameof(PackageFileNameTestCases))]
public void GetPackOutputItemsTaskTests_Execute_CheckPackageFileName(PackageFileNameTestCase testCase)
{
var outputItemTask = new NuGet.Build.Tasks.Pack.GetPackOutputItemsTask();
outputItemTask.PackageId = testCase.IdProjProp;
outputItemTask.PackageVersion = testCase.VersionProjProp;
outputItemTask.IncludeSymbols = testCase.IncludeSymbols;
outputItemTask.SymbolPackageFormat = PackageFileNameTestsCommon.GetSymbolPackageFormatText(testCase.SymbolPackageFormat);
outputItemTask.OutputFileNamesWithoutVersion = testCase.OutputFileNamesWithoutVersion;
if (!string.IsNullOrWhiteSpace(testCase.VersionNuspecProperties))
{
outputItemTask.NuspecProperties = new string[] { $"version={testCase.VersionNuspecProperties}" };
}

using (var testDirectory = TestDirectory.Create())
{
outputItemTask.PackageOutputPath = testDirectory.Path;
outputItemTask.NuspecOutputPath = testDirectory.Path;
if (testCase.UseNuspecFile)
{
outputItemTask.NuspecFile = System.IO.Path.Combine(testDirectory.Path, PackageFileNameTestsCommon.FILENAME_NUSPEC_FILE);
}

PackageFileNameTestsCommon.CreateTestProjectFileAndNuspecFile(testCase, testDirectory);

Assert.True(outputItemTask.Execute());

foreach (string outputNupkgName in testCase.OutputNupkgNames)
{
string[] itemSpecs = outputItemTask.OutputPackItems.Select(item => item.ItemSpec).ToArray();
var matchCount = PackageFileNameTestsCommon.GetNameMatchFilePathCount(outputNupkgName, itemSpecs);
Assert.True(matchCount == 1, $"{outputNupkgName} is not found in output. [{string.Join(" , ", itemSpecs.Select(_ => System.IO.Path.GetFileName(_)))}]");
}
}
}
}
}
Loading