/// <summary>
        /// Deletes a version of a package from an Azure DevOps feed
        /// </summary>
        /// <param name="feed">Feed to delete the package from</param>
        /// <param name="packageName">package to delete</param>
        /// <param name="versionsToDelete">Collection of versions to delete</param>
        /// <returns></returns>
        private async Task DeletePackageVersionsFromFeedAsync(AzureDevOpsFeed feed, string packageName, HashSet <string> versionsToDelete)
        {
            var azdoClient = AzureDevOpsClients[feed.Account];

            foreach (string version in versionsToDelete)
            {
                try
                {
                    Logger.LogInformation($"Deleting package {packageName}.{version} from feed {feed.Name}");

                    await azdoClient.DeleteNuGetPackageVersionFromFeedAsync(feed.Account,
                                                                            feed.Project?.Name,
                                                                            feed.Name,
                                                                            packageName,
                                                                            version);
                }
                catch (HttpRequestException e)
                {
                    Logger.LogError(e, $"There was an error attempting to delete package {packageName}.{version} from the {feed.Name} feed. Skipping...");
                }
            }
        }
        private Dictionary <string, AzureDevOpsFeed> SetupFeeds(string account)
        {
            AzureDevOpsProject someProject = new AzureDevOpsProject("0", "someProject");
            var allFeeds = new Dictionary <string, AzureDevOpsFeed>();

            // This is the reference release feed.
            var releaseFeed = new AzureDevOpsFeed(account, "0", ReleaseFeedName, someProject)
            {
                Packages = new List <AzureDevOpsPackage>()
                {
                    new AzureDevOpsPackage("releasedPackage1", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false),
                            new AzureDevOpsPackageVersion("2.0", isDeleted: true),
                        }
                    },
                    new AzureDevOpsPackage("releasedPackage2", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false),
                            new AzureDevOpsPackageVersion("2.0", isDeleted: false),
                        }
                    }
                }
            };

            allFeeds.Add(releaseFeed.Name, releaseFeed);

            var managedFeedWithUnreleasedPackages = new AzureDevOpsFeed(account, "1", FeedWithUnreleasedPackagesName, null)
            {
                Packages = new List <AzureDevOpsPackage>()
                {
                    new AzureDevOpsPackage("unreleasedPackage1", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false)
                        }
                    },
                    new AzureDevOpsPackage("releasedPackage1", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false),
                        }
                    }
                }
            };

            allFeeds.Add(managedFeedWithUnreleasedPackages.Name, managedFeedWithUnreleasedPackages);

            var managedFeedWithEveryPackageReleased = new AzureDevOpsFeed(account, "2", FeedWithAllPackagesReleasedName, someProject)
            {
                Packages = new List <AzureDevOpsPackage>()
                {
                    new AzureDevOpsPackage("Newtonsoft.Json", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("12.0.2", isDeleted: false)
                        }
                    },
                    new AzureDevOpsPackage("releasedPackage1", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false)
                        }
                    },
                    new AzureDevOpsPackage("releasedPackage2", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false),
                            new AzureDevOpsPackageVersion("2.0", false)
                        }
                    }
                }
            };

            allFeeds.Add(managedFeedWithEveryPackageReleased.Name, managedFeedWithEveryPackageReleased);

            // add a feed with all released packages, but that doesn't match the name pattern. It shouldn't be touched by the cleaner.
            var nonManagedFeedWithEveryPackageReleased = new AzureDevOpsFeed(account, "3", UnmanagedFeedName, someProject)
            {
                Packages = new List <AzureDevOpsPackage>()
                {
                    new AzureDevOpsPackage("Newtonsoft.Json", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("12.0.2", isDeleted: false)
                        }
                    },
                    new AzureDevOpsPackage("releasedPackage1", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false)
                        }
                    },
                    new AzureDevOpsPackage("releasedPackage2", "nuget")
                    {
                        Versions = new AzureDevOpsPackageVersion[]
                        {
                            new AzureDevOpsPackageVersion("1.0", isDeleted: false),
                            new AzureDevOpsPackageVersion("2.0", isDeleted: false)
                        }
                    }
                }
            };

            allFeeds.Add(nonManagedFeedWithEveryPackageReleased.Name, nonManagedFeedWithEveryPackageReleased);

            return(allFeeds);
        }
 /// <summary>
 /// Checks whether a feed is empty
 /// (all the packages in the feed have had their versions deleted)
 /// </summary>
 /// <param name="feed"></param>
 /// <returns>true if the feed is empty, false otherwise</returns>
 private static bool IsFeedEmpty(AzureDevOpsFeed feed)
 {
     return(feed.Packages.Count == 0 || feed.Packages.All(p => p.Versions.All(v => v.IsDeleted)));
 }
 /// <summary>
 /// Populates the packages and versions for a given feed
 /// </summary>
 /// <param name="feed">Feed to populate</param>
 /// <returns></returns>
 private async Task PopulatePackagesForFeedAsync(AzureDevOpsFeed feed)
 {
     feed.Packages = await AzureDevOpsClients[feed.Account].GetPackagesForFeedAsync(feed.Account, feed.Project?.Name, feed.Name);
 }
        /// <summary>
        /// Updates the location for assets in the Database when
        /// a version of an asset is found in the release feeds or in NuGet.org
        /// </summary>
        /// <param name="feed">Feed to examine</param>
        /// <param name="package">Package to search for</param>
        /// <param name="dotnetFeedsPackageMapping">Mapping of packages and their versions in the release feeds</param>
        /// <returns>Collection of versions that were updated for the package</returns>
        private async Task <HashSet <string> > UpdateReleasedVersionsForPackageAsync(
            AzureDevOpsFeed feed,
            AzureDevOpsPackage package,
            Dictionary <string, Dictionary <string, HashSet <string> > > dotnetFeedsPackageMapping)
        {
            var releasedVersions = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var version in package.Versions)
            {
                var matchingAssets = Context.Assets
                                     .Include(a => a.Locations)
                                     .Where(a => a.Name == package.Name &&
                                            a.Version == version.Version).AsEnumerable();

                var matchingAsset = matchingAssets.FirstOrDefault(
                    a => a.Locations.Any(l => l.Location.Contains(feed.Name)));

                if (matchingAsset == null)
                {
                    Logger.LogError($"Unable to find asset {package.Name}.{version.Version} in feed {feed.Name} in BAR. " +
                                    $"Unable to determine if it was released or update its locations.");
                    continue;
                }
                else
                {
                    if (matchingAsset.Locations.Any(l => l.Location == FeedConstants.NuGetOrgLocation ||
                                                    dotnetFeedsPackageMapping.Any(f => l.Location == f.Key)))
                    {
                        Logger.LogInformation($"Package {package.Name}.{version.Version} is already present in a public location.");
                        releasedVersions.Add(version.Version);
                    }
                    else
                    {
                        List <string> feedsWherePackageIsAvailable = GetReleaseFeedsWherePackageIsAvailable(package.Name,
                                                                                                            version.Version,
                                                                                                            dotnetFeedsPackageMapping);

                        try
                        {
                            if (await IsPackageAvailableInNugetOrgAsync(package.Name, version.Version))
                            {
                                feedsWherePackageIsAvailable.Add(FeedConstants.NuGetOrgLocation);
                            }
                        }
                        catch (HttpRequestException e)
                        {
                            Logger.LogInformation(e, $"Failed to determine if package {package.Name}.{version.Version} is present in NuGet.org");
                        }


                        if (feedsWherePackageIsAvailable.Count > 0)
                        {
                            releasedVersions.Add(version.Version);
                            foreach (string feedToAdd in feedsWherePackageIsAvailable)
                            {
                                Logger.LogInformation($"Found package {package.Name}.{version.Version} in " +
                                                      $"{feedToAdd}, adding location to asset.");

                                matchingAsset.Locations.Add(new AssetLocation()
                                {
                                    Location = feedToAdd,
                                    Type     = LocationType.NugetFeed
                                });
                                await Context.SaveChangesAsync();
                            }
                        }
                        else
                        {
                            Logger.LogInformation($"Unable to find {package.Name}.{version} in any of the release feeds");
                        }
                    }
                }
            }
            return(releasedVersions);
        }