| File: NuGetUtility.cs | Web Access |
| Project: src\arcade\src\Microsoft.DotNet.Build.Tasks.Packaging\src\Microsoft.DotNet.Build.Tasks.Packaging.csproj (Microsoft.DotNet.Build.Tasks.Packaging) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Newtonsoft.Json; using NuGet.Common; using NuGet.Configuration; using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.RuntimeModel; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace Microsoft.DotNet.Build.Tasks.Packaging { public static class NuGetUtility { internal static IEnumerable<Version> GetAllVersionsForPackageId(string packageId, bool includePrerelease, bool includeUnlisted, Log log, CancellationToken cancellationToken) { List<Version> result = new List<Version>(); ISettings settings = Settings.LoadDefaultSettings(Directory.GetCurrentDirectory()); IEnumerable<PackageSource> enabledSources = GetEnabledSources(settings); var logger = new NuGetLogger(log); Parallel.ForEach(enabledSources, (packageSource) => { using (var sourceCacheContext = new SourceCacheContext()) { bool loadedData = false; int retriesRemaining = 2; IEnumerable<IPackageSearchMetadata> searchMetadata = null; while (!loadedData) { try { var sourceRepository = new SourceRepository(packageSource, Repository.Provider.GetCoreV3()); var packageMetadataResource = sourceRepository.GetResourceAsync<PackageMetadataResource>().GetAwaiter().GetResult(); #pragma warning disable CA2025 // we force GetMetadataAsync to be synchronous so sourceCacheContext can't be disposed early searchMetadata = packageMetadataResource.GetMetadataAsync(packageId, includePrerelease, includeUnlisted, sourceCacheContext, logger, cancellationToken).GetAwaiter().GetResult(); #pragma warning restore loadedData = true; } catch (Exception e) { retriesRemaining--; if (retriesRemaining <= 0) { logger.Log(LogLevel.Error, "Encountered Connection Issue: " + e.ToString() + ", retries exhausted"); throw; } logger.Log(LogLevel.Information, "Encountered Connection Issue: " + e.ToString() + ", retrying..."); // returns to start of while loop to retry after a delay Thread.Sleep(5000); } } foreach (IPackageSearchMetadata packageMetadata in searchMetadata) { lock (result) { Version threePartVersion = VersionUtility.As3PartVersion(packageMetadata.Identity.Version.Version); if (!result.Contains(threePartVersion)) result.Add(threePartVersion); } } } }); // Given we are looking in different sources, we reorder all versions. return result.OrderBy(v => v); } private static IEnumerable<PackageSource> GetEnabledSources(ISettings settings) { if (settings == null) { throw new ArgumentNullException(nameof(settings)); } var provider = new PackageSourceProvider(settings); return provider.LoadPackageSources().Where(e => e.IsEnabled == true).ToList(); } public static Version GetLatestPatchStableVersionForRelease(this IEnumerable<Version> versions, int eraMajorVersion, int eraMinorVersion) { return versions.Where(v => VersionUtility.As2PartVersion(v) == new Version(eraMajorVersion, eraMinorVersion)) .OrderByDescending(v => v) .FirstOrDefault(); } public static void WriteRuntimeGraph(string filePath, RuntimeGraph runtimeGraph) { using (var fileStream = new FileStream(filePath, FileMode.Create)) using (var textWriter = new StreamWriter(fileStream)) using (var jsonWriter = new JsonTextWriter(textWriter)) using (var writer = new JsonObjectWriter(jsonWriter)) { jsonWriter.Formatting = Formatting.Indented; // workaround https://github.com/NuGet/Home/issues/9532 writer.WriteObjectStart(); JsonRuntimeFormat.WriteRuntimeGraph(writer, runtimeGraph); writer.WriteObjectEnd(); } } internal class NuGetLogger : ILogger { private readonly Log _log; public NuGetLogger(Log log) { _log = log; } public void Log(LogLevel level, string data) => _log.LogMessage($"{level.ToString()} - {data}"); public void Log(ILogMessage message) => _log.LogMessage(message.ToString()); public Task LogAsync(LogLevel level, string data) => Task.Run(() => Log(level, data)); public Task LogAsync(ILogMessage message) => Task.Run(() => Log(message)); public void LogDebug(string data) => _log.LogMessage(data); public void LogError(string data) => _log.LogError(data); public void LogInformation(string data) => _log.LogMessage(data); public void LogInformationSummary(string data) => _log.LogMessage(data); public void LogMinimal(string data) => _log.LogMessage(data); public void LogVerbose(string data) => _log.LogMessage(data); public void LogWarning(string data) => _log.LogWarning(data); } } }