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

error when missing tpv and platform present #3691

Merged
merged 13 commits into from
Oct 21, 2020
Merged
Show file tree
Hide file tree
Changes from 2 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
28 changes: 25 additions & 3 deletions src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ public async Task<RestoreResult> ExecuteAsync(CancellationToken token)
_success = false;
}

_success &= HasValidPlatformVersions();

// evaluate packages.lock.json file
var packagesLockFilePath = PackagesLockFileUtilities.GetNuGetLockFilePath(_request.Project);
var isLockFileValid = false;
Expand Down Expand Up @@ -404,6 +406,26 @@ public async Task<RestoreResult> ExecuteAsync(CancellationToken token)
}
}

private bool HasValidPlatformVersions()
{
IEnumerable<NuGetFramework> badPlatforms = _request.Project.TargetFrameworks
.Select(frameworkInfo => frameworkInfo.FrameworkName)
.Where(framework => !string.IsNullOrEmpty(framework.Platform) && (framework.PlatformVersion == FrameworkConstants.EmptyVersion));

if (badPlatforms.Any())
{
_logger.Log(RestoreLogMessage.CreateError(
NuGetLogCode.NU1012,
string.Format(CultureInfo.CurrentCulture, Strings.Error_PlatformVersionNotPresent, string.Join(", ", badPlatforms))
));
return false;
}
else
{
return true;
}
}

private async Task<bool> AreCentralVersionRequirementsSatisfiedAsync()
{
// The dependencies should not have versions explicitelly defined if cpvm is enabled.
Expand Down Expand Up @@ -627,7 +649,7 @@ private bool ValidatePackagesSha512(PackagesLockFile lockFile, LockFile assetsFi
{
if (!noOp)
{
// Clean up to preserve the pre no-op behavior. This should not be used, but we want to be cautious.
// Clean up to preserve the pre no-op behavior. This should not be used, but we want to be cautious.
_request.LockFilePath = null;
_request.Project.RestoreMetadata.CacheFilePath = null;
}
Expand Down Expand Up @@ -727,7 +749,7 @@ private LockFile BuildAssetsFile(
/// <summary>
/// Check if the given graphs are valid and log errors/warnings.
/// If fatal errors are encountered the rest of the errors/warnings
/// are not logged. This is to avoid flooding the log with long
/// are not logged. This is to avoid flooding the log with long
/// dependency chains for every package.
/// </summary>
private async Task<bool> ValidateRestoreGraphsAsync(IEnumerable<RestoreTargetGraph> graphs, ILogger logger)
Expand Down Expand Up @@ -1108,7 +1130,7 @@ private List<ExternalProjectReference> GetProjectReferences(RemoteWalkContext co
else
{
// External references were passed, but the top level project wasn't found.
// This is always due to an internal issue and typically caused by errors
// This is always due to an internal issue and typically caused by errors
// building the project closure.
Debug.Fail("RestoreRequest.ExternalProjects contains references, but does not contain the top level references. Add the project we are restoring for.");
throw new InvalidOperationException($"Missing external reference metadata for {_request.Project.Name}");
Expand Down
9 changes: 9 additions & 0 deletions src/NuGet.Core/NuGet.Commands/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/NuGet.Core/NuGet.Commands/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1114,4 +1114,7 @@ For more information, visit https://docs.nuget.org/docs/reference/command-line-r
<data name="Error_MultiplePackagePaths" xml:space="preserve">
<value>{0} contains more than one path</value>
</data>
<data name="Error_PlatformVersionNotPresent" xml:space="preserve">
<value>Platform is not present for one or more target framework(s): {0}</value>
zkat marked this conversation as resolved.
Show resolved Hide resolved
</data>
</root>
17 changes: 11 additions & 6 deletions src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
namespace NuGet.Common
{
/// <summary>
/// This enum is used to quantify NuGet error and warning codes.
/// This enum is used to quantify NuGet error and warning codes.
/// Format - NUxyzw where NU is the prefix indicating NuGet and xyzw is a 4 digit code
///
/// Numbers - xyzw
/// x - 'x' is the largest digit and should be used to quantify a set of errors.
/// For example 1yzw are set of restore related errors and no other code path should use the range 1000 to 1999 for errors or warnings.
///
///
/// y - 'y' is the second largest digit and should be used for sub sections withing a broad category.
///
///
/// For example 12zw cvould be http related errors.
/// Further 'y' = 0-4 should be used for errors and 'y' = 5-9 should be warnings.
///
///
/// zw - 'zw' are the least two digit.
/// These could be used for different errors or warnings within the broad categories set by digits 'xy'.
///
Expand All @@ -31,9 +31,9 @@ namespace NuGet.Common
/// 1200/1700 - Compat
/// 1300/1800 - Feed
/// 1400/1900 - Package
///
///
/// All new codes need a corresponding MarkDown file under https://github.com/NuGet/docs.microsoft.com-nuget/tree/master/docs/reference/errors-and-warnings.
///
///
/// </summary>
public enum NuGetLogCode
{
Expand Down Expand Up @@ -102,6 +102,11 @@ public enum NuGetLogCode
/// </summary>
NU1011 = 1011,

/// <summary>
/// Platform version not found.
/// </summary>
NU1012 = 1012,

/// <summary>
/// Unable to resolve package, generic message for unknown type constraints.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode
NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode
1 change: 1 addition & 0 deletions src/NuGet.Core/NuGet.Packaging/Rules/RuleSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static class RuleSet
new UpholdBuildConventionRule(),
new ReferencesInNuspecMatchRefAssetsRule(),
new InvalidUndottedFrameworkRule(),
new TargetFrameworkMissingPlatformVersionRule(),
new IconUrlDeprecationWarning(AnalysisResources.IconUrlDeprecationWarning),
}
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// 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.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using NuGet.Client;
using NuGet.Common;
using NuGet.ContentModel;
using NuGet.Frameworks;
using NuGet.Packaging.Core;
using NuGet.RuntimeModel;

namespace NuGet.Packaging.Rules
{
internal class TargetFrameworkMissingPlatformVersionRule : IPackageRule
zkat marked this conversation as resolved.
Show resolved Hide resolved
{
// NOTE: We never actually generate messages, only error on failure.
public string MessageFormat => "";

public TargetFrameworkMissingPlatformVersionRule()
{
}

public IEnumerable<PackagingLogMessage> Validate(PackageArchiveReader builder)
{
return Validate(new NuspecReader(builder.GetNuspec()), builder.GetFiles());
zkat marked this conversation as resolved.
Show resolved Hide resolved
}

internal static IEnumerable<PackagingLogMessage> Validate(NuspecReader reader, IEnumerable<string> files)
{
var bads = (new string[]
zkat marked this conversation as resolved.
Show resolved Hide resolved
{
ValidateDependencyGroups(reader),
ValidateReferenceGroups(reader),
ValidateFrameworkAssemblies(reader),
ValidateFiles(files)
}).Where(err => err != null);

if (bads.Any())
{
string items = string.Empty;
foreach (string badMessage in bads)
{
items += "\n- " + badMessage;
zkat marked this conversation as resolved.
Show resolved Hide resolved
}
// PackagingLogMessage technically has an Error level, but
// that doesn't look like it fails pack, which is what we need
// to do in this case.
throw new PackagingException(NuGetLogCode.NU1012, string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersions, items));
zkat marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
return new List<PackagingLogMessage>();
}
}

internal static string ValidateDependencyGroups(NuspecReader reader)
{
var bads = new HashSet<string>(reader.GetDependencyGroups()
.Select(group => group.TargetFramework)
.Where(groupFramework => groupFramework.HasPlatform && groupFramework.PlatformVersion == FrameworkConstants.EmptyVersion)
.Select(framework => framework.GetShortFolderName()));
if (bads.Any())
{
return string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromDependencyGroups, string.Join(", ", bads));
}
else
{
return null;
}
}

internal static string ValidateReferenceGroups(NuspecReader reader)
{
var bads = new HashSet<string>(reader.GetReferenceGroups()
.Select(group => group.TargetFramework)
.Where(groupFramework => groupFramework.HasPlatform && groupFramework.PlatformVersion == FrameworkConstants.EmptyVersion)
.Select(framework => framework.GetShortFolderName()));
if (bads.Any())
{
return string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromReferenceGroups, string.Join(", ", bads));
}
else
{
return null;
}
}

internal static string ValidateFrameworkAssemblies(NuspecReader reader)
{
var bads = new HashSet<string>(reader.GetFrameworkAssemblyGroups()
.Select(group => group.TargetFramework)
.Where(groupFramework => groupFramework.HasPlatform && groupFramework.PlatformVersion == FrameworkConstants.EmptyVersion)
.Select(framework => framework.GetShortFolderName()));
if (bads.Any())
{
return string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromFrameworkAssemblyGroups, string.Join(", ", bads));
}
else
{
return null;
}
}

internal static string ValidateFiles(IEnumerable<string> files)
{
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var file in files.Select(t => PathUtility.GetPathWithDirectorySeparator(t)))
{
set.Add(file);
}

var managedCodeConventions = new ManagedCodeConventions(new RuntimeGraph());
var collection = new ContentItemCollection();
collection.Load(set.Select(path => path.Replace('\\', '/')).ToArray());

var patterns = managedCodeConventions.Patterns;

var frameworkPatterns = new List<PatternSet>()
{
patterns.RuntimeAssemblies,
patterns.CompileRefAssemblies,
patterns.CompileLibAssemblies,
patterns.NativeLibraries,
patterns.ResourceAssemblies,
patterns.MSBuildFiles,
patterns.ContentFiles,
patterns.ToolsAssemblies,
patterns.EmbedAssemblies,
patterns.MSBuildTransitiveFiles
};
var warnPaths = new HashSet<string>();

var bads = new HashSet<string>();
foreach (var pattern in frameworkPatterns)
{
IEnumerable<ContentItemGroup> targetedItemGroups = ContentExtractor.GetContentForPattern(collection, pattern);
foreach (ContentItemGroup group in targetedItemGroups)
{
foreach (ContentItem item in group.Items)
{
var framework = (NuGetFramework)item.Properties["tfm"];
if (framework == null)
{
continue;
}

if (framework.HasPlatform && framework.PlatformVersion == FrameworkConstants.EmptyVersion)
{
bads.Add(framework.GetShortFolderName());
}
}
}
}

if (bads.Any())
{
return string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromIncludedFiles, string.Join(", ", bads));
}
else
{
return null;
}
}
}
}

45 changes: 45 additions & 0 deletions src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading