using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using NugetForUnity.Models; using UnityEngine; namespace NugetForUnity.PackageSource { /// /// A package source that combines the results from multiple other package sources. /// internal sealed class NugetPackageSourceCombined : INugetPackageSource { [NotNull] [ItemNotNull] private readonly List packageSources; /// /// Initializes a new instance of the class. /// /// The package source's to combine the results from. public NugetPackageSourceCombined([NotNull] [ItemNotNull] List packageSources) { this.packageSources = packageSources ?? throw new ArgumentNullException(nameof(packageSources)); } /// public string Name { get => "All"; set { // this is a fixed value } } /// public bool IsEnabled { get; set; } /// public string SavedPath { get => "(Aggregate source)"; set { // this is a fixed value } } /// public string SavedProtocolVersion { get => null; set { // multiple sources can't have protocol version } } /// public bool SavedPasswordIsEncrypted { get => false; set { // multiple sources can't have credentials } } /// public string SavedPassword { get => null; set { // multiple sources can't have credentials } } /// public string UserName { get => null; set { // multiple sources can't have credentials } } /// public bool HasPassword { get => false; set { // multiple sources can't have passwords } } /// public List FindPackagesById(INugetPackageIdentifier package) { var activeSourcesCount = packageSources.Count(source => source.IsEnabled); if (activeSourcesCount == 0) { Debug.LogWarning("There are no active package sources. Check your nuget.config."); return new List(); } if (activeSourcesCount == 1) { return packageSources.First(source => source.IsEnabled).FindPackagesById(package); } return packageSources.Where(source => source.IsEnabled).SelectMany(source => source.FindPackagesById(package)).Distinct().ToList(); } /// public INugetPackage GetSpecificPackage(INugetPackageIdentifier package) { var activeSourcesCount = packageSources.Count(source => source.IsEnabled); if (activeSourcesCount == 0) { Debug.LogWarning("There are no active package sources. Check your nuget.config."); return null; } if (activeSourcesCount == 1) { return packageSources.First(source => source.IsEnabled).GetSpecificPackage(package); } // Loop through all active sources and stop once the package is found INugetPackage bestMatch = null; foreach (var source in packageSources.Where(s => s.IsEnabled)) { var foundPackage = source.GetSpecificPackage(package); if (foundPackage == null) { continue; } if (foundPackage.Version == package.Version) { NugetLogger.LogVerbose("{0} {1} was found in {2}", foundPackage.Id, foundPackage.Version, source.Name); return foundPackage; } NugetLogger.LogVerbose( "{0} {1} was found in {2}, but wanted {3}", foundPackage.Id, foundPackage.Version, source.Name, package.Version); if (bestMatch == null) { // if another package hasn't been found yet, use the current found one bestMatch = foundPackage; } // another package has been found previously, but neither match identically else if (foundPackage.CompareTo(bestMatch) > 0) { // use the new package if it's closer to the desired version bestMatch = foundPackage; } } return bestMatch; } /// public List GetUpdates( IEnumerable packages, bool includePrerelease = false, string targetFrameworks = "", string versionConstraints = "") { var activeSourcesCount = packageSources.Count(source => source.IsEnabled); if (activeSourcesCount == 0) { Debug.LogWarning("There are no active package sources. Check your nuget.config."); return new List(); } if (activeSourcesCount == 1) { return packageSources.First(source => source.IsEnabled).GetUpdates(packages, includePrerelease, targetFrameworks, versionConstraints); } return packageSources.Where(source => source.IsEnabled) .SelectMany(source => source.GetUpdates(packages, includePrerelease, targetFrameworks, versionConstraints)) .Distinct() .ToList(); } /// public Task> SearchAsync( string searchTerm = "", bool includePrerelease = false, int numberToGet = 15, int numberToSkip = 0, CancellationToken cancellationToken = default) { var activeSourcesCount = packageSources.Count(source => source.IsEnabled); if (activeSourcesCount == 0) { Debug.LogWarning("There are no active package sources. Check your nuget.config."); return Task.FromResult(new List()); } if (activeSourcesCount == 1) { return packageSources.First(source => source.IsEnabled) .SearchAsync(searchTerm, includePrerelease, numberToGet, numberToSkip, cancellationToken); } return SearchMultipleAsync(searchTerm, includePrerelease, numberToGet, numberToSkip, cancellationToken); } /// public void DownloadNupkgToFile(INugetPackageIdentifier package, string outputFilePath, string downloadUrlHint) { throw new NotImplementedException( "This shouldn't happen / is currently not implemented as each package has its own 'DownloadNupkgToFile' method."); } /// public void Dispose() { // packageSources are disposed by them self. } [NotNull] [ItemNotNull] private async Task> SearchMultipleAsync( string searchTerm = "", bool includePrerelease = false, int numberToGet = 15, int numberToSkip = 0, CancellationToken cancellationToken = default) { var results = await Task.WhenAll( packageSources.Where(source => source.IsEnabled) .Select(source => source.SearchAsync(searchTerm, includePrerelease, numberToGet, numberToSkip, cancellationToken))); return results.SelectMany(result => result).Distinct().ToList(); } } }