diff --git a/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs b/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs index 4ef78e76a211..beee597e3101 100644 --- a/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs +++ b/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs @@ -214,7 +214,7 @@ protected void UpdateWorkloadManifests(WorkloadHistoryRecorder recorder, ITransa } } - string resolvedWorkloadSetVersion = _workloadSetVersionFromGlobalJson ??_workloadSetVersionFromCommandLine; + string resolvedWorkloadSetVersion = _workloadSetVersionFromGlobalJson ?? _workloadSetVersionFromCommandLine; if (string.IsNullOrWhiteSpace(resolvedWorkloadSetVersion) && !UseRollback && !FromHistory) { _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(_includePreviews, updateToLatestWorkloadSet, offlineCache).Wait(); @@ -423,10 +423,14 @@ protected IEnumerable WriteSDKInstallRecordsForVSWorkloads(IEnumerab internal static class InstallingWorkloadCommandParser { - public static readonly CliOption WorkloadSetVersionOption = new("--version") + public static readonly CliOption WorkloadSetVersionOption = new CliOption("--version") { Description = Strings.WorkloadSetVersionOptionDescription - }; + }.AddCompletions((ctx) => + { + var versions = Search.Versions.SearchWorkloadSetsCommand.GetWorkloadSetVersions(ctx).GetAwaiter().GetResult(); + return versions.Select(v => new System.CommandLine.Completions.CompletionItem(v)); + }); public static readonly CliOption PrintDownloadLinkOnlyOption = new("--print-download-link-only") { diff --git a/src/Cli/dotnet/commands/dotnet-complete/CompleteCommand.cs b/src/Cli/dotnet/commands/dotnet-complete/CompleteCommand.cs index 765b17ba2bc8..300687412c52 100644 --- a/src/Cli/dotnet/commands/dotnet-complete/CompleteCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-complete/CompleteCommand.cs @@ -60,8 +60,8 @@ private static CompletionItem[] Completions(ParseResult complete) var result = Parser.Instance.Parse(input); - return result.GetCompletions(position) - .Distinct() + var completions = result.GetCompletions(position); + return completions.Distinct() .ToArray(); } } diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs index 3cbe4e79dbab..9b5e45aa9953 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs @@ -2,26 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.CommandLine; -using System.Text.Json; -using Microsoft.Deployment.DotNet.Releases; using Microsoft.DotNet.Cli; -using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Workloads.Workload.Install; using Microsoft.NET.Sdk.WorkloadManifestReader; -using Microsoft.TemplateEngine.Cli.Commands; namespace Microsoft.DotNet.Workloads.Workload.Search { internal class WorkloadSearchCommand : WorkloadCommandBase { private readonly IWorkloadResolver _workloadResolver; - private readonly ReleaseVersion _sdkVersion; private readonly string _workloadIdStub; - private readonly int _numberOfWorkloadSetsToTake; - private readonly string _workloadSetOutputFormat; - private readonly IWorkloadManifestInstaller _installer; - internal bool ListWorkloadSetVersions { get; set; } = false; public WorkloadSearchCommand( ParseResult result, @@ -31,53 +22,17 @@ public WorkloadSearchCommand( _workloadIdStub = result.GetValue(WorkloadSearchCommandParser.WorkloadIdStubArgument); workloadResolverFactory = workloadResolverFactory ?? new WorkloadResolverFactory(); + var creationResult = workloadResolverFactory.Create(); + _workloadResolver = creationResult.WorkloadResolver; if (!string.IsNullOrEmpty(result.GetValue(WorkloadSearchCommandParser.VersionOption))) { throw new GracefulException(Install.LocalizableStrings.SdkVersionOptionNotSupported); } - - var creationResult = workloadResolverFactory.Create(); - - _sdkVersion = creationResult.SdkVersion; - _workloadResolver = creationResult.WorkloadResolver; - - _numberOfWorkloadSetsToTake = result.GetValue(SearchWorkloadSetsParser.TakeOption); - _workloadSetOutputFormat = result.GetValue(SearchWorkloadSetsParser.FormatOption); - - _installer = WorkloadInstallerFactory.GetWorkloadInstaller( - reporter, - new SdkFeatureBand(_sdkVersion), - _workloadResolver, - Verbosity, - creationResult.UserProfileDir, - !SignCheck.IsDotNetSigned(), - restoreActionConfig: new RestoreActionConfig(result.HasOption(SharedOptions.InteractiveOption)), - elevationRequired: false, - shouldLog: false); } public override int Execute() { - if (ListWorkloadSetVersions) - { - var featureBand = new SdkFeatureBand(_sdkVersion); - var packageId = _installer.GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), featureBand); - var versions = PackageDownloader.GetLatestPackageVersions(packageId, _numberOfWorkloadSetsToTake, packageSourceLocation: null, includePreview: !string.IsNullOrWhiteSpace(_sdkVersion.Prerelease)) - .GetAwaiter().GetResult() - .Select(version => WorkloadManifestUpdater.WorkloadSetPackageVersionToWorkloadSetVersion(featureBand, version.Version.ToString())); - if (_workloadSetOutputFormat?.Equals("json", StringComparison.OrdinalIgnoreCase) == true) - { - Reporter.WriteLine(JsonSerializer.Serialize(versions.Select(version => version.ToDictionary(_ => "workloadVersion", v => v)))); - } - else - { - Reporter.WriteLine(string.Join('\n', versions)); - } - - return 0; - } - IEnumerable availableWorkloads = _workloadResolver.GetAvailableWorkloads() .OrderBy(workload => workload.Id); diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/versions/SearchWorkloadSetsCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/search/versions/SearchWorkloadSetsCommand.cs new file mode 100644 index 000000000000..6270b42d1327 --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-workload/search/versions/SearchWorkloadSetsCommand.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.CommandLine.Completions; +using System.Text.Json; +using Microsoft.Deployment.DotNet.Releases; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Workloads.Workload.Install; +using Microsoft.NET.Sdk.WorkloadManifestReader; +using Microsoft.TemplateEngine.Cli.Commands; + +namespace Microsoft.DotNet.Workloads.Workload.Search.Versions; + +internal class SearchWorkloadSetsCommand : WorkloadCommandBase +{ + internal readonly int NumberOfWorkloadSetsToTake; + private readonly SearchWorkloadSetsFormat _workloadSetOutputFormat; + internal readonly IWorkloadManifestInstaller Installer; + internal readonly ReleaseVersion SdkVersion; + private readonly IWorkloadResolver _workloadResolver; + + private static readonly ManifestId WorkloadPackageIdBase = new("Microsoft.NET.Workloads"); + + public SearchWorkloadSetsCommand(ParseResult result, IWorkloadResolverFactory workloadResolverFactory = null, IReporter reporter = null) : base(result, reporter: reporter) + { + NumberOfWorkloadSetsToTake = result.HasOption(SearchWorkloadSetsParser.TakeOption) ? result.GetValue(SearchWorkloadSetsParser.TakeOption) : 5; + _workloadSetOutputFormat = result.GetValue(SearchWorkloadSetsParser.FormatOption); + workloadResolverFactory = workloadResolverFactory ?? new WorkloadResolverFactory(); + var creationResult = workloadResolverFactory.Create(); + + SdkVersion = creationResult.SdkVersion; + _workloadResolver = creationResult.WorkloadResolver; + + Installer = WorkloadInstallerFactory.GetWorkloadInstaller( + reporter, + new SdkFeatureBand(SdkVersion), + _workloadResolver, + Verbosity, + creationResult.UserProfileDir, + !SignCheck.IsDotNetSigned(), + restoreActionConfig: new RestoreActionConfig(result.HasOption(SharedOptions.InteractiveOption)), + elevationRequired: false, + shouldLog: false); + } + + protected override void ShowHelpOrErrorIfAppropriate(ParseResult parseResult) + { + + } + + public async Task Execute(CancellationToken cancellationToken) + { + var featureBand = new SdkFeatureBand(SdkVersion); + var packageId = Installer.GetManifestPackageId(WorkloadPackageIdBase, featureBand); + var versions = (await PackageDownloader.GetLatestPackageVersions(packageId, NumberOfWorkloadSetsToTake, packageSourceLocation: null, includePreview: !string.IsNullOrWhiteSpace(SdkVersion.Prerelease)).ConfigureAwait(false)) + .Select(version => WorkloadManifestUpdater.WorkloadSetPackageVersionToWorkloadSetVersion(featureBand, version.Version.ToString())); + if (_workloadSetOutputFormat == SearchWorkloadSetsFormat.json) + { + Reporter.WriteLine(JsonSerializer.Serialize(versions.Select(version => version.ToDictionary(_ => "workloadVersion", v => v)))); + } + else + { + Reporter.WriteLine(string.Join('\n', versions)); + } + + return 0; + } + + public override int Execute() => Execute(CancellationToken.None).GetAwaiter().GetResult(); + + /// + /// Used for CLI completions to get the workload set versions. + /// + /// + public static async Task> GetWorkloadSetVersions(CompletionContext ctx) + { + var inner = new SearchWorkloadSetsCommand(ctx.ParseResult); + var featureBand = new SdkFeatureBand(inner.SdkVersion); + var packageId = inner.Installer.GetManifestPackageId(WorkloadPackageIdBase, featureBand); + var versions = (await inner.PackageDownloader.GetLatestPackageVersions(packageId, inner.NumberOfWorkloadSetsToTake, packageSourceLocation: null, includePreview: !string.IsNullOrWhiteSpace(inner.SdkVersion.Prerelease)).ConfigureAwait(false)) + .Select(version => WorkloadManifestUpdater.WorkloadSetPackageVersionToWorkloadSetVersion(featureBand, version.Version.ToString())); + return versions; + } +} diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/SearchWorkloadSetsParser.cs b/src/Cli/dotnet/commands/dotnet-workload/search/versions/SearchWorkloadSetsParser.cs similarity index 78% rename from src/Cli/dotnet/commands/dotnet-workload/search/SearchWorkloadSetsParser.cs rename to src/Cli/dotnet/commands/dotnet-workload/search/versions/SearchWorkloadSetsParser.cs index 5ffecb96ad9f..eae7c2ea3eaf 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/SearchWorkloadSetsParser.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/search/versions/SearchWorkloadSetsParser.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.CommandLine; -using Microsoft.DotNet.Workloads.Workload.Search; +using Microsoft.DotNet.Workloads.Workload.Search.Versions; using LocalizableStrings = Microsoft.DotNet.Workloads.Workload.Search.LocalizableStrings; namespace Microsoft.DotNet.Cli @@ -11,7 +11,7 @@ internal static class SearchWorkloadSetsParser { public static readonly CliOption TakeOption = new("--take") { DefaultValueFactory = (_) => 5 }; - public static readonly CliOption FormatOption = new("--format") + public static readonly CliOption FormatOption = new("--format") { Description = LocalizableStrings.FormatOptionDescription }; @@ -37,12 +37,15 @@ private static CliCommand ConstructCommand() } }); - command.SetAction(parseResult => new WorkloadSearchCommand(parseResult) - { - ListWorkloadSetVersions = true - }.Execute()); + command.SetAction((parseResult, ct) => new SearchWorkloadSetsCommand(parseResult).Execute(ct)); return command; } } + + internal enum SearchWorkloadSetsFormat + { + list, + json + } }