Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,8 @@ private static bool ShouldPrunePackage(
return false;
}

if (isRootProject)
if (isRootProject) // Don't prune direct PRs
{
if (enablePruningWarnings && SdkAnalysisLevelMinimums.IsEnabled(
projectRestoreMetadata.SdkAnalysisLevel,
projectRestoreMetadata.UsingMicrosoftNETSdk,
SdkAnalysisLevelMinimums.PruningWarnings))
{
logger.Log(RestoreLogMessage.CreateWarning(NuGetLogCode.NU1510, string.Format(CultureInfo.CurrentCulture, Strings.Error_RestorePruningDirectPackageReference, dependency.Name),
dependency.Name,
targetGraphName));
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1414,7 +1414,7 @@ .. chosenResolvedItem.Suppressions

private static bool IsNewerThanNET10(NuGetFramework frameworkName)
{
if (frameworkName.Framework == FrameworkConstants.FrameworkIdentifiers.NetCoreApp)
if (StringComparer.OrdinalIgnoreCase.Equals(frameworkName.Framework, FrameworkConstants.FrameworkIdentifiers.NetCoreApp))
{
return frameworkName.Version.Major >= 10;
}
Expand Down
126 changes: 126 additions & 0 deletions src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ public async Task<RestoreResult> ExecuteAsync(CancellationToken token)
packagesLockFile,
token);

AnalyzePruningResults(_request.Project, _logger);

var graphs = await GenerateRestoreGraphsAsync(telemetry, contextForProject, token);

bool auditRan = false;
Expand Down Expand Up @@ -758,6 +760,130 @@ private bool HasValidPlatformVersions()
}
}

internal static void AnalyzePruningResults(PackageSpec project, ILogger logger)
{
bool enablePruningWarnings =
SdkAnalysisLevelMinimums.IsEnabled(
project.RestoreMetadata.SdkAnalysisLevel,
project.RestoreMetadata.UsingMicrosoftNETSdk,
SdkAnalysisLevelMinimums.PruningWarnings) &&
HasFrameworkNewerThanNET10(project);

if (!enablePruningWarnings)
{
return;
}

Dictionary<string, List<string>> prunedDirectPackages = GetPrunableDirectPackages(project);

if (prunedDirectPackages != null)
{
RaiseNU1510WarningsIfNeeded(project, logger, prunedDirectPackages);
}

static Dictionary<string, List<string>> GetPrunableDirectPackages(PackageSpec project)
{
Dictionary<string, List<string>> prunedDirectPackages = null;

// Calculate direct packages that are in the pruning range.
foreach (TargetFrameworkInformation framework in project.TargetFrameworks)
{
if (framework.PackagesToPrune != null && framework.PackagesToPrune.Count > 0)
{
foreach (var dependency in framework.Dependencies)
{
if (framework.PackagesToPrune.TryGetValue(dependency.Name, out PrunePackageReference packageToPrune)
&& dependency.LibraryRange.VersionRange.Satisfies(packageToPrune.VersionRange.MaxVersion!))
{
prunedDirectPackages ??= new(StringComparer.OrdinalIgnoreCase);
if (!prunedDirectPackages.ContainsKey(dependency.Name))
{
prunedDirectPackages.Add(dependency.Name, [framework.TargetAlias]);
}
else
{
prunedDirectPackages[dependency.Name].Add(framework.TargetAlias);
}
}
}
}
}

return prunedDirectPackages;
}

static void RaiseNU1510WarningsIfNeeded(PackageSpec project, ILogger logger, Dictionary<string, List<string>> prunedDirectPackages)
{
Dictionary<string, string> aliasToTargetGraphName = null;
foreach (var prunedPackage in prunedDirectPackages)
{
// Do not warn if the package exists in any framework.
if (prunedPackage.Value.Count != project.TargetFrameworks.Count)
{
bool doesPackageRemain = false;
foreach (var framework in project.TargetFrameworks)
{
if (!prunedPackage.Value.Contains(framework.TargetAlias))
{
if (ContainsPackage(prunedPackage, framework))
{
doesPackageRemain = true;
break;
}
}
}
if (doesPackageRemain)
{
continue;
}
}

aliasToTargetGraphName ??= InitializeAliasToTargetGraphName(project);
logger.Log(RestoreLogMessage.CreateWarning(
NuGetLogCode.NU1510,
string.Format(CultureInfo.CurrentCulture, Strings.Error_RestorePruningDirectPackageReference, prunedPackage.Key),
prunedPackage.Key,
prunedPackage.Value.Select(e => aliasToTargetGraphName[e]).ToArray()));
}
}

static bool HasFrameworkNewerThanNET10(PackageSpec project)
{
foreach (var framework in project.TargetFrameworks.NoAllocEnumerate())
{
if (StringComparer.OrdinalIgnoreCase.Equals(framework.FrameworkName.Framework, FrameworkConstants.FrameworkIdentifiers.NetCoreApp) &&
framework.FrameworkName.Version.Major >= 10)
{
return true;
}
}
return false;
}

static Dictionary<string, string> InitializeAliasToTargetGraphName(PackageSpec project)
{
var aliasToTargetGraphName = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var framework in project.TargetFrameworks)
{
aliasToTargetGraphName.Add(framework.TargetAlias, FrameworkRuntimePair.GetTargetGraphName(framework.FrameworkName, runtimeIdentifier: null));
}

return aliasToTargetGraphName;
}

static bool ContainsPackage(KeyValuePair<string, List<string>> prunedPackage, TargetFrameworkInformation framework)
{
foreach (var dependency in framework.Dependencies.NoAllocEnumerate())
{
if (dependency.Name.Equals(prunedPackage.Key, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}

private async Task<bool> AreCentralVersionRequirementsSatisfiedAsync(RestoreRequest restoreRequest, int httpSourcesCount)
{
if (restoreRequest?.Project?.RestoreMetadata == null || !restoreRequest.Project.RestoreMetadata.CentralPackageVersionsEnabled)
Expand Down
Loading