diff --git a/src/NuGet.Core/NuGet.Protocol/Resources/PackageSearchResourceV3.cs b/src/NuGet.Core/NuGet.Protocol/Resources/PackageSearchResourceV3.cs index ba8f1b5ee22..eb27c8b0b8f 100644 --- a/src/NuGet.Core/NuGet.Protocol/Resources/PackageSearchResourceV3.cs +++ b/src/NuGet.Core/NuGet.Protocol/Resources/PackageSearchResourceV3.cs @@ -83,19 +83,19 @@ public override async Task> SearchAsync(stri private static IEnumerable GetVersions(PackageSearchMetadata metadata, SearchFilter filter) { - var versions = metadata.ParsedVersions; - - // TODO: in v2, we only have download count for all versions, not per version. - // To be consistent, in v3, we also use total download count for now. - var totalDownloadCount = versions.Select(v => v.DownloadCount).Sum(); - versions = versions - .Select(v => v.Version) - .Where(v => filter.IncludePrerelease || !v.IsPrerelease) - .Concat(new[] { metadata.Version }) - .Distinct() - .Select(v => new VersionInfo(v, totalDownloadCount)) - .ToArray(); - + var uniqueVersions = new HashSet(); + var versions = new List(); + foreach (var ver in metadata.ParsedVersions) + { + if ((filter.IncludePrerelease || !ver.Version.IsPrerelease) && uniqueVersions.Add(ver.Version)) + { + versions.Add(new VersionInfo(ver.Version, ver.DownloadCount)); + } + } + if (uniqueVersions.Add(metadata.Version)) + { + versions.Add(new VersionInfo(metadata.Version, metadata.DownloadCount)); + } return versions; } diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/PackageSearchResourceV3Tests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/PackageSearchResourceV3Tests.cs index 3c133b784af..0f63ac34cba 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/PackageSearchResourceV3Tests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/PackageSearchResourceV3Tests.cs @@ -105,6 +105,38 @@ public async Task PackageSearchResourceV3_GetMetadataAsync_NotFound() Assert.Empty(packages); } + [Fact] + public async Task PackageSearchResourceV3_GetMetadataAsync_VersionsDownloadCount() + { + // Arrange + var responses = new Dictionary(); + responses.Add("https://api-v3search-0.nuget.org/query?q=entityframework&skip=0&take=1&prerelease=false&semVerLevel=2.0.0", + ProtocolUtility.GetResource("NuGet.Protocol.Tests.compiler.resources.EntityFrameworkSearch.json", GetType())); + responses.Add("http://testsource.com/v3/index.json", JsonData.IndexWithoutFlatContainer); + + var repo = StaticHttpHandler.CreateSource("http://testsource.com/v3/index.json", Repository.Provider.GetCoreV3(), responses); + + var resource = await repo.GetResourceAsync(); + + // Act + var packages = await resource.SearchAsync( + "entityframework", + new SearchFilter(false), + skip: 0, + take: 1, + log: NullLogger.Instance, + cancellationToken: CancellationToken.None); + + var package = packages.SingleOrDefault(); + + var versions = await package.GetVersionsAsync(); + + // Assert + Assert.Equal(28390569, package.DownloadCount); + Assert.Equal(14, versions.Count()); + Assert.Equal(64099, versions.First().DownloadCount); + } + [Fact] public async Task PackageSearchResourceV3_SearchEncoding() {