public HashSet <int> FindDependencyPackages(HashSet <int> roots) { var result = new HashSet <int>(); var next = new HashSet <int>(roots); var seen = new HashSet <int>(roots); do { var dependencies = _galleryContext.PackageRegistrations .Join( _galleryContext.Set <PackageDependency>(), registration => registration.Id, dependency => dependency.Id, (registration, dependency) => new { DependencyRegistrationKey = registration.Key, ParentRegistrationKey = dependency.Package.PackageRegistrationKey }) .Where(j => next.Contains(j.ParentRegistrationKey)) .Select(j => j.DependencyRegistrationKey) .Distinct() .ToList(); next.Clear(); next.UnionWith(dependencies); next.ExceptWith(seen); result.UnionWith(next); seen.UnionWith(next); }while (next.Count() > 0); return(result); }
private async Task <bool> IsDeleted(PackageRevalidation revalidation) { var packageStatus = await _galleryContext.Set <Package>() .Where(p => p.PackageRegistration.Id == revalidation.PackageId) .Where(p => p.NormalizedVersion == revalidation.PackageNormalizedVersion) .Select(p => (PackageStatus?)p.PackageStatusKey) .FirstOrDefaultAsync(); return(packageStatus == null || packageStatus == PackageStatus.Deleted); }
public Repository(IGalleryContext dbContext) { MainDbContext = dbContext; EntityDbSet = dbContext.Set <TEntity>(); }
private async Task <IReadOnlyList <PackageRevalidation> > FilterCompletedRevalidationsAsync(IReadOnlyList <PackageRevalidation> revalidations) { if (!revalidations.Any()) { return(revalidations); } var completed = new List <PackageRevalidation>(); var uncompleted = revalidations.ToDictionary( r => $"{r.PackageId}/{r.PackageNormalizedVersion}", r => r); // Packages that already have a repository signature do not need to be revalidated. _logger.LogInformation("Finding revalidations that can be skipped because their packages are already repository signed..."); var hasRepositorySignatures = await _validationContext.PackageSigningStates .Select(s => new { IdAndVersion = s.PackageId + "/" + s.PackageNormalizedVersion, s.PackageSignatures }) .Where(s => uncompleted.Keys.Contains(s.IdAndVersion)) .Where(s => s.PackageSignatures.Any(sig => sig.Type == PackageSignatureType.Repository)) .Select(s => s.IdAndVersion) .ToListAsync(); _logger.LogInformation( "Found {RevalidationCount} revalidations that can be skipped because their packages are already repository signed", hasRepositorySignatures.Count); foreach (var idAndVersion in hasRepositorySignatures) { completed.Add(uncompleted[idAndVersion]); uncompleted.Remove(idAndVersion); } // Packages that are no longer available should not be revalidated. _logger.LogInformation("Finding revalidations' package statuses..."); var packageStatuses = await _galleryContext.Set <Package>() .Select(p => new { Identity = p.PackageRegistration.Id + "/" + p.NormalizedVersion, p.PackageStatusKey }) .Where(p => uncompleted.Keys.Contains(p.Identity)) .ToDictionaryAsync( p => p.Identity, p => p.PackageStatusKey); _logger.LogInformation("Found {PackageStatusCount} revalidations' package statuses", packageStatuses.Count); foreach (var key in uncompleted.Keys.ToList()) { // Packages that are hard deleted won't have a status. if (!packageStatuses.TryGetValue(key, out var status) || status == PackageStatus.Deleted) { completed.Add(uncompleted[key]); uncompleted.Remove(key); continue; } } _logger.LogInformation( "Found {CompletedRevalidations} revalidations that can be skipped. There are {UncompletedRevalidations} " + "revalidations remaining in this batch", completed.Count, uncompleted.Count); // Update revalidations that were determined to be completed and return the remaining revalidations. if (completed.Any()) { await MarkRevalidationsAsCompletedAsync(completed); } return(uncompleted.Values.ToList()); }