Skip to content

Commit 43ba6f0

Browse files
authored
dotnet list package works with unlisted and prerelease packages (#7038)
1 parent 9984777 commit 43ba6f0

7 files changed

Lines changed: 321 additions & 22 deletions

File tree

src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PackageReferenceCommands/ListPackage/ListPackageCommandRunner.cs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ internal async Task<Dictionary<string, List<IPackageSearchMetadata>>> GetPackage
422422
: (Environment.ProcessorCount / listPackageArgs.PackageSources.Count) + 1;
423423

424424
await ThrottledForEachAsync(allPackages,
425-
async (packageId, cancellationToken) => await GetPackageVersionsAsync(packageId, listPackageArgs, cancellationToken),
425+
async (packageId, cancellationToken) => await GetPackageMetadataAsync(packageId, listPackageArgs, cancellationToken),
426426
packageMetadata => packageMetadataById[packageMetadata.Key] = packageMetadata.Value,
427427
maxParallel,
428428
listPackageArgs.CancellationToken);
@@ -559,7 +559,10 @@ internal async Task UpdatePackagesWithSourceMetadata(
559559
// Get latest metadata *only* if this is a report requiring "outdated" metadata
560560
if (listPackageArgs.ReportType == ReportType.Outdated && matchingPackage.Count > 0)
561561
{
562-
var latestVersion = matchingPackage.Where(newVersion => MeetsConstraints(newVersion.Identity.Version, topLevelPackage, listPackageArgs)).Max(i => i.Identity.Version);
562+
var latestVersion = matchingPackage
563+
.Where(package => package.IsListed)
564+
.Where(newVersion => MeetsConstraints(newVersion.Identity.Version, topLevelPackage, listPackageArgs))
565+
.Max(i => i.Identity.Version);
563566

564567
if (latestVersion is not null)
565568
{
@@ -595,7 +598,10 @@ internal async Task UpdatePackagesWithSourceMetadata(
595598
// Get latest metadata *only* if this is a report requiring "outdated" metadata
596599
if (listPackageArgs.ReportType == ReportType.Outdated && matchingPackage.Count > 0)
597600
{
598-
var latestVersion = matchingPackage.Where(newVersion => MeetsConstraints(newVersion.Identity.Version, transitivePackage, listPackageArgs)).Max(i => i.Identity.Version);
601+
var latestVersion = matchingPackage
602+
.Where(newVersion => newVersion.IsListed)
603+
.Where(newVersion => MeetsConstraints(newVersion.Identity.Version, transitivePackage, listPackageArgs))
604+
.Max(i => i.Identity.Version);
599605

600606
transitivePackage.LatestPackageMetadata = matchingPackage.First(p => p.Identity.Version == latestVersion);
601607
transitivePackage.UpdateLevel = GetUpdateLevel(transitivePackage.ResolvedPackageMetadata.Identity.Version, transitivePackage.LatestPackageMetadata.Identity.Version);
@@ -645,14 +651,13 @@ private UpdateLevel GetUpdateLevel(NuGetVersion resolvedVersion, NuGetVersion la
645651
}
646652

647653
/// <summary>
648-
/// Prepares the calls to sources for latest versions and updates
649-
/// the list of tasks with the requests
654+
/// Gets the package metadata for a specific package from all sources
650655
/// </summary>
651656
/// <param name="package">The package to get the latest version for</param>
652657
/// <param name="listPackageArgs">List args for the token and source provider></param>
653658
/// <param name="cancellationToken"></param>
654659
/// <returns>A list of tasks for all latest versions for packages from all sources</returns>
655-
private async Task<KeyValuePair<string, List<IPackageSearchMetadata>>> GetPackageVersionsAsync(
660+
private async Task<KeyValuePair<string, List<IPackageSearchMetadata>>> GetPackageMetadataAsync(
656661
string package,
657662
ListPackageArgs listPackageArgs,
658663
CancellationToken cancellationToken)
@@ -661,7 +666,7 @@ private async Task<KeyValuePair<string, List<IPackageSearchMetadata>>> GetPackag
661666
var sources = listPackageArgs.PackageSources;
662667

663668
await ThrottledForEachAsync(sources,
664-
async (source, innerCancellationToken) => await GetLatestVersionPerSourceAsync(source, listPackageArgs, package, innerCancellationToken),
669+
async (source, innerCancellationToken) => await GetPackageMetadataAsync(source, listPackageArgs, package, innerCancellationToken),
665670
continuation: results.AddRange,
666671
maxParallel: listPackageArgs.PackageSources.Count,
667672
cancellationToken);
@@ -670,14 +675,14 @@ await ThrottledForEachAsync(sources,
670675
}
671676

672677
/// <summary>
673-
/// Gets the highest version of a package from a specific source
678+
/// Gets package metadata for a specific package from a specific source
674679
/// </summary>
675680
/// <param name="packageSource">The source to look for packages at</param>
676681
/// <param name="listPackageArgs">The list args for the cancellation token</param>
677682
/// <param name="package">Package to look for updates for</param>
678683
/// <param name="cancellationToken"></param>
679684
/// <returns>An updated package with the highest version at a single source</returns>
680-
private async Task<IEnumerable<IPackageSearchMetadata>> GetLatestVersionPerSourceAsync(
685+
private async Task<IEnumerable<IPackageSearchMetadata>> GetPackageMetadataAsync(
681686
PackageSource packageSource,
682687
ListPackageArgs listPackageArgs,
683688
string package,
@@ -687,11 +692,16 @@ private async Task<IEnumerable<IPackageSearchMetadata>> GetLatestVersionPerSourc
687692
var packageMetadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>(cancellationToken);
688693

689694
using var sourceCacheContext = new SourceCacheContext();
695+
// This is used for --outdated, --deprecated, and --vulnerable.
696+
// So, we need the package metadata for the currently installed version,
697+
// even if it's pre-release or unlisted.
698+
// This means that the logic for --outdated has to do filtering based on IsListed and
699+
// prerelease.
690700
IEnumerable<IPackageSearchMetadata> packages =
691701
await packageMetadataResource.GetMetadataAsync(
692702
package,
693-
includePrerelease: listPackageArgs.Prerelease,
694-
includeUnlisted: false,
703+
includePrerelease: true,
704+
includeUnlisted: true,
695705
sourceCacheContext: sourceCacheContext,
696706
log: listPackageArgs.Logger,
697707
token: listPackageArgs.CancellationToken);
@@ -710,7 +720,7 @@ await packageMetadataResource.GetMetadataAsync(
710720
/// <returns>Whether the new version meets the constraints or not</returns>
711721
private bool MeetsConstraints(NuGetVersion newVersion, InstalledPackageReference package, ListPackageArgs listPackageArgs)
712722
{
713-
var result = !newVersion.IsPrerelease || listPackageArgs.Prerelease || package.ResolvedPackageMetadata.Identity.Version.IsPrerelease;
723+
var result = !newVersion.IsPrerelease || listPackageArgs.Prerelease;
714724

715725
if (listPackageArgs.HighestPatch)
716726
{

test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,12 @@ public static void CreatePackage(string repositoryPath, string id, string versio
559559
/// </summary>
560560
public static JObject CreateSinglePackageRegistrationBlob(MockServer server, string id, string version)
561561
{
562-
return FeedUtilities.CreatePackageRegistrationBlob(server.Uri, id, new KeyValuePair<string, bool>[] { new KeyValuePair<string, bool>(version, true) }, new HashSet<PackageIdentity>());
562+
return FeedUtilities.CreatePackageRegistrationBlob(
563+
server.Uri,
564+
id,
565+
new KeyValuePair<string, bool>[] { new KeyValuePair<string, bool>(version, true) },
566+
new HashSet<PackageIdentity>(),
567+
null);
563568
}
564569

565570
public static string CreateProjFileContent(

test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetIntegrationTestFixture.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ internal CommandRunnerResult RunDotnet(string workingDirectory, string args = ""
182182
// the one set by the _inner_ (test environment-specific) dotnet cli call we're about to make.
183183
// We need to ensure that this points to the correct SDK directory because this value
184184
// is used to locate many Tasks - especially those located by relative path or name.
185-
["MSBuildExtensionsPath"] = SdkDirectory.FullName
185+
["MSBuildExtensionsPath"] = SdkDirectory.FullName,
186+
["PATH"] = $"{_cliDirectory}{Path.PathSeparator}{Environment.GetEnvironmentVariable("PATH")}"
186187
};
187188

188189
if (enableDiagnostics)

0 commit comments

Comments
 (0)