From b65f586997d51c8c935564f0038cc73e0356ab55 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Thu, 11 Oct 2018 22:34:37 -0500 Subject: [PATCH] (GH-1397) Search each repo based on features Search through each repo based on features, instead of looking at only what all in aggregate have available. This allows searching for prereleases when available even if not every repo supports them. --- .../services/NugetService.cs | 76 ++++++++++++------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs index 0f1e6a8cc9..4649ea7de6 100644 --- a/src/chocolatey/infrastructure.app/services/NugetService.cs +++ b/src/chocolatey/infrastructure.app/services/NugetService.cs @@ -435,7 +435,6 @@ public virtual ConcurrentDictionary install_run(Chocolate uninstallSuccessAction: null, addUninstallHandler: true); - bool repositoryIsServiceBased = repository_is_service_based(packageManager.SourceRepository); var originalConfig = config; foreach (string packageName in packageNames.or_empty_list_if_null()) @@ -472,7 +471,7 @@ public virtual ConcurrentDictionary install_run(Chocolate continue; } - IPackage availablePackage = find_package(packageName, version, config, packageManager.SourceRepository, repositoryIsServiceBased); + IPackage availablePackage = find_package(packageName, version, config, packageManager.SourceRepository); if (availablePackage == null) { var logMessage = @"{0} not installed. The package was not found with the source(s) listed. @@ -610,8 +609,6 @@ public virtual ConcurrentDictionary upgrade_run(Chocolate uninstallSuccessAction: null, addUninstallHandler: false); - bool repositoryIsServiceBased = repository_is_service_based(packageManager.SourceRepository); - var configIgnoreDependencies = config.IgnoreDependencies; set_package_names_if_all_is_specified(config, () => { config.IgnoreDependencies = true; }); config.IgnoreDependencies = configIgnoreDependencies; @@ -685,7 +682,7 @@ public virtual ConcurrentDictionary upgrade_run(Chocolate config.Prerelease = true; } - IPackage availablePackage = find_package(packageName, version, config, packageManager.SourceRepository, repositoryIsServiceBased); + IPackage availablePackage = find_package(packageName, version, config, packageManager.SourceRepository); config.Prerelease = originalPrerelease; if (availablePackage == null) @@ -876,8 +873,6 @@ public ConcurrentDictionary get_outdated(ChocolateyConfig addUninstallHandler: false); var repository = packageManager.SourceRepository; - bool repositoryIsServiceBased = repository_is_service_based(repository); - var outdatedPackages = new ConcurrentDictionary(); set_package_names_if_all_is_specified(config, () => { config.IgnoreDependencies = true; }); @@ -912,7 +907,7 @@ public ConcurrentDictionary get_outdated(ChocolateyConfig config.Prerelease = true; } - var latestPackage = find_package(packageName, null, config, repository, repositoryIsServiceBased); + var latestPackage = find_package(packageName, null, config, repository); if (latestPackage == null) { @@ -940,12 +935,57 @@ public ConcurrentDictionary get_outdated(ChocolateyConfig return outdatedPackages; } - private IPackage find_package(string packageName, SemanticVersion version, ChocolateyConfiguration config, IPackageRepository repository, bool isRepositoryServiceBased) + private IPackage find_package(string packageName, SemanticVersion version, ChocolateyConfiguration config, IPackageRepository repository) { packageName = packageName.to_string().ToLower(CultureInfo.CurrentCulture); // find the package based on version if (version != null) return repository.FindPackage(packageName, version, config.Prerelease, allowUnlisted: false); + // we should always be using an aggregate repository + var aggregateRepository = repository as AggregateRepository; + if (aggregateRepository != null) + { + var packageResults = new List(); + + foreach (var packageRepository in aggregateRepository.Repositories.or_empty_list_if_null()) + { + this.Log().Debug("Using '" + packageRepository.Source + "'."); + this.Log().Debug("- Supports prereleases? '" + packageRepository.SupportsPrereleasePackages + "'."); + this.Log().Debug("- Is ServiceBased? '" + (packageRepository is IServiceBasedRepository) + "'."); + + // search based on lower case id - similar to PackageRepositoryExtensions.FindPackagesByIdCore() + IQueryable combinedResults = packageRepository.GetPackages().Where(x => x.Id.ToLower() == packageName); + + if (config.Prerelease && packageRepository.SupportsPrereleasePackages) + { + combinedResults = combinedResults.Where(p => p.IsAbsoluteLatestVersion); + } + else + { + combinedResults = combinedResults.Where(p => p.IsLatestVersion); + } + + if (!(packageRepository is IServiceBasedRepository)) + { + combinedResults = combinedResults + .Where(PackageExtensions.IsListed) + .Where(p => config.Prerelease || p.IsReleaseVersion()) + .distinct_last(PackageEqualityComparer.Id, PackageComparer.Version) + .AsQueryable(); + } + + var packageRepositoryResults = combinedResults.ToList(); + if (packageRepositoryResults.Count() != 0) + { + this.Log().Debug("Package '{0}' found on source '{1}'".format_with(packageName, packageRepository.Source)); + packageResults.AddRange(packageRepositoryResults); + } + } + + // get only one result, should be the latest - similar to TryFindLatestPackageById + return packageResults.OrderByDescending(x => x.Version).FirstOrDefault(); + } + // search based on lower case id - similar to PackageRepositoryExtensions.FindPackagesByIdCore() IQueryable results = repository.GetPackages().Where(x => x.Id.ToLower() == packageName); @@ -958,7 +998,7 @@ private IPackage find_package(string packageName, SemanticVersion version, Choco results = results.Where(p => p.IsLatestVersion); } - if (!isRepositoryServiceBased) + if (!(repository is IServiceBasedRepository)) { results = results .Where(PackageExtensions.IsListed) @@ -971,22 +1011,6 @@ private IPackage find_package(string packageName, SemanticVersion version, Choco return results.ToList().OrderByDescending(x => x.Version).FirstOrDefault(); } - private bool repository_is_service_based(IPackageRepository repository) - { - bool isRemote; - var aggregateRepo = repository as AggregateRepository; - if (aggregateRepo != null) - { - isRemote = aggregateRepo.Repositories.All(repo => repo is IServiceBasedRepository); - } - else - { - isRemote = repository is IServiceBasedRepository; - } - - return isRemote; - } - /// /// Sets the configuration for the package upgrade ///