1
0
mirror of synced 2024-11-15 01:33:51 +00:00
PettingZoo/PettingZoo.Tapeti/NuGet/NuGetPackageManager.cs
Mark van Renswoude c75ea0cc62 Implemented DataAnnotation based validation for Tapeti messages
Fixed class name missing when selecting from Tapeti class
Added Filter to class selection dialog
Fixed or removed some minor todo's
2022-01-03 15:04:00 +01:00

200 lines
7.0 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using NuGet.Common;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using ILogger = Serilog.ILogger;
namespace PettingZoo.Tapeti.NuGet
{
public class NuGetPackageManager : INuGetPackageManager
{
private const string NuGetDefaultSource = @"https://api.nuget.org/v3/index.json";
private readonly ILogger logger;
private readonly SourceCacheContext cache;
private readonly List<Source> sources;
public IReadOnlyList<INuGetPackageSource> Sources => sources;
public NuGetPackageManager(ILogger logger)
{
this.logger = logger;
cache = new SourceCacheContext();
sources = new List<Source>
{
new(logger.ForContext("source", NuGetDefaultSource), cache, "nuget.org", NuGetDefaultSource)
};
}
public NuGetPackageManager WithSourcesFrom(string nuGetConfig)
{
if (!File.Exists(nuGetConfig))
return this;
var doc = new XmlDocument();
doc.Load(nuGetConfig);
var nodes = doc.SelectNodes(@"/configuration/packageSources/add");
if (nodes == null)
return this;
foreach (var entry in nodes.Cast<XmlNode>())
{
if (entry.Attributes == null)
continue;
var nameAttribute = entry.Attributes["key"];
var urlAttribute = entry.Attributes["value"];
if (string.IsNullOrEmpty(nameAttribute?.Value) || string.IsNullOrEmpty(urlAttribute?.Value))
continue;
sources.Add(new Source(logger.ForContext("source", urlAttribute.Value), cache, nameAttribute.Value, urlAttribute.Value));
}
return this;
}
private class Source : INuGetPackageSource
{
private readonly ILogger logger;
private readonly SourceCacheContext cache;
private readonly SourceRepository repository;
public string Name { get; }
public Source(ILogger logger, SourceCacheContext cache, string name, string url)
{
this.logger = logger;
this.cache = cache;
Name = name;
repository = Repository.Factory.GetCoreV3(url);
}
public async Task<IReadOnlyList<INuGetPackage>> Search(string searchTerm, bool includePrerelease, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(searchTerm))
return Array.Empty<INuGetPackage>();
try
{
var resource = await repository.GetResourceAsync<PackageSearchResource>(cancellationToken);
var filter = new SearchFilter(includePrerelease);
var result = (await resource.SearchAsync(searchTerm, filter, 0, 20, new NullLogger(),
cancellationToken))
.Select(p => new Package(logger, cache, repository, p))
.ToArray();
return result;
}
catch (Exception e)
{
logger.Error(e, "NuGet Search failed for term '{searchTerm}' (includePrerelease {includePrerelease})", searchTerm, includePrerelease);
throw;
}
}
}
protected class Package : INuGetPackage
{
private readonly ILogger logger;
private readonly SourceCacheContext cache;
private readonly SourceRepository repository;
private readonly IPackageSearchMetadata packageSearchMetadata;
public string Title => packageSearchMetadata.Title;
public string Description => packageSearchMetadata.Description;
public string Authors => packageSearchMetadata.Authors;
public string Version => packageSearchMetadata.Identity.Version.ToString();
private IReadOnlyList<INuGetPackageVersion>? versions;
public Package(ILogger logger, SourceCacheContext cache, SourceRepository repository, IPackageSearchMetadata packageSearchMetadata)
{
this.logger = logger;
this.cache = cache;
this.repository = repository;
this.packageSearchMetadata = packageSearchMetadata;
}
public async Task<IReadOnlyList<INuGetPackageVersion>> GetVersions(CancellationToken cancellationToken)
{
try
{
return versions ??= (await packageSearchMetadata.GetVersionsAsync())
.Select(v => new PackageVersion(cache, repository, packageSearchMetadata, v.Version))
.ToArray();
}
catch (Exception e)
{
logger.Error(e, "NuGet GetVersions failed for packge Id '{packageId}')", packageSearchMetadata.Identity.Id);
throw;
}
}
}
protected class PackageVersion : INuGetPackageVersion, IComparable<PackageVersion>
{
private readonly SourceCacheContext cache;
private readonly SourceRepository repository;
private readonly IPackageSearchMetadata packageSearchMetadata;
protected readonly NuGetVersion NuGetVersion;
public PackageVersion(SourceCacheContext cache, SourceRepository repository, IPackageSearchMetadata packageSearchMetadata, NuGetVersion nuGetVersion)
{
this.cache = cache;
this.repository = repository;
this.packageSearchMetadata = packageSearchMetadata;
NuGetVersion = nuGetVersion;
}
public string Version => NuGetVersion.ToString();
public async Task Download(Stream destination, CancellationToken cancellationToken)
{
var resource = await repository.GetResourceAsync<FindPackageByIdResource>(cancellationToken);
await resource.CopyNupkgToStreamAsync(packageSearchMetadata.Identity.Id, NuGetVersion, destination, cache, new NullLogger(), cancellationToken);
}
public int CompareTo(INuGetPackageVersion? other)
{
if (ReferenceEquals(this, other)) return 0;
if (other == null) return 1;
return other is PackageVersion packageVersion ? CompareTo(packageVersion) : string.Compare(Version, other.Version, StringComparison.Ordinal);
}
public int CompareTo(PackageVersion? other)
{
if (ReferenceEquals(this, other)) return 0;
return other == null ? 1 : NuGetVersion.CompareTo(other.NuGetVersion);
}
}
}
}