Cmdlets/src/XpandPosh.Cmdlets/GetNugetPackageSearchMetadata/Get-NugetPackageSearchMetadata.cs
using System;
using System.Collections.Generic; using System.Linq; using System.Management.Automation; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using System.Threading; using NuGet.Common; using NuGet.Configuration; using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.Versioning; namespace XpandPosh.Cmdlets.GetNugetPackageSearchMetadata{ public interface IPackageSourceSearchMetadata{ string Source{ get; } IPackageSearchMetadata Metadata{ get; } } class PackageSourceSearchMetadata:IPackageSourceSearchMetadata{ public PackageSourceSearchMetadata(string source, IPackageSearchMetadata metadata){ Source = source; Metadata = metadata; } public string Source{ get; } public IPackageSearchMetadata Metadata{ get; } } [Cmdlet(VerbsCommon.Get, "NugetPackageSearchMetadata")] [OutputType(typeof(IPackageSourceSearchMetadata))] [CmdletBinding] public class GetNugetPackageSearchMetadata : Cmdlet{ [Parameter(Position = 0,ValueFromPipeline = true,Mandatory = true)] public string Name{ get; set; } [Parameter(Position = 1)] public string[] Sources{ get; set; } = {"https://nuget.devexpress.com/88luCgoeuPFTrDrTDcc6zKg22U2cVcTm3vdKCv88I7PHF9St6i/api"}; [Parameter] public SwitchParameter IncludePrerelease{ get; set; } =new SwitchParameter(false); [Parameter] public SwitchParameter IncludeUnlisted{ get; set; } = new SwitchParameter(false); [Parameter] public SwitchParameter AllVersions{ get; set; } = new SwitchParameter(false); [Parameter] public string[] Versions{ get; set; } class MetadataEqualityComparer:IEqualityComparer<IPackageSourceSearchMetadata>{ public bool Equals(IPackageSourceSearchMetadata x, IPackageSourceSearchMetadata y){ return x?.Metadata.Identity.Id == y?.Metadata.Identity.Id && GetNuGetVersion(x)?.Version == GetNuGetVersion(y)?.Version; } public int GetHashCode(IPackageSourceSearchMetadata obj){ return $"{obj.Metadata.Identity.Id}{GetNuGetVersion(obj).Version}".GetHashCode(); } } protected override void ProcessRecord(){ base.ProcessRecord(); var providers = new List<Lazy<INuGetResourceProvider>>(); providers.AddRange(Repository.Provider.GetCoreV3()); var metadatas =ListPackages(providers) .SelectMany(s => GetPackageSourceSearchMetadatas(s,providers)) .OnErrorResumeNext(Observable.Empty<IPackageSourceSearchMetadata>()) .ToEnumerable(); WriteObject(metadatas, true); } private IObservable<string> ListPackages(List<Lazy<INuGetResourceProvider>> providers){ if (Name != null){ return Observable.Return(Name); } return Sources.ToObservable().SelectMany(source => { var sourceRepository = new SourceRepository(new PackageSource(source), providers); return sourceRepository.GetResourceAsync<ListResource>().ToObservable() .Select(resource => resource.ListAsync(null,false,false,false,NullLogger.Instance, CancellationToken.None).ToObservable()) .Merge(); }) .SelectMany(async => { return Observable.Create<IPackageSearchMetadata>(observer =>{ var enumeratorAsync = async.GetEnumeratorAsync(); return enumeratorAsync.MoveNextAsync().ToObservable() .Do(b => { if (b){ observer.OnNext(enumeratorAsync.Current); } else{ observer.OnCompleted(); } }) .Subscribe(); }); }) .Select(metadata => metadata.Identity.Id); } private IPackageSourceSearchMetadata[] GetPackageSourceSearchMetadatas(string name, List<Lazy<INuGetResourceProvider>> providers){ var metadatas = Sources.SelectMany(source => { var sourceRepository = new SourceRepository(new PackageSource(source), providers); var packageMetadataResource = sourceRepository.GetResourceAsync<PackageMetadataResource>().Result; return packageMetadataResource.GetMetadataAsync(name, IncludePrerelease, IncludeUnlisted, NullLogger.Instance, CancellationToken.None).Result .Select(metadata => new PackageSourceSearchMetadata(source, metadata)); }) .Distinct(new MetadataEqualityComparer()) .OrderByDescending(metadata => GetNuGetVersion(metadata).Version) .ToArray(); if (!AllVersions && Versions==null){ return metadatas.Take(1).ToArray(); } if (Versions != null){ return metadatas.Where(metadata => { var nuGetVersion = GetNuGetVersion(metadata).ToString(); return Versions.Contains(nuGetVersion); }).ToArray(); } return metadatas; } private static NuGetVersion GetNuGetVersion(IPackageSourceSearchMetadata metadata){ if (metadata.Metadata is PackageSearchMetadata searchMetadata) return searchMetadata.Version; if (metadata.Metadata is LocalPackageSearchMetadata localPackageSearchMetadata) return localPackageSearchMetadata.Identity.Version; return ((PackageSearchMetadataV2Feed) metadata.Metadata).Version; } } } |