| File: Commands\Package\PackageCommandParser.cs | Web Access |
| Project: src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet) |
// 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 Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.Commands.Package.Add; using Microsoft.DotNet.Cli.Commands.Package.List; using Microsoft.DotNet.Cli.Commands.Package.Remove; using Microsoft.DotNet.Cli.Commands.Package.Search; using Microsoft.DotNet.Cli.Commands.Run; using Microsoft.DotNet.Cli.Extensions; using Microsoft.Extensions.EnvironmentAbstractions; using NuGet.Versioning; namespace Microsoft.DotNet.Cli.Commands.Package; internal sealed class PackageCommandParser { public static void ConfigureCommand(PackageCommandDefinition command) { command.SetAction((parseResult) => parseResult.HandleMissingCommand()); command.RemoveCommand.SetAction(parseResult => new PackageRemoveCommand(parseResult).Execute()); command.ListCommand.SetAction(parseResult => new PackageListCommand(parseResult).Execute()); ConfigureAddCommand(command.AddCommand); command.SearchCommand.SetAction(parseResult => { var command = new PackageSearchCommand(parseResult); int exitCode = command.Execute(); if (exitCode == 1) { parseResult.ShowHelp(); } // Only return 1 or 0 return exitCode == 0 ? 0 : 1; }); } internal static void ConfigureAddCommand(PackageAddCommandDefinitionBase def) { def.PackageIdArgument.CompletionSources.Add(context => { // we should take --prerelease flags into account for version completion var allowPrerelease = context.ParseResult.GetValue(def.PrereleaseOption); return QueryNuGet(context.WordToComplete, allowPrerelease, CancellationToken.None).Result.Select(packageId => new CompletionItem(packageId)); }); def.VersionOption.CompletionSources.Add(context => { // we can only do version completion if we have a package id if (context.ParseResult.GetValue(def.PackageIdArgument) is { HasVersion: false } packageId) { // we should take --prerelease flags into account for version completion var allowPrerelease = context.ParseResult.GetValue(def.PrereleaseOption); return QueryVersionsForPackage(packageId.Id, context.WordToComplete, allowPrerelease, CancellationToken.None) .Result .Select(version => new CompletionItem(version.ToNormalizedString())); } else { return []; } }); def.SetAction(parseResult => new PackageAddCommand(parseResult).Execute()); } private static async Task<IEnumerable<string>> QueryNuGet(string packageStem, bool allowPrerelease, CancellationToken cancellationToken) { try { var downloader = new NuGetPackageDownloader.NuGetPackageDownloader(packageInstallDir: new DirectoryPath()); var versions = await downloader.GetPackageIdsAsync(packageStem, allowPrerelease, cancellationToken: cancellationToken); return versions; } catch (Exception) { return []; } } private static async Task<IEnumerable<NuGetVersion>> QueryVersionsForPackage(string packageId, string versionFragment, bool allowPrerelease, CancellationToken cancellationToken) { try { var downloader = new NuGetPackageDownloader.NuGetPackageDownloader(packageInstallDir: new DirectoryPath()); var versions = await downloader.GetPackageVersionsAsync(new(packageId), versionFragment, allowPrerelease, cancellationToken: cancellationToken); return versions; } catch (Exception) { return []; } } internal static (string Path, AppKinds AllowedAppKinds) ProcessPathOptions(Option<string?>? fileOption, Option<string?>? projectOption, Argument<string>? projectOrFileArgument, ParseResult parseResult) { bool hasFileOption = fileOption is not null && parseResult.HasOption(fileOption); bool hasProjectOption = projectOption is not null && parseResult.HasOption(projectOption); return (hasFileOption, hasProjectOption) switch { (false, false) => projectOrFileArgument != null && parseResult.GetValue(projectOrFileArgument) is { } projectOrFile ? (projectOrFile, AppKinds.Any) : (Environment.CurrentDirectory, AppKinds.ProjectBased), (true, false) => (parseResult.GetValue(fileOption!)!, AppKinds.FileBased), (false, true) => (parseResult.GetValue(projectOption!)!, AppKinds.ProjectBased), (true, true) => throw new Utils.GracefulException(CliCommandStrings.CannotCombineOptions, fileOption!.Name, projectOption!.Name), }; } }