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:
Taylor Southwick 2021-05-04 13:40:41 -07:00 коммит произвёл GitHub
Родитель f5a0c7b634
Коммит 10fd0c8d40
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
41 изменённых файлов: 576 добавлений и 244 удалений

Просмотреть файл

@ -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" />

Просмотреть файл

@ -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>();
}
}
}