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();
}
}
}