Enable LTS/Current/Preview selection (#469)
This change does a couple of things to enable LTS/Current/Preview selection: - Adds a command line argument to allow selection - Maps the selected support model to identify the TFM that is needed - Updates the PackageLoader to limit searches to results that match the TFMs in a project
This commit is contained in:
Родитель
f5a0c7b634
Коммит
10fd0c8d40
|
@ -5,13 +5,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
## Current
|
||||
|
||||
### Added
|
||||
- A new command line option (`--target-tfm-support` to select the support model of LTS/Preview/Current that is desired [#469](https://github.com/dotnet/upgrade-assistant/pull/469)
|
||||
|
||||
### Fixed
|
||||
- VB Win Forms projects should keep import for 'System.Windows.Forms' [#474](https://github.com/dotnet/upgrade-assistant/pull/474)
|
||||
|
||||
## Version 0.2.222702 - 2021-04-27 ([Link](https://www.nuget.org/packages/upgrade-assistant/0.2.222702))
|
||||
|
||||
### Added
|
||||
- Multiple entrypoints can now be added by using globbing and multiple instances of the `--entry-point` argument [#425](https://github.com/dotnet/upgrade-assistant/pull/425)
|
||||
- Multiple entrypoints can now be added by using globbing and multiple instances of the `--entry-point` argument [#425](https://github.com/dotnet/upgrade-assistant/pull/425)
|
||||
- NuGet credential providers will now be used, if present (may require running in interactive mode) [#448](https://github.com/dotnet/upgrade-assistant/pull/448)
|
||||
- Source analyzers and code fix providers are now applied to source embedded in Razor documents [#455](https://github.com/dotnet/upgrade-assistant/pull/455)
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
<PackageVersion Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.321" />
|
||||
<PackageVersion Include="System.Collections.Immutable" Version="5.0.0" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta1.20371.2" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta1.21216.1" />
|
||||
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Linq.Async" Version="5.0.0" />
|
||||
<PackageVersion Include="System.Reactive" Version="5.0.0" />
|
||||
|
|
42
README.md
42
README.md
|
@ -82,29 +82,25 @@ Arguments:
|
|||
<project>
|
||||
|
||||
Options:
|
||||
--skip-backup Disables backing up the project. This is
|
||||
not recommended unless the project is in
|
||||
source control since this tool will make
|
||||
large changes to both the project and
|
||||
source files.
|
||||
--extension <extension> Specifies a .NET Upgrade Assistant
|
||||
extension package to include. This could
|
||||
be an ExtensionManifest.json file, a
|
||||
directory containing an
|
||||
ExtensionManifest.json file, or a zip
|
||||
archive containing an extension. This
|
||||
option can be specified multiple times.
|
||||
-e, --entry-point <entry-point> Provides the entry-point project to start
|
||||
the upgrade process. This may include
|
||||
globbing patterns such as '*' for match.
|
||||
-v, --verbose Enable verbose diagnostics
|
||||
--non-interactive Automatically select each first option in
|
||||
non-interactive mode.
|
||||
--non-interactive-wait Wait the supplied seconds before moving
|
||||
<non-interactive-wait> on to the next option in non-interactive
|
||||
mode.
|
||||
--version Show version information
|
||||
-?, -h, --help Show help and usage information
|
||||
--skip-backup Disables backing up the project. This is not recommended unless the
|
||||
project is in source control since this tool will make large changes
|
||||
to both the project and source files.
|
||||
--extension <extension> Specifies a .NET Upgrade Assistant extension package to include. This
|
||||
could be an ExtensionManifest.json file, a directory containing an
|
||||
ExtensionManifest.json file, or a zip archive containing an extension.
|
||||
This option can be specified multiple times.
|
||||
-e, --entry-point <entry-point> Provides the entry-point project to start the upgrade process. This
|
||||
may include globbing patterns such as '*' for match.
|
||||
-v, --verbose Enable verbose diagnostics
|
||||
--non-interactive Automatically select each first option in non-interactive mode.
|
||||
--non-interactive-wait <non-interactive-wait> Wait the supplied seconds before moving on to the next option in
|
||||
non-interactive mode.
|
||||
--target-tfm-support <Current|LTS|Preview> Select if you would like the Long Term Support (LTS), Current, or
|
||||
Preview TFM. See
|
||||
https://dotnet.microsoft.com/platform/support/policy/dotnet-core for
|
||||
details for what these mean.
|
||||
--version Show version information
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
|
||||
>**:warning:** The primary usage of upgrade-assistant is to be used in interactive mode, giving users control over changes/upgrades done to their projects. Usage of upgrade-assistant with --non-interactive mode can leave projects in a broken state and users are advised to use at their own discretion. **:warning:**
|
||||
|
|
|
@ -7,6 +7,19 @@ namespace Microsoft.DotNet.UpgradeAssistant.Cli
|
|||
{
|
||||
internal static class ConsoleUtils
|
||||
{
|
||||
public static int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Console.IsOutputRedirected)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
return Console.WindowWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
if (!Console.IsOutputRedirected)
|
||||
|
|
|
@ -7,7 +7,6 @@ using System.CommandLine;
|
|||
using System.CommandLine.Builder;
|
||||
using System.CommandLine.Help;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.CommandLine.IO;
|
||||
using System.CommandLine.Parsing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -15,6 +14,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Microsoft.DotNet.UpgradeAssistant.Extensions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
@ -133,7 +133,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Cli
|
|||
services.AddSingleton<IProcessRunner, ProcessRunner>();
|
||||
services.AddSingleton<ErrorCodeAccessor>();
|
||||
|
||||
services.AddStepManagement();
|
||||
services.AddStepManagement(context.Configuration.GetSection("DefaultTargetFrameworks").Bind);
|
||||
});
|
||||
|
||||
var host = configure(hostBuilder).UseConsoleLifetime(options =>
|
||||
|
@ -181,29 +181,18 @@ namespace Microsoft.DotNet.UpgradeAssistant.Cli
|
|||
private class HelpWithHeader : HelpBuilder
|
||||
{
|
||||
public HelpWithHeader(IConsole console)
|
||||
: base(console, maxWidth: 90)
|
||||
: base(console, maxWidth: ConsoleUtils.Width)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Write(ICommand command)
|
||||
protected override void AddSynopsis(ICommand command)
|
||||
{
|
||||
ShowHeader();
|
||||
|
||||
WriteString("Makes a best-effort attempt to upgrade .NET Framework projects to .NET 5.");
|
||||
WriteString("This tool does not completely automate the upgrade process and it is expected that projects will have build errors after the tool runs. Manual changes will be required to complete the upgrade to .NET 5.");
|
||||
WriteString("This tool's purpose is to automate some of the 'routine' upgrade tasks such as changing project file formats and updating APIs with near-equivalents in .NET Core. Analyzers added to the project will highlight the remaining changes needed after the tool runs.");
|
||||
|
||||
base.Write(command);
|
||||
}
|
||||
|
||||
private void WriteString(string input)
|
||||
{
|
||||
foreach (var line in SplitText(input, MaxWidth))
|
||||
{
|
||||
Console.Out.WriteLine(line);
|
||||
}
|
||||
|
||||
Console.Out.WriteLine();
|
||||
const string Title = "Makes a best-effort attempt to upgrade .NET Framework projects to current, preview or LTS versions of .NET.\n\n" +
|
||||
"This tool does not completely automate the upgrade process and it is expected that projects will have build errors after the tool runs. Manual changes will be required to complete the upgrade to .NET 5.\n\n" +
|
||||
"This tool's purpose is to automate some of the 'routine' upgrade tasks such as changing project file formats and updating APIs with near-equivalents in the selected target framework. Analyzers added to the project will highlight the remaining changes needed after the tool runs.\n";
|
||||
WriteHeading(Title, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,6 +207,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Cli
|
|||
command.AddOption(new Option<bool>(new[] { "--verbose", "-v" }, "Enable verbose diagnostics"));
|
||||
command.AddOption(new Option<bool>(new[] { "--non-interactive" }, "Automatically select each first option in non-interactive mode."));
|
||||
command.AddOption(new Option<int>(new[] { "--non-interactive-wait" }, "Wait the supplied seconds before moving on to the next option in non-interactive mode."));
|
||||
command.AddOption(new Option<UpgradeTarget>(new[] { "--target-tfm-support" }, "Select if you would like the Long Term Support (LTS), Current, or Preview TFM. See https://dotnet.microsoft.com/platform/support/policy/dotnet-core for details for what these mean."));
|
||||
}
|
||||
|
||||
#if ANALYZE_COMMAND
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
"Templates\\VisualBasicWebAppTemplates\\WebAppTemplates.json"
|
||||
]
|
||||
},
|
||||
"TFMSelector": {
|
||||
"CurrentTFMBase": "net5.0",
|
||||
"LTSTFMBase": "net5.0"
|
||||
"DefaultTargetFrameworks": {
|
||||
"Current": "net5.0",
|
||||
"LTS": "netcoreapp3.1",
|
||||
"Preview": "net6.0"
|
||||
},
|
||||
"TryConvertProjectConverter": {
|
||||
"TryConvertPath": "./tools/try-convert.exe"
|
||||
|
|
|
@ -9,12 +9,10 @@ namespace Microsoft.DotNet.UpgradeAssistant
|
|||
{
|
||||
public interface IPackageLoader
|
||||
{
|
||||
IEnumerable<string> PackageSources { get; }
|
||||
|
||||
Task<bool> DoesPackageSupportTargetFrameworksAsync(NuGetReference packageReference, IEnumerable<TargetFrameworkMoniker> targetFrameworks, CancellationToken token);
|
||||
|
||||
Task<IEnumerable<NuGetReference>> GetNewerVersionsAsync(NuGetReference reference, bool latestMinorAndBuildOnly, CancellationToken token);
|
||||
Task<IEnumerable<NuGetReference>> GetNewerVersionsAsync(NuGetReference reference, IEnumerable<TargetFrameworkMoniker> tfms, bool latestMinorAndBuildOnly, CancellationToken token);
|
||||
|
||||
Task<NuGetReference?> GetLatestVersionAsync(string packageName, bool includePreRelease, string[]? packageSources, CancellationToken token);
|
||||
Task<NuGetReference?> GetLatestVersionAsync(string packageName, IEnumerable<TargetFrameworkMoniker> tfms, bool includePreRelease, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant
|
||||
{
|
||||
|
|
|
@ -27,6 +27,6 @@ namespace Microsoft.DotNet.UpgradeAssistant
|
|||
|
||||
public int NonInteractiveWait { get; set; } = 2;
|
||||
|
||||
public UpgradeTarget UpgradeTarget { get; set; } = UpgradeTarget.Current;
|
||||
public UpgradeTarget TargetTfmSupport { get; set; } = UpgradeTarget.Current;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Microsoft.DotNet.UpgradeAssistant
|
|||
public enum UpgradeTarget
|
||||
{
|
||||
LTS,
|
||||
Current
|
||||
Current,
|
||||
Preview
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using NuGet.Configuration;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
||||
{
|
||||
public interface INuGetPackageSourceFactory
|
||||
{
|
||||
IEnumerable<PackageSource> GetPackageSources(string? path);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
||||
{
|
||||
public class NuGetDownloaderOptions
|
||||
{
|
||||
public string? CachePath { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NuGet.Configuration;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
||||
{
|
||||
public class NuGetPackageSourceFactory : INuGetPackageSourceFactory
|
||||
{
|
||||
private const string DefaultPackageSource = "https://api.nuget.org/v3/index.json";
|
||||
|
||||
private readonly ILogger<NuGetPackageSourceFactory> _logger;
|
||||
|
||||
public NuGetPackageSourceFactory(ILogger<NuGetPackageSourceFactory> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public IEnumerable<PackageSource> GetPackageSources(string? path)
|
||||
{
|
||||
var packageSources = new List<PackageSource>();
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
var nugetSettings = Settings.LoadDefaultSettings(path);
|
||||
var sourceProvider = new PackageSourceProvider(nugetSettings);
|
||||
packageSources.AddRange(sourceProvider.LoadPackageSources().Where(e => e.IsEnabled));
|
||||
}
|
||||
|
||||
if (packageSources.Count == 0)
|
||||
{
|
||||
packageSources.Add(new PackageSource(DefaultPackageSource));
|
||||
}
|
||||
|
||||
_logger.LogDebug("Found package sources: {PackageSources}", packageSources);
|
||||
|
||||
return packageSources;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,14 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NuGet.Configuration;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging;
|
||||
|
@ -20,38 +22,47 @@ namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
|||
{
|
||||
public sealed class PackageLoader : IPackageLoader, IDisposable
|
||||
{
|
||||
private const string DefaultPackageSource = "https://api.nuget.org/v3/index.json";
|
||||
private const int MaxRetries = 3;
|
||||
|
||||
private readonly SourceCacheContext _cache;
|
||||
private readonly List<PackageSource> _packageSources;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Lazy<IEnumerable<PackageSource>> _packageSources;
|
||||
private readonly ILogger<PackageLoader> _logger;
|
||||
private readonly NuGet.Common.ILogger _nugetLogger;
|
||||
private readonly string _cachePath;
|
||||
private readonly IDictionary<PackageSource, SourceRepository> _sourceRepositoryCache;
|
||||
private readonly Dictionary<PackageSource, SourceRepository> _sourceRepositoryCache;
|
||||
private readonly NuGetDownloaderOptions _options;
|
||||
|
||||
public IEnumerable<string> PackageSources => _packageSources.Select(s => s.Source);
|
||||
|
||||
public PackageLoader(UpgradeOptions options, ILogger<PackageLoader> logger)
|
||||
public PackageLoader(
|
||||
UpgradeOptions upgradeOptions,
|
||||
INuGetPackageSourceFactory sourceFactory,
|
||||
ILogger<PackageLoader> logger,
|
||||
IOptions<NuGetDownloaderOptions> options)
|
||||
{
|
||||
if (upgradeOptions is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(upgradeOptions));
|
||||
}
|
||||
|
||||
if (sourceFactory is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceFactory));
|
||||
}
|
||||
|
||||
if (options is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if (options.ProjectPath is null)
|
||||
if (upgradeOptions.ProjectPath is null)
|
||||
{
|
||||
throw new ArgumentException("Project path must be set in UpgradeOptions", nameof(options));
|
||||
throw new ArgumentException("Project path must be set in UpgradeOptions", nameof(upgradeOptions));
|
||||
}
|
||||
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_nugetLogger = new NuGetLogger(logger);
|
||||
_cache = new SourceCacheContext();
|
||||
_packageSources = GetPackageSources(Path.GetDirectoryName(options.ProjectPath));
|
||||
_packageSources = new Lazy<IEnumerable<PackageSource>>(() => sourceFactory.GetPackageSources(Path.GetDirectoryName(upgradeOptions.ProjectPath)));
|
||||
_sourceRepositoryCache = new Dictionary<PackageSource, SourceRepository>();
|
||||
|
||||
var settings = Settings.LoadDefaultSettings(null);
|
||||
_cachePath = SettingsUtility.GetGlobalPackagesFolder(settings);
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
public async Task<bool> DoesPackageSupportTargetFrameworksAsync(NuGetReference packageReference, IEnumerable<TargetFrameworkMoniker> targetFrameworks, CancellationToken token)
|
||||
|
@ -68,23 +79,35 @@ namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
|||
return targetFrameworks.All(tfm => packageFrameworks.Any(f => DefaultCompatibilityProvider.Instance.IsCompatible(NuGetFramework.Parse(tfm.Name), f)));
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<NuGetReference>> GetNewerVersionsAsync(NuGetReference reference, bool latestMinorAndBuildOnly, CancellationToken token)
|
||||
public Task<IEnumerable<NuGetReference>> GetNewerVersionsAsync(NuGetReference reference, IEnumerable<TargetFrameworkMoniker> tfms, bool latestMinorAndBuildOnly, CancellationToken token)
|
||||
{
|
||||
if (reference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(reference));
|
||||
}
|
||||
|
||||
var versions = new List<NuGetVersion>();
|
||||
return SearchByNameAsync(reference.Name, tfms, currentVersion: reference.GetNuGetVersion(), latestMinorAndBuildOnly: latestMinorAndBuildOnly, token: token);
|
||||
}
|
||||
|
||||
// Query each package source for listed versions of the given package name
|
||||
foreach (var source in _packageSources)
|
||||
public async Task<NuGetReference?> GetLatestVersionAsync(string packageName, IEnumerable<TargetFrameworkMoniker> tfms, bool includePreRelease, CancellationToken token)
|
||||
{
|
||||
var result = await SearchByNameAsync(packageName, tfms, includePreRelease, token: token).ConfigureAwait(false);
|
||||
|
||||
return result.LastOrDefault();
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<NuGetReference>> SearchByNameAsync(string name, IEnumerable<TargetFrameworkMoniker> tfms, bool includePrerelease = false, NuGetVersion? currentVersion = null, bool latestMinorAndBuildOnly = false, CancellationToken token = default)
|
||||
{
|
||||
var results = new List<IPackageSearchMetadata>();
|
||||
|
||||
foreach (var source in _packageSources.Value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var metadata = await GetSourceRepository(source).GetResourceAsync<PackageMetadataResource>(token).ConfigureAwait(false);
|
||||
var searchResults = await CallWithRetryAsync(() => metadata.GetMetadataAsync(reference.Name, includePrerelease: true, includeUnlisted: false, _cache, _nugetLogger, token)).ConfigureAwait(false);
|
||||
versions.AddRange(searchResults.Select(r => r.Identity.Version));
|
||||
var searchResults = await CallWithRetryAsync(() => metadata.GetMetadataAsync(name, includePrerelease: includePrerelease, includeUnlisted: false, _cache, _nugetLogger, token)).ConfigureAwait(false);
|
||||
|
||||
results.AddRange(searchResults);
|
||||
}
|
||||
catch (NuGetProtocolException)
|
||||
{
|
||||
|
@ -96,76 +119,59 @@ namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
|||
}
|
||||
}
|
||||
|
||||
// Filter to only include versions higher than the user's current version and,
|
||||
// optionally, only the highest minor/build for each major version
|
||||
var currentVersion = reference.GetNuGetVersion();
|
||||
var filteredVersions = versions.Distinct().Where(v => v > currentVersion);
|
||||
var versionsToReturn = latestMinorAndBuildOnly
|
||||
? filteredVersions.GroupBy(v => v.Major).Select(v => v.Where(v => !v.IsPrerelease).Max() ?? v.Max()!)
|
||||
: filteredVersions;
|
||||
|
||||
_logger.LogDebug("Found versions for package {PackageName}: {PackageVersions}", reference.Name, versionsToReturn);
|
||||
|
||||
return versionsToReturn.OrderBy(v => v).Select(v => reference with { Version = v.ToNormalizedString() });
|
||||
return FilterSearchResults(name, results, tfms, currentVersion, latestMinorAndBuildOnly);
|
||||
}
|
||||
|
||||
public async Task<NuGetReference?> GetLatestVersionAsync(string packageName, bool includePreRelease, string[]? packageSources, CancellationToken token)
|
||||
public static IEnumerable<NuGetReference> FilterSearchResults(
|
||||
string name,
|
||||
IReadOnlyCollection<IPackageSearchMetadata> searchResults,
|
||||
IEnumerable<TargetFrameworkMoniker> tfms,
|
||||
NuGetVersion? currentVersion = null,
|
||||
bool latestMinorAndBuildOnly = false)
|
||||
{
|
||||
NuGetVersion? highestVersion = null;
|
||||
|
||||
// Query each package source for listed versions of the given package name
|
||||
foreach (var source in packageSources?.Select(p => new PackageSource(p)) ?? _packageSources)
|
||||
if (searchResults is null || searchResults.Count == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var metadata = await GetSourceRepository(source).GetResourceAsync<PackageMetadataResource>(token).ConfigureAwait(false);
|
||||
var searchResults = await CallWithRetryAsync(() => metadata.GetMetadataAsync(packageName, includePrerelease: includePreRelease, includeUnlisted: false, _cache, _nugetLogger, token)).ConfigureAwait(false);
|
||||
var highestVersionResult = searchResults.Select(r => r.Identity.Version).Max(v => v);
|
||||
if (highestVersionResult is null)
|
||||
return Enumerable.Empty<NuGetReference>();
|
||||
}
|
||||
|
||||
var tfmSet = ImmutableHashSet.CreateRange(tfms.Select(t => NuGetFramework.Parse(t.Name)));
|
||||
|
||||
var results = searchResults
|
||||
.Where(r => currentVersion is null || r.Identity.Version > currentVersion);
|
||||
|
||||
if (latestMinorAndBuildOnly)
|
||||
{
|
||||
results = results
|
||||
.GroupBy(r => r.Identity.Version.Major)
|
||||
.SelectMany(r =>
|
||||
{
|
||||
continue;
|
||||
var max = r.Max(t => t.Identity.Version);
|
||||
|
||||
return r.Where(t => t.Identity.Version == max);
|
||||
});
|
||||
}
|
||||
|
||||
return results
|
||||
.Where(r =>
|
||||
{
|
||||
var unsupported = tfmSet;
|
||||
|
||||
foreach (var dep in r.DependencySets)
|
||||
{
|
||||
foreach (var t in unsupported)
|
||||
{
|
||||
if (DefaultCompatibilityProvider.Instance.IsCompatible(t, dep.TargetFramework))
|
||||
{
|
||||
unsupported = unsupported.Remove(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (highestVersion is null || highestVersionResult > highestVersion)
|
||||
{
|
||||
highestVersion = highestVersionResult;
|
||||
}
|
||||
}
|
||||
catch (NuGetProtocolException)
|
||||
{
|
||||
_logger.LogWarning("Failed to get package versions from source {PackageSource} due to a NuGet protocol error", source.Source);
|
||||
}
|
||||
catch (HttpRequestException exc)
|
||||
{
|
||||
_logger.LogWarning("Failed to get package versions from source {PackageSource} due to an HTTP error ({StatusCode})", source.Source, exc.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (highestVersion is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NuGetReference(packageName, highestVersion.ToFullString());
|
||||
}
|
||||
|
||||
private List<PackageSource> GetPackageSources(string? projectDir)
|
||||
{
|
||||
var packageSources = new List<PackageSource>();
|
||||
if (projectDir != null)
|
||||
{
|
||||
var nugetSettings = Settings.LoadDefaultSettings(projectDir);
|
||||
var sourceProvider = new PackageSourceProvider(nugetSettings);
|
||||
packageSources.AddRange(sourceProvider.LoadPackageSources().Where(e => e.IsEnabled));
|
||||
}
|
||||
|
||||
if (packageSources.Count == 0)
|
||||
{
|
||||
packageSources.Add(new PackageSource(DefaultPackageSource));
|
||||
}
|
||||
|
||||
_logger.LogDebug("Found package sources: {PackageSources}", packageSources);
|
||||
return packageSources;
|
||||
return unsupported.IsEmpty;
|
||||
})
|
||||
.Select(r => r.Identity.Version)
|
||||
.OrderBy(v => v)
|
||||
.Select(v => new NuGetReference(name, v.ToNormalizedString()));
|
||||
}
|
||||
|
||||
private async Task<T> CallWithRetryAsync<T>(Func<Task<T>> func)
|
||||
|
@ -240,9 +246,9 @@ namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
|||
}
|
||||
|
||||
// First look in the local NuGet cache for the archive
|
||||
if (_cachePath is not null)
|
||||
if (_options.CachePath is string cachePath)
|
||||
{
|
||||
var archivePath = Path.Combine(_cachePath, packageReference.Name, packageReference.Version, $"{packageReference.Name}.{packageReference.Version}.nupkg");
|
||||
var archivePath = Path.Combine(cachePath, packageReference.Name, packageReference.Version, $"{packageReference.Name}.{packageReference.Version}.nupkg");
|
||||
if (File.Exists(archivePath))
|
||||
{
|
||||
_logger.LogDebug("NuGet package {NuGetPackage} loaded from {PackagePath}", packageReference, archivePath);
|
||||
|
@ -256,7 +262,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.MSBuild
|
|||
|
||||
// Attempt to download the package from the sources
|
||||
var packageVersion = packageReference.GetNuGetVersion();
|
||||
foreach (var source in _packageSources)
|
||||
foreach (var source in _packageSources.Value)
|
||||
{
|
||||
var repo = GetSourceRepository(source);
|
||||
var packageFinder = await repo.GetResourceAsync<FindPackageByIdResource>(token).ConfigureAwait(false);
|
||||
|
|
|
@ -7,6 +7,7 @@ using Microsoft.Build.Construction;
|
|||
using Microsoft.Build.Evaluation;
|
||||
using Microsoft.DotNet.UpgradeAssistant.MSBuild;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NuGet.Configuration;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant
|
||||
{
|
||||
|
@ -22,15 +23,28 @@ namespace Microsoft.DotNet.UpgradeAssistant
|
|||
services.AddTransient<IUpgradeStartup, MSBuildRegistrationStartup>();
|
||||
services.AddSingleton<IUpgradeContextFactory, MSBuildUpgradeContextFactory>();
|
||||
services.AddSingleton<IComponentIdentifier, ComponentIdentifier>();
|
||||
services.AddSingleton<IPackageLoader, PackageLoader>();
|
||||
services.AddSingleton<IVersionComparer, NuGetVersionComparer>();
|
||||
services.AddSingleton<IUpgradeStartup, NuGetCredentialsStartup>();
|
||||
|
||||
// Instantiate the upgrade context with a func to avoid needing MSBuild types prior to MSBuild registration
|
||||
services.AddTransient<MSBuildWorkspaceUpgradeContext>();
|
||||
services.AddTransient<IUpgradeContext>(sp => sp.GetRequiredService<MSBuildWorkspaceUpgradeContext>());
|
||||
services.AddTransient<Func<MSBuildWorkspaceUpgradeContext>>(sp => () => sp.GetRequiredService<MSBuildWorkspaceUpgradeContext>());
|
||||
|
||||
services.AddNuGet();
|
||||
}
|
||||
|
||||
private static void AddNuGet(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IPackageLoader, PackageLoader>();
|
||||
services.AddSingleton<IVersionComparer, NuGetVersionComparer>();
|
||||
services.AddTransient<ITargetFrameworkMonikerComparer, NuGetTargetFrameworkMonikerComparer>();
|
||||
services.AddSingleton<IUpgradeStartup, NuGetCredentialsStartup>();
|
||||
services.AddSingleton<INuGetPackageSourceFactory, NuGetPackageSourceFactory>();
|
||||
services.AddOptions<NuGetDownloaderOptions>()
|
||||
.Configure(options =>
|
||||
{
|
||||
var settings = Settings.LoadDefaultSettings(null);
|
||||
options.CachePath = SettingsUtility.GetGlobalPackagesFolder(settings);
|
||||
});
|
||||
}
|
||||
|
||||
// TEMPORARY WORKAROUND
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Options" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\Microsoft.DotNet.UpgradeAssistant.Abstractions\Microsoft.DotNet.UpgradeAssistant.Abstractions.csproj" />
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant
|
||||
{
|
||||
public class DefaultTfmOptions
|
||||
{
|
||||
[Required]
|
||||
public string Current { get; set; } = null!;
|
||||
|
||||
[Required]
|
||||
public string LTS { get; set; } = null!;
|
||||
|
||||
[Required]
|
||||
public string Preview { get; set; } = null!;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.TargetFramework
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant
|
||||
{
|
||||
public class TFMSelectorOptions
|
||||
{
|
||||
public string? CurrentTFMBase { get; set; }
|
||||
|
||||
public string? LTSTFMBase { get; set; }
|
||||
}
|
||||
}
|
|
@ -12,32 +12,26 @@ namespace Microsoft.DotNet.UpgradeAssistant.TargetFramework
|
|||
{
|
||||
public class TargetFrameworkSelector : ITargetFrameworkSelector
|
||||
{
|
||||
private const string DefaultCurrentTFMBase = "net5.0";
|
||||
private const string DefaultLTSTFMBase = "net5.0";
|
||||
|
||||
private readonly ITargetFrameworkMonikerComparer _comparer;
|
||||
private readonly DefaultTfmOptions _selectorOptions;
|
||||
private readonly IEnumerable<ITargetFrameworkSelectorFilter> _selectors;
|
||||
private readonly ILogger<TargetFrameworkSelector> _logger;
|
||||
|
||||
private readonly string _currentTFMBase;
|
||||
private readonly string _ltsTFMBase;
|
||||
|
||||
private readonly UpgradeTarget _upgradeTarget;
|
||||
|
||||
public TargetFrameworkSelector(
|
||||
UpgradeOptions options,
|
||||
ITargetFrameworkMonikerComparer comparer,
|
||||
IOptions<TFMSelectorOptions> selectorOptions,
|
||||
IOptions<DefaultTfmOptions> selectorOptions,
|
||||
IEnumerable<ITargetFrameworkSelectorFilter> selectors,
|
||||
ILogger<TargetFrameworkSelector> logger)
|
||||
{
|
||||
_comparer = comparer;
|
||||
_selectorOptions = selectorOptions?.Value ?? throw new ArgumentNullException(nameof(selectorOptions));
|
||||
_selectors = selectors;
|
||||
_logger = logger;
|
||||
|
||||
_currentTFMBase = selectorOptions?.Value.CurrentTFMBase ?? DefaultCurrentTFMBase;
|
||||
_ltsTFMBase = selectorOptions?.Value.LTSTFMBase ?? DefaultLTSTFMBase;
|
||||
_upgradeTarget = options?.UpgradeTarget ?? throw new ArgumentNullException(nameof(options));
|
||||
_upgradeTarget = options?.TargetTfmSupport ?? throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
public async ValueTask<TargetFrameworkMoniker> SelectTargetFrameworkAsync(IProject project, CancellationToken token)
|
||||
|
@ -47,7 +41,14 @@ namespace Microsoft.DotNet.UpgradeAssistant.TargetFramework
|
|||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
var appBase = _upgradeTarget == UpgradeTarget.Current ? _currentTFMBase : _ltsTFMBase;
|
||||
var appBase = _upgradeTarget switch
|
||||
{
|
||||
UpgradeTarget.Current => _selectorOptions.Current,
|
||||
UpgradeTarget.Preview => _selectorOptions.Preview,
|
||||
UpgradeTarget.LTS => _selectorOptions.LTS,
|
||||
_ => _selectorOptions.LTS,
|
||||
};
|
||||
|
||||
var current = GetDefaultTargetFrameworkMoniker(project);
|
||||
|
||||
if (!_comparer.TryParse(appBase, out var appBaseTfm))
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.TargetFramework
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using Microsoft.DotNet.UpgradeAssistant.Checks;
|
||||
using Microsoft.DotNet.UpgradeAssistant.TargetFramework;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
@ -9,13 +10,16 @@ namespace Microsoft.DotNet.UpgradeAssistant
|
|||
{
|
||||
public static class UpgraderExtensions
|
||||
{
|
||||
public static void AddStepManagement(this IServiceCollection services)
|
||||
public static void AddStepManagement(this IServiceCollection services, Action<DefaultTfmOptions> options)
|
||||
{
|
||||
services.AddScoped<UpgraderManager>();
|
||||
services.AddTransient<IUpgradeContextProperties, UpgradeContextProperties>();
|
||||
services.AddTransient<IUpgradeStepOrderer, UpgradeStepOrderer>();
|
||||
services.AddReadinessChecks();
|
||||
services.AddTargetFrameworkSelectors();
|
||||
services.AddOptions<DefaultTfmOptions>()
|
||||
.Configure(options)
|
||||
.ValidateDataAnnotations();
|
||||
}
|
||||
|
||||
private static void AddReadinessChecks(this IServiceCollection services)
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Analyzers
|
|||
|
||||
if (!packageReferences.Any(r => NewtonsoftPackageName.Equals(r.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var newtonsoftPackage = await _packageLoader.GetLatestVersionAsync(NewtonsoftPackageName, false, null, token).ConfigureAwait(false);
|
||||
var newtonsoftPackage = await _packageLoader.GetLatestVersionAsync(NewtonsoftPackageName, project.TargetFrameworks, false, token).ConfigureAwait(false);
|
||||
|
||||
if (newtonsoftPackage is not null)
|
||||
{
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Analyzers
|
|||
var packageToAdd = newPackage;
|
||||
if (packageToAdd.HasWildcardVersion)
|
||||
{
|
||||
var reference = await _packageLoader.GetLatestVersionAsync(packageToAdd.Name, false, null, token).ConfigureAwait(false);
|
||||
var reference = await _packageLoader.GetLatestVersionAsync(packageToAdd.Name, project.TargetFrameworks, false, token).ConfigureAwait(false);
|
||||
|
||||
if (reference is not null)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -53,7 +52,9 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Analyzers
|
|||
else
|
||||
{
|
||||
// If the package won't work on the target Framework, check newer versions of the package
|
||||
var updatedReference = await GetUpdatedPackageVersionAsync(packageReference, project.TargetFrameworks, token).ConfigureAwait(false);
|
||||
var newerVersions = await _packageLoader.GetNewerVersionsAsync(packageReference, project.TargetFrameworks, true, token).ConfigureAwait(false);
|
||||
var updatedReference = newerVersions.FirstOrDefault();
|
||||
|
||||
if (updatedReference == null)
|
||||
{
|
||||
_logger.LogWarning("No version of {PackageName} found that supports {TargetFramework}; leaving unchanged", packageReference.Name, project.TargetFrameworks);
|
||||
|
@ -82,34 +83,5 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Analyzers
|
|||
|
||||
return state;
|
||||
}
|
||||
|
||||
private async Task<NuGetReference?> GetUpdatedPackageVersionAsync(NuGetReference packageReference, IEnumerable<TargetFrameworkMoniker> targetFramework, CancellationToken token)
|
||||
{
|
||||
var latestMinorVersions = await _packageLoader.GetNewerVersionsAsync(packageReference, true, token).ConfigureAwait(false);
|
||||
NuGetReference? prereleaseCandidate = null;
|
||||
|
||||
foreach (var newerPackage in latestMinorVersions)
|
||||
{
|
||||
if (await _packageLoader.DoesPackageSupportTargetFrameworksAsync(newerPackage, targetFramework, token).ConfigureAwait(false))
|
||||
{
|
||||
_logger.LogDebug("Package {NuGetPackage} will work on {TargetFramework}", newerPackage, targetFramework);
|
||||
|
||||
// Only return a pre-release version if it's the only newer major version that supports the necessary TFM
|
||||
if (newerPackage.IsPrerelease)
|
||||
{
|
||||
if (prereleaseCandidate is null)
|
||||
{
|
||||
prereleaseCandidate = newerPackage;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return newerPackage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prereleaseCandidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,18 +32,23 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Analyzers
|
|||
|
||||
public async Task<PackageAnalysisState> AnalyzeAsync(IProject project, PackageAnalysisState state, CancellationToken token)
|
||||
{
|
||||
if (project is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (state is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
var references = await project.Required().GetNuGetReferencesAsync(token).ConfigureAwait(false);
|
||||
var references = await project.GetNuGetReferencesAsync(token).ConfigureAwait(false);
|
||||
var packageReferences = references.PackageReferences.Where(r => !state.PackagesToRemove.Contains(r));
|
||||
|
||||
// If the project doesn't include a reference to the analyzer package, mark it for addition
|
||||
if (!packageReferences.Any(r => AnalyzerPackageName.Equals(r.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var analyzerPackage = await _packageLoader.GetLatestVersionAsync(AnalyzerPackageName, true, null, token).ConfigureAwait(false);
|
||||
var analyzerPackage = await _packageLoader.GetLatestVersionAsync(AnalyzerPackageName, project.TargetFrameworks, true, token).ConfigureAwait(false);
|
||||
|
||||
if (analyzerPackage is not null)
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Analyzers
|
|||
return state;
|
||||
}
|
||||
|
||||
var latestVersion = await _loader.GetLatestVersionAsync(PackageName, false, null, token).ConfigureAwait(false);
|
||||
var latestVersion = await _loader.GetLatestVersionAsync(PackageName, project.TargetFrameworks, false, token).ConfigureAwait(false);
|
||||
|
||||
if (latestVersion is null)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoFixture;
|
||||
using Moq;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.MSBuild.Tests
|
||||
{
|
||||
[Collection(MSBuildStepTestCollection.Name)]
|
||||
public class PackageLoaderTests
|
||||
{
|
||||
private readonly Fixture _fixture;
|
||||
|
||||
public PackageLoaderTests()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
|
||||
_fixture.Customize<NuGetReference>(o =>
|
||||
o.Without(o => o.PrivateAssets)
|
||||
.Without(o => o.Version));
|
||||
}
|
||||
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
[Theory]
|
||||
public void FilterTestEmptyInput(bool isNull)
|
||||
{
|
||||
// Arrange
|
||||
var name = _fixture.Create<string>();
|
||||
var searchResults = isNull ? null : Array.Empty<IPackageSearchMetadata>();
|
||||
var tfms = _fixture.CreateMany<TargetFrameworkMoniker>();
|
||||
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(name, searchResults!, tfms);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
private static IPackageSearchMetadata MockSearchMetadata(NuGetReference reference, params TargetFrameworkMoniker[] tfms)
|
||||
{
|
||||
var metadata = new Mock<IPackageSearchMetadata>();
|
||||
var identity = new PackageIdentity(reference.Name, reference.GetNuGetVersion());
|
||||
var groups = tfms.Select(tfm => new PackageDependencyGroup(NuGetFramework.Parse(tfm.Name), Enumerable.Empty<PackageDependency>()));
|
||||
|
||||
metadata.Setup(m => m.Identity).Returns(identity);
|
||||
metadata.Setup(m => m.DependencySets).Returns(groups);
|
||||
|
||||
return metadata.Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilterExplicitMatch()
|
||||
{
|
||||
// Arrange
|
||||
var item = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var tfm = TargetFrameworkMoniker.NetStandard20;
|
||||
var metadata = MockSearchMetadata(item, tfm);
|
||||
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item.Name, new[] { metadata }, new[] { tfm });
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result, r => Assert.Equal(r, item));
|
||||
}
|
||||
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
[Theory]
|
||||
public void FilterSupported(bool isBackwards)
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "2.0.0" };
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.Net50);
|
||||
|
||||
var list = isBackwards ? new[] { metadata2, metadata1 } : new[] { metadata1, metadata2 };
|
||||
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, list, new[] { TargetFrameworkMoniker.Net50 });
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
r => Assert.Equal(r, item1),
|
||||
r => Assert.Equal(r, item2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filter3Only2Supported()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "2.0.0" };
|
||||
var item3 = item1 with { Version = "3.0.0" };
|
||||
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.Net50);
|
||||
var metadata3 = MockSearchMetadata(item3, TargetFrameworkMoniker.Net60);
|
||||
|
||||
foreach (var metadata in Permute(metadata1, metadata2, metadata3))
|
||||
{
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, metadata, new[] { TargetFrameworkMoniker.Net50 });
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
r => Assert.Equal(r, item1),
|
||||
r => Assert.Equal(r, item2));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filter3Only1Supported()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "2.0.0" };
|
||||
var item3 = item1 with { Version = "3.0.0" };
|
||||
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.Net45);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.Net50);
|
||||
var metadata3 = MockSearchMetadata(item3, TargetFrameworkMoniker.Net60);
|
||||
|
||||
foreach (var metadata in Permute(metadata1, metadata2, metadata3))
|
||||
{
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, metadata, new[] { TargetFrameworkMoniker.Net50 });
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result, r => Assert.Equal(r, item2));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filter3Only1SupportedMultipleTfmsInSearch()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "2.0.0" };
|
||||
var item3 = item1 with { Version = "3.0.0" };
|
||||
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.NetStandard10, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.Net45, TargetFrameworkMoniker.Net50);
|
||||
var metadata3 = MockSearchMetadata(item3, TargetFrameworkMoniker.Net50_Linux, TargetFrameworkMoniker.Net50_Windows);
|
||||
|
||||
foreach (var metadata in Permute(metadata1, metadata2, metadata3))
|
||||
{
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, metadata, new[] { TargetFrameworkMoniker.Net50 });
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
r => Assert.Equal(r, item1),
|
||||
r => Assert.Equal(r, item2));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filter3Only1SupportedMultipleTfms()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "2.0.0" };
|
||||
var item3 = item1 with { Version = "3.0.0" };
|
||||
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.NetStandard10, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.Net45, TargetFrameworkMoniker.Net50);
|
||||
var metadata3 = MockSearchMetadata(item3, TargetFrameworkMoniker.Net50_Linux, TargetFrameworkMoniker.Net50_Windows);
|
||||
|
||||
foreach (var metadata in Permute(metadata1, metadata2, metadata3))
|
||||
{
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, metadata, new[] { TargetFrameworkMoniker.Net50, TargetFrameworkMoniker.NetStandard20 });
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result, r => Assert.Equal(r, item1));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filter3Only1SupportedMultipleTfmsNoMatches()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "2.0.0" };
|
||||
var item3 = item1 with { Version = "3.0.0" };
|
||||
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.Net45, TargetFrameworkMoniker.NetCoreApp21);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.Net45, TargetFrameworkMoniker.Net50);
|
||||
var metadata3 = MockSearchMetadata(item3, TargetFrameworkMoniker.Net50_Linux, TargetFrameworkMoniker.Net50_Windows);
|
||||
|
||||
foreach (var metadata in Permute(metadata1, metadata2, metadata3))
|
||||
{
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, metadata, new[] { TargetFrameworkMoniker.Net50, TargetFrameworkMoniker.NetStandard20 });
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilterOnly()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = _fixture.Create<NuGetReference>() with { Version = "1.0.0" };
|
||||
var item2 = item1 with { Version = "1.1.0" };
|
||||
var item3 = item1 with { Version = "1.2.0" };
|
||||
var item4 = item1 with { Version = "2.1.0" };
|
||||
|
||||
var metadata1 = MockSearchMetadata(item1, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata2 = MockSearchMetadata(item2, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata3 = MockSearchMetadata(item3, TargetFrameworkMoniker.NetStandard20);
|
||||
var metadata4 = MockSearchMetadata(item4, TargetFrameworkMoniker.NetStandard20);
|
||||
|
||||
foreach (var metadata in Permute(metadata1, metadata2, metadata3, metadata4))
|
||||
{
|
||||
// Act
|
||||
var result = PackageLoader.FilterSearchResults(item1.Name, metadata, new[] { TargetFrameworkMoniker.Net50 }, latestMinorAndBuildOnly: true);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
r => Assert.Equal(r, item3),
|
||||
r => Assert.Equal(r, item4));
|
||||
}
|
||||
}
|
||||
|
||||
private static IReadOnlyCollection<IReadOnlyCollection<T>> Permute<T>(params T[] nums)
|
||||
{
|
||||
var list = new List<IReadOnlyCollection<T>>();
|
||||
return DoPermute(nums, 0, nums.Length - 1, list);
|
||||
|
||||
static List<IReadOnlyCollection<T>> DoPermute(T[] nums, int start, int end, List<IReadOnlyCollection<T>> list)
|
||||
{
|
||||
if (start == end)
|
||||
{
|
||||
// We have one of our possible n! solutions,
|
||||
// add it to the list.
|
||||
list.Add(new List<T>(nums));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = start; i <= end; i++)
|
||||
{
|
||||
Swap(ref nums[start], ref nums[i]);
|
||||
DoPermute(nums, start + 1, end, list);
|
||||
Swap(ref nums[start], ref nums[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
static void Swap(ref T a, ref T b)
|
||||
{
|
||||
var temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,10 +16,11 @@ namespace Microsoft.DotNet.UpgradeAssistant.Tests
|
|||
{
|
||||
public class TargetFrameworkSelectorTests
|
||||
{
|
||||
private readonly TFMSelectorOptions _options = new TFMSelectorOptions
|
||||
private readonly DefaultTfmOptions _options = new DefaultTfmOptions
|
||||
{
|
||||
CurrentTFMBase = Current,
|
||||
LTSTFMBase = LTS,
|
||||
Current = Current,
|
||||
LTS = LTS,
|
||||
Preview = Preview,
|
||||
};
|
||||
|
||||
[Fact]
|
||||
|
@ -61,14 +62,14 @@ namespace Microsoft.DotNet.UpgradeAssistant.Tests
|
|||
project.Setup(p => p.TargetFrameworks).Returns(currentTfms.Select(t => ParseTfm(t)).ToArray());
|
||||
project.Setup(p => p.GetComponentsAsync(default)).Returns(new ValueTask<ProjectComponents>(components));
|
||||
|
||||
mock.Create<UpgradeOptions>().UpgradeTarget = target;
|
||||
mock.Mock<IOptions<TFMSelectorOptions>>().Setup(o => o.Value).Returns(_options);
|
||||
mock.Create<UpgradeOptions>().TargetTfmSupport = target;
|
||||
mock.Mock<IOptions<DefaultTfmOptions>>().Setup(o => o.Value).Returns(_options);
|
||||
|
||||
var moniker = mock.Mock<ITargetFrameworkMonikerComparer>();
|
||||
moniker.Setup(c => c.TryMerge(ParseTfm(current), tfm, out finalTfm)).Returns(true);
|
||||
moniker.SetupTryParse();
|
||||
|
||||
var appBase = target == UpgradeTarget.Current ? _options.CurrentTFMBase : _options.LTSTFMBase;
|
||||
var appBase = target == UpgradeTarget.Current ? _options.Current : _options.LTS;
|
||||
|
||||
var selector = mock.Create<TargetFrameworkSelector>();
|
||||
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using Autofac.Extras.Moq;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.UpgradeAssistant.Tests
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac.Extras.Moq;
|
||||
|
@ -36,7 +37,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Tests.Analyzers
|
|||
|
||||
// Assert
|
||||
Assert.Contains(actual.PackagesToAdd, (package) => package.Name.Equals(NewtonsoftPackageName, System.StringComparison.Ordinal));
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string[]>(), It.IsAny<CancellationToken>()),
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<IEnumerable<TargetFrameworkMoniker>>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
|
@ -66,7 +67,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Tests.Analyzers
|
|||
|
||||
// Assert
|
||||
Assert.DoesNotContain(actual.PackagesToAdd, (package) => package.Name.Equals(NewtonsoftPackageName, System.StringComparison.Ordinal));
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string[]>(), It.IsAny<CancellationToken>()),
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<IEnumerable<TargetFrameworkMoniker>>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Never());
|
||||
}
|
||||
|
||||
|
@ -93,7 +94,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Tests.Analyzers
|
|||
|
||||
// Assert
|
||||
Assert.DoesNotContain(actual.PackagesToAdd, (package) => package.Name.Equals(NewtonsoftPackageName, System.StringComparison.Ordinal));
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string[]>(), It.IsAny<CancellationToken>()),
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<IEnumerable<TargetFrameworkMoniker>>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Never());
|
||||
}
|
||||
|
||||
|
@ -120,7 +121,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Tests.Analyzers
|
|||
|
||||
// Assert
|
||||
Assert.DoesNotContain(actual.PackagesToAdd, (package) => package.Name.Equals(NewtonsoftPackageName, System.StringComparison.Ordinal));
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string[]>(), It.IsAny<CancellationToken>()),
|
||||
packageLoader.Verify(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<IEnumerable<TargetFrameworkMoniker>>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Never());
|
||||
}
|
||||
|
||||
|
@ -155,7 +156,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Packages.Tests.Analyzers
|
|||
private static Mock<IPackageLoader> CreatePackageLoader(AutoMock mock)
|
||||
{
|
||||
var packageLoader = mock.Mock<IPackageLoader>();
|
||||
packageLoader.Setup(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<string[]>(), It.IsAny<CancellationToken>()))
|
||||
packageLoader.Setup(pl => pl.GetLatestVersionAsync(It.IsAny<string>(), It.IsAny<IEnumerable<TargetFrameworkMoniker>>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult((NuGetReference?)new NuGetReference(NewtonsoftPackageName, "122.0.0")));
|
||||
return packageLoader;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"Hyak.Common": "1.2.2",
|
||||
"MahApps.Metro": "2.4.4",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.5",
|
||||
"Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers": "1.0.0",
|
||||
"Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers": "0.2.222702",
|
||||
"Microsoft.Windows.Compatibility": "5.0.2",
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"Nito.AsyncEx": "5.1.0"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="1.0.0">
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.2.222702">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Antlr4" Version="4.6.6" />
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</Target>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="1.0.0">
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.2.222702">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="1.0.0">
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.2.222702">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<PackageReference Include="Castle.Windsor" Version="4.1.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.3" />
|
||||
<PackageReference Include="Microsoft.Rest.ClientRuntime.Azure" Version="3.3.7" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="1.0.0">
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.2.222702">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Hyak.Common" Version="1.2.2" />
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<PackageReference Include="System.ServiceModel.Duplex" Version="4.8.1" />
|
||||
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.8.1" />
|
||||
<PackageReference Include="System.ServiceModel.Federation" Version="4.8.1" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="1.0.0">
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.2.222702">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="1.0.0">
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.2.222702">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Windows.Compatibility" Version="5.0.2" />
|
||||
|
|
|
@ -26,21 +26,19 @@ namespace Integration.Tests
|
|||
_unknownPackages = unknownPackages ?? throw new ArgumentNullException(nameof(unknownPackages));
|
||||
}
|
||||
|
||||
public IEnumerable<string> PackageSources => _other.PackageSources;
|
||||
|
||||
public Task<bool> DoesPackageSupportTargetFrameworksAsync(NuGetReference packageReference, IEnumerable<TargetFrameworkMoniker> targetFrameworks, CancellationToken token)
|
||||
{
|
||||
return _other.DoesPackageSupportTargetFrameworksAsync(packageReference, targetFrameworks, token);
|
||||
}
|
||||
|
||||
public async Task<NuGetReference?> GetLatestVersionAsync(string packageName, bool includePreRelease, string[]? packageSources, CancellationToken token)
|
||||
public async Task<NuGetReference?> GetLatestVersionAsync(string packageName, IEnumerable<TargetFrameworkMoniker> tfms, bool includePreRelease, CancellationToken token)
|
||||
{
|
||||
if (_packages.TryGetValue(packageName, out var known))
|
||||
{
|
||||
return known;
|
||||
}
|
||||
|
||||
var latest = await _other.GetLatestVersionAsync(packageName, includePreRelease, packageSources, token).ConfigureAwait(false);
|
||||
var latest = await _other.GetLatestVersionAsync(packageName, tfms, includePreRelease, token).ConfigureAwait(false);
|
||||
|
||||
if (latest is not null)
|
||||
{
|
||||
|
@ -51,14 +49,14 @@ namespace Integration.Tests
|
|||
return latest;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<NuGetReference>> GetNewerVersionsAsync(NuGetReference reference, bool latestMinorAndBuildOnly, CancellationToken token)
|
||||
public async Task<IEnumerable<NuGetReference>> GetNewerVersionsAsync(NuGetReference reference, IEnumerable<TargetFrameworkMoniker> tfms, bool latestMinorAndBuildOnly, CancellationToken token)
|
||||
{
|
||||
if (_packages.TryGetValue(reference.Name, out var known))
|
||||
{
|
||||
return new NuGetReference[] { known };
|
||||
}
|
||||
|
||||
var latest = await _other.GetNewerVersionsAsync(reference, latestMinorAndBuildOnly, token).ConfigureAwait(false);
|
||||
var latest = await _other.GetNewerVersionsAsync(reference, tfms, latestMinorAndBuildOnly, token).ConfigureAwait(false);
|
||||
|
||||
if (latest is not null)
|
||||
{
|
||||
|
@ -67,7 +65,7 @@ namespace Integration.Tests
|
|||
_logger.LogError("Unexpected check for newer version: {Name}, {Version}", reference.Name, reference.Version);
|
||||
}
|
||||
|
||||
return latest ?? Array.Empty<NuGetReference>();
|
||||
return latest ?? Enumerable.Empty<NuGetReference>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче