Skip to content

Commit ee25a4e

Browse files
Add initial reverse dependencies feat (without view) (#7988)
Progress on #4718
1 parent ac27bd5 commit ee25a4e

20 files changed

Lines changed: 875 additions & 10 deletions

File tree

src/NuGetGallery.Core/Entities/EntitiesContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public EntitiesContext(DbConnection connection, bool readOnly)
6060
public DbSet<Package> Packages { get; set; }
6161
public DbSet<PackageDeprecation> Deprecations { get; set; }
6262
public DbSet<PackageRegistration> PackageRegistrations { get; set; }
63+
public DbSet<PackageDependency> PackageDependencies { get; set; }
6364
public DbSet<Credential> Credentials { get; set; }
6465
public DbSet<Scope> Scopes { get; set; }
6566
public DbSet<UserSecurityPolicy> UserSecurityPolicies { get; set; }

src/NuGetGallery.Core/Entities/IEntitiesContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public interface IEntitiesContext : IReadOnlyEntitiesContext
1212
DbSet<Certificate> Certificates { get; set; }
1313
DbSet<PackageDeprecation> Deprecations { get; set; }
1414
DbSet<PackageRegistration> PackageRegistrations { get; set; }
15+
DbSet<PackageDependency> PackageDependencies { get; set; }
1516
DbSet<Credential> Credentials { get; set; }
1617
DbSet<Scope> Scopes { get; set; }
1718
DbSet<User> Users { get; set; }

src/NuGetGallery.Services/Configuration/FeatureFlagService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class FeatureFlagService : IFeatureFlagService
2020
private const string EmbeddedIconFlightName = GalleryPrefix + "EmbeddedIcons";
2121
private const string ForceFlatContainerIconsFeatureName = GalleryPrefix + "ForceFlatContainerIcons";
2222
private const string GitHubUsageFlightName = GalleryPrefix + "GitHubUsage";
23+
private const string PackageDependentsFlightName = GalleryPrefix + "PackageDependents";
2324
private const string ManageDeprecationFeatureName = GalleryPrefix + "ManageDeprecation";
2425
private const string ManageDeprecationForManyVersionsFeatureName = GalleryPrefix + "ManageDeprecationMany";
2526
private const string ManageDeprecationApiFeatureName = GalleryPrefix + "ManageDeprecationApi";
@@ -135,6 +136,11 @@ public bool IsGitHubUsageEnabled(User user)
135136
return _client.IsEnabled(GitHubUsageFlightName, user, defaultValue: false);
136137
}
137138

139+
public bool IsPackageDependentsEnabled(User user)
140+
{
141+
return _client.IsEnabled(PackageDependentsFlightName, user, defaultValue: false);
142+
}
143+
138144
public bool IsABTestingEnabled(User user)
139145
{
140146
return _client.IsEnabled(ABTestingFlightName, user, defaultValue: false);

src/NuGetGallery.Services/Configuration/IFeatureFlagService.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ public interface IFeatureFlagService
8080
/// <returns>Whether or not the Flight is enabled for the user</returns>
8181
bool IsGitHubUsageEnabled(User user);
8282

83+
/// <summary>
84+
/// Whether a user can see the "Package Dependents" section in a package's display page. Also, no
85+
/// data is gathered from the database
86+
/// </summary>
87+
/// <param name="user">The user to test for the Flight</param>
88+
/// <returns>Whether or not the Flight is enabled for the user</returns>
89+
bool IsPackageDependentsEnabled(User user);
90+
8391
/// <summary>
8492
/// Whether the OData controllers use the read-only replica.
8593
/// </summary>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace NuGetGallery
7+
{
8+
public class PackageDependent
9+
{
10+
public string Id { get; set; }
11+
public int DownloadCount { get; set; }
12+
public string Description { get; set; }
13+
14+
// TODO Add verify checkmark
15+
// https://github.com/NuGet/NuGetGallery/issues/4718
16+
}
17+
}
18+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
6+
namespace NuGetGallery
7+
{
8+
public class PackageDependents
9+
{
10+
public IReadOnlyCollection<PackageDependent> TopPackages { get; set; }
11+
public int TotalPackageCount { get; set; }
12+
}
13+
}

src/NuGetGallery.Services/NuGetGallery.Services.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@
146146
<Compile Include="Helpers\MailAddressConverter.cs" />
147147
<Compile Include="Helpers\UploadHelper.cs" />
148148
<Compile Include="Models\LuceneIndexLocation.cs" />
149+
<Compile Include="Models\PackageDependent.cs" />
150+
<Compile Include="Models\PackageDependents.cs" />
149151
<Compile Include="Models\ReportPackageReason.cs" />
150152
<Compile Include="Models\StorageType.cs" />
151153
<Compile Include="PackageManagement\ActionOnNewPackageContext.cs" />

src/NuGetGallery.Services/PackageManagement/IPackageService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ namespace NuGetGallery
1717
/// </summary>
1818
public interface IPackageService : ICorePackageService
1919
{
20+
/// <summary>
21+
/// Returns a package dependents object that includes a collection of the top packages that
22+
/// depend on the focus package and a total count of those dependents.
23+
/// </summary>
24+
/// <param name="id">The package ID.</param>
25+
PackageDependents GetPackageDependents(string id);
26+
2027
/// <summary>
2128
/// Returns all packages with an <see cref="Package.Id"/> of <paramref name="id"/>.
2229
/// Includes deprecation fields based on <paramref name="deprecationFields"/>.

src/NuGetGallery.Services/PackageManagement/PackageService.cs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Data.Common;
67
using System.Data.Entity;
78
using System.IO;
89
using System.Linq;
@@ -24,19 +25,22 @@ public class PackageService : CorePackageService, IPackageService
2425
private readonly IAuditingService _auditingService;
2526
private readonly ITelemetryService _telemetryService;
2627
private readonly ISecurityPolicyService _securityPolicyService;
28+
private readonly IEntitiesContext _entitiesContext;
2729

2830
public PackageService(
2931
IEntityRepository<PackageRegistration> packageRegistrationRepository,
3032
IEntityRepository<Package> packageRepository,
3133
IEntityRepository<Certificate> certificateRepository,
3234
IAuditingService auditingService,
3335
ITelemetryService telemetryService,
34-
ISecurityPolicyService securityPolicyService)
36+
ISecurityPolicyService securityPolicyService,
37+
IEntitiesContext entitiesContext)
3538
: base(packageRepository, packageRegistrationRepository, certificateRepository)
3639
{
3740
_auditingService = auditingService ?? throw new ArgumentNullException(nameof(auditingService));
3841
_telemetryService = telemetryService ?? throw new ArgumentNullException(nameof(telemetryService));
3942
_securityPolicyService = securityPolicyService ?? throw new ArgumentNullException(nameof(securityPolicyService));
43+
_entitiesContext = entitiesContext ?? throw new ArgumentNullException(nameof(entitiesContext));
4044
}
4145

4246
/// <summary>
@@ -136,12 +140,60 @@ public override PackageRegistration FindPackageRegistrationById(string packageId
136140
}
137141

138142
public virtual IReadOnlyCollection<Package> FindPackagesById(
139-
string id,
143+
string id,
140144
PackageDeprecationFieldsToInclude deprecationFields = PackageDeprecationFieldsToInclude.None)
141145
{
142146
return GetPackagesByIdQueryable(id, deprecationFields).ToList();
143147
}
144148

149+
public PackageDependents GetPackageDependents(string id)
150+
{
151+
if (string.IsNullOrWhiteSpace(id))
152+
{
153+
throw new ArgumentNullException(nameof(id));
154+
}
155+
156+
PackageDependents result = new PackageDependents();
157+
result.TopPackages = GetListOfDependents(id);
158+
result.TotalPackageCount = GetDependentCount(id);
159+
return result;
160+
}
161+
162+
private IReadOnlyCollection<PackageDependent> GetListOfDependents(string id)
163+
{
164+
var packageDependentsList = new List<PackageDependent>();
165+
var listPackages = (from pd in _entitiesContext.PackageDependencies
166+
join p in _entitiesContext.Packages on pd.PackageKey equals p.Key
167+
join pr in _entitiesContext.PackageRegistrations on p.PackageRegistrationKey equals pr.Key
168+
where p.IsLatestSemVer2 && pd.Id == id
169+
group 1 by new { pr.Id, pr.DownloadCount, p.Description } into ng
170+
orderby ng.Key.DownloadCount descending
171+
select new { ng.Key.Id, ng.Key.DownloadCount, ng.Key.Description }
172+
).Take(5).ToList();
173+
174+
foreach(var pd in listPackages)
175+
{
176+
var packageDependent = new PackageDependent();
177+
packageDependent.Description = pd.Description;
178+
packageDependent.DownloadCount = pd.DownloadCount;
179+
packageDependent.Id = pd.Id;
180+
packageDependentsList.Add(packageDependent);
181+
}
182+
183+
return packageDependentsList;
184+
}
185+
186+
private int GetDependentCount(string id)
187+
{
188+
var totalCount = (from pd in _entitiesContext.PackageDependencies
189+
join p in _entitiesContext.Packages on pd.PackageKey equals p.Key
190+
where pd.Id == id && p.IsLatestSemVer2
191+
group 1 by p.PackageRegistrationKey
192+
).Count();
193+
194+
return totalCount;
195+
}
196+
145197
public virtual IReadOnlyCollection<Package> FindPackagesById(
146198
string id,
147199
bool includePackageRegistration)

src/NuGetGallery/App_Data/Files/Content/flags.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
"SiteAdmins": true,
4747
"Accounts": [],
4848
"Domains": []
49+
},
50+
"NuGetGallery.PackageDependents": {
51+
"All": false,
52+
"SiteAdmins": true,
53+
"Accounts": [],
54+
"Domains": []
4955
}
5056
}
5157
}

0 commit comments

Comments
 (0)