diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs index e66fbdc2c5a..eaed372b225 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; @@ -12,6 +13,7 @@ using Microsoft.CodeAnalysis; using Microsoft.TypeSpec.Generator.Input; using NuGet.Configuration; +using NuGet.Versioning; namespace Microsoft.TypeSpec.Generator.Utilities { @@ -238,10 +240,30 @@ private static async Task ResolveResultAsync(InputExternalType { try { - var resolvedVersion = !string.IsNullOrEmpty(external.MinVersion) - ? external.MinVersion! - : await NugetPackageResolver.ResolveLatestPackageVersion(external.Package!, nugetSettings); - + string? resolvedVersion; + // Search for the compatible version. + if (!string.IsNullOrEmpty(external.MinVersion)) + { + // If min version was provided, we + // 1. Search if it is in our repositories; + // 2. Get the latest one if it is not. + // 3. If our version is a pre release, include pre released versions in our search. + NuGetVersion minVersion = new(external.MinVersion); + IList versions = await NugetPackageResolver.GetAllVersions(external.Package!, nugetSettings, allowPrerelease: minVersion.IsPrerelease); + if (versions.Any(x => x == minVersion)) + { + resolvedVersion = external.MinVersion; + } + else + { + resolvedVersion = versions.Max()?.ToString(); + } + } + else + { + // If min version was not provided, get the latest stable version. + resolvedVersion = await NugetPackageResolver.ResolveLatestPackageVersion(external.Package!, nugetSettings); + } if (!string.IsNullOrEmpty(resolvedVersion)) { var downloader = new NugetPackageDownloader(external.Package!, resolvedVersion!, null, nugetSettings); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/NugetPackageResolver.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/NugetPackageResolver.cs index 2c2883a3534..ab8de1f4e93 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/NugetPackageResolver.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/NugetPackageResolver.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using NuGet.Configuration; using NuGet.Frameworks; +using NuGet.Packaging; using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.Repositories; @@ -202,6 +203,28 @@ private static NuGetFramework ResolveCurrentFramework() return null; } + public static async Task> GetAllVersions(string packageName, ISettings nugetSettings, bool allowPrerelease) + { + HashSet versions = []; + var sources = SettingsUtility.GetEnabledSources(nugetSettings); + using var cacheContext = new SourceCacheContext(); + foreach (var source in sources) + { + try + { + var repository = Repository.Factory.GetCoreV3(source.Source); + var resource = await repository.GetResourceAsync(); + IEnumerable versionsFromOneRepo = (await resource.GetAllVersionsAsync(packageName, cacheContext, NuGet.Common.NullLogger.Instance, CancellationToken.None)).Where(v => !v.IsPrerelease || allowPrerelease); + versions.AddRange(versionsFromOneRepo); + } + catch + { + // Skip failed source. + } + } + return [..versions]; + } + /// /// Queries the configured NuGet feeds for the latest stable version of . /// When is provided, the latest stable version greater than or equal to it