nuget-extensions/nuget-commands/src.5.8/ListCommandBase.cs (120 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.TeamCity.NuGet.ExtendedCommands.Data;
using NuGet;
using NuGet.Configuration;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using NullLogger = NuGet.Common.NullLogger;
using NullSettings = NuGet.Configuration.NullSettings;
using PackageSource = NuGet.Configuration.PackageSource;
using PackageSourceProvider = NuGet.Configuration.PackageSourceProvider;
using SemanticVersion = NuGet.SemanticVersion;
namespace JetBrains.TeamCity.NuGet.ExtendedCommands
{
public abstract class ListCommandBase : CommandBase
{
protected ListCommandBase()
{
ResourceProviders = new List<Lazy<INuGetResourceProvider>>(Repository.Provider.GetCoreV3());
}
[Import]
public IPackageRepositoryFactory RepositoryFactoryTC { get; set; }
protected IEnumerable<Lazy<INuGetResourceProvider>> ResourceProviders { get; }
/// <exception cref="InvalidFeedUrlException">may be thrown on error</exception>
protected async Task<IEnumerable<SemanticVersion>> GetAllPackagesAsync(INuGetSource feed,
PackageFetchOption fetchOption,
string packageId)
{
await System.Console.Out.WriteLineAsync($"Checking package {packageId} on source: {feed}");
ValidateSourceUrl(feed);
var sourceRepo = CreateSourceRepository(feed);
var (hasV3Service, v3Service) = await new RemoteV3FindPackageByIdResourceProvider()
.TryCreate(sourceRepo, CancellationToken.None)
.ConfigureAwait(false);
if (hasV3Service && v3Service is RemoteV3FindPackageByIdResource remoteV3FindPackageByIdResource)
{
await System.Console.Out.WriteLineAsync($"Using V3 protocol for source: {feed}");
return await GetPackageVersionsAsync(remoteV3FindPackageByIdResource, packageId, fetchOption);
}
var (hasV2Service, v2Service) = await new RemoteV2FindPackageByIdResourceProvider()
.TryCreate(sourceRepo, CancellationToken.None)
.ConfigureAwait(false); ;
if (hasV2Service && v2Service is RemoteV2FindPackageByIdResource remoteV2FindPackageByIdResource)
{
await System.Console.Out.WriteLineAsync($"Using V2 protocol for source: {feed}");
return await GetPackageVersionsAsync(remoteV2FindPackageByIdResource, packageId, fetchOption);
}
var param = Expression.Parameter(typeof(IPackage));
var filter = QueryBuilder.GenerateQuery(fetchOption, new [] { packageId }, param);
var repo = RepositoryFactoryTC.CreateRepository(feed.Source);
return repo
.GetPackages()
.Where(Expression.Lambda<Func<IPackage, bool>>(filter, param))
.ToList() // Executing NuGet command
.Select(x => x.Version);
}
private SourceRepository CreateSourceRepository(INuGetSource feed)
{
var sourceRepositoryProvider = new SourceRepositoryProvider(new PackageSourceProvider(NullSettings.Instance), ResourceProviders);
var sourceRepo = sourceRepositoryProvider.CreateRepository(
new PackageSource(feed.Source, feed.Source)
{
Credentials = feed.HasCredentials
? PackageSourceCredential.FromUserInput(feed.Source,
feed.Username, feed.Password, false, "basic")
: default
});
return sourceRepo;
}
private static async Task<IEnumerable<SemanticVersion>> GetPackageVersionsAsync(FindPackageByIdResource findPackageByIdResource,
string packageId,
PackageFetchOption fetchOption)
{
using (var context = new SourceCacheContext() {NoCache = true})
{
var packageVersions = await findPackageByIdResource.GetAllVersionsAsync(
packageId,
context,
NullLogger.Instance,
CancellationToken.None)
.ConfigureAwait(false);
IEnumerable<NuGetVersion> result = packageVersions.OrderByDescending(x => x);
switch (fetchOption)
{
case PackageFetchOption.IncludeLatest:
result = result.Where(x => !x.IsPrerelease).Take(1);
break;
case PackageFetchOption.IncludeLatestAndPrerelease:
result = result.Take(1);
break;
}
return result.Select(x => SemanticVersion.Parse(x.ToFullString()));
}
}
private static void ValidateSourceUrl(INuGetSource feed)
{
string source = feed.Source;
Uri uri;
try
{
uri = new Uri(source);
}
catch (Exception e)
{
throw new InvalidFeedUrlException(source, e.Message);
}
if (uri.IsFile && !Directory.Exists(uri.LocalPath))
{
throw new InvalidFeedUrlException(source, "Local path does not exist: " + uri.LocalPath);
}
}
}
}