Cmdlets/src/XpandPosh.Cmdlets/GetNugetPackage/Get-NugetPackage.cs
using System;
using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Management.Automation; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using System.Threading; using System.Threading.Tasks; using ImpromptuInterface; using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; using NuGet.Packaging; using NuGet.Protocol; using NuGet.Protocol.Core.Types; using XpandPosh.Cmdlets.GetNugetPackageSearchMetadata; using XpandPosh.CmdLets; namespace XpandPosh.Cmdlets.GetNugetPackage{ [Cmdlet(VerbsCommon.Get, "NugetPackage")] [OutputType(typeof(INugetPackageAssembly))] [CmdletBinding] public class GetNugetPackage : XpandCmdlet{ [Parameter(ValueFromPipeline = true)] public string Name{ get; set; } [Parameter(Mandatory = true, Position = 2)] public string[] Sources{ get; set; } [Parameter(Mandatory =true, Position = 1)] public string OutputFolder{ get; set; } [Parameter] public SwitchParameter AllVersions{ get; set; } [Parameter] public string[] Versions{ get; set; } [Parameter] public SwitchParameter AllFiles{ get; set; } protected override Task ProcessRecordAsync(){ return GetDownloadResults() .SelectMany(NugetPackageAssemblies) .DefaultIfEmpty() .Catch(this,Name) .WriteObject(this) .ToTask(); } private IEnumerable<INugetPackageAssembly> NugetPackageAssemblies(DownloadResourceResult result){ var resultPackageReader = (PackageFolderReader) result.PackageReader; var directoryInfo = new DirectoryInfo($"{Path.GetDirectoryName(resultPackageReader.GetNuspecFile())}"); return resultPackageReader.GetLibItems().SelectMany(group => group.Items .Where(s => AllFiles || Path.GetExtension(s) == ".dll") .Select(s => new{ Package = directoryInfo.Parent?.Name, Version = directoryInfo.Name, DotNetFramework = group.TargetFramework.GetDotNetFrameworkName(DefaultFrameworkNameProvider.Instance), File = $@"{s.Replace(@"/", @"\")}" }.ActLike<INugetPackageAssembly>())); } private IObservable<DownloadResourceResult> GetDownloadResults(){ var sourceSearchMetadatas = PackageSourceSearchMetadatas(); var packageSourceSearchMetadatas = sourceSearchMetadatas.ToObservable().Replay().RefCount(); var downloadContext = new PackageDownloadContext(new SourceCacheContext()); var providers = new List<Lazy<INuGetResourceProvider>>(); providers.AddRange(Repository.Provider.GetCoreV3()); var downloads = packageSourceSearchMetadatas.Select(metadata => metadata.Source).Distinct() .Select(s => new SourceRepository(new PackageSource(s), providers)) .SelectMany(repository => repository.GetResourceAsync<DownloadResource>().ToObservable().Select(resource => (resource,repository))) .Replay().RefCount(); return packageSourceSearchMetadatas .SelectMany(metadata => { return downloads.FirstAsync(tuple => tuple.Item2.PackageSource.Source == metadata.Source) .SelectMany(tuple => tuple.Item1.GetDownloadResourceResultAsync(metadata.Metadata.Identity, downloadContext, OutputFolder, NullLogger.Instance, CancellationToken.None)); }) .Where(result => result.Status == DownloadResourceResultStatus.Available) .Catch(this, Name); } private Collection<IPackageSourceSearchMetadata> PackageSourceSearchMetadatas(){ string allVersions = $"-{nameof(AllVersions)} {AllVersions}"; if (!AllVersions){ allVersions = null; } string sources = $"-{nameof(Sources)} @({string.Join(",", Sources.Select(s => $"'{s}'"))})"; string versions = null; if (Versions != null){ versions = $"-{nameof(Versions)} @({string.Join(",", Versions.Select(s => $"'{s}'"))})"; } string name=$"-{nameof(Name)} {Name}"; if (Name == null){ name = null; } var cmdletName = CmdletExtensions.GetCmdletName<GetNugetPackageSearchMetadata.GetNugetPackageSearchMetadata>(); var script = $"{cmdletName} {sources} {allVersions} {name} {versions}"; var sourceSearchMetadatas = this.Invoke<IPackageSourceSearchMetadata>(script); return sourceSearchMetadatas; } } } |