diff --git a/src/Cli/dotnet/Parser.cs b/src/Cli/dotnet/Parser.cs index f42cf6661970..9572176d73fd 100644 --- a/src/Cli/dotnet/Parser.cs +++ b/src/Cli/dotnet/Parser.cs @@ -119,7 +119,7 @@ public static class Parser // Argument public static readonly Argument DotnetSubCommand = new("subcommand") { Arity = ArgumentArity.ZeroOrOne, Hidden = true }; - private static Command ConfigureCommandLine(Command rootCommand) + private static Command ConfigureCommandLine(RootCommand rootCommand) { for (int i = rootCommand.Options.Count - 1; i >= 0; i--) { @@ -156,6 +156,9 @@ private static Command ConfigureCommandLine(Command rootCommand) // Add argument rootCommand.Arguments.Add(DotnetSubCommand); + // NuGet implements several commands in its own repo. Add them to the .NET SDK via the provided API. + NuGet.CommandLine.XPlat.NuGetCommands.Add(rootCommand); + rootCommand.SetAction(parseResult => { if (parseResult.GetValue(DiagOption) && parseResult.Tokens.Count == 1) diff --git a/test/dotnet.Tests/CommandTests/NuGet/GivenANuGetCommand.cs b/test/dotnet.Tests/CommandTests/NuGet/GivenANuGetCommand.cs index 8e7359a4cf23..a114c98a1e4d 100644 --- a/test/dotnet.Tests/CommandTests/NuGet/GivenANuGetCommand.cs +++ b/test/dotnet.Tests/CommandTests/NuGet/GivenANuGetCommand.cs @@ -6,6 +6,8 @@ using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Commands.NuGet; using Moq; +using Newtonsoft.Json.Linq; +using NuGet.Versioning; namespace Microsoft.DotNet.Tools.Run.Tests { @@ -133,5 +135,50 @@ public void ItHasAWhySubcommand() .And.NotHaveStdErr() .And.HaveStdOutContaining("has the following dependency"); } + + [Fact] + public void ItCanUpdatePackages() + { + // Arrange + var testAssetName = "TestAppSimple"; + var testAsset = _testAssetsManager + .CopyTestAsset(testAssetName) + .WithSource(); + var projectDirectory = testAsset.Path; + + NuGetConfigWriter.Write(projectDirectory, TestContext.Current.TestPackages); + + new DotnetCommand(Log, "package", "add", "dotnet-hello@1.0.0") + .WithWorkingDirectory(projectDirectory) + .Execute() + .Should() + .Pass() + .And.NotHaveStdErr(); + + // Act + var commandResult = new DotnetCommand(Log, "package", "update", "dotnet-hello") + .WithWorkingDirectory(projectDirectory) + .Execute() + .Should() + .Pass() + .And.NotHaveStdErr(); + + // Assert + var listPackageCommandResult = new DotnetCommand(Log, "package", "list", "--format", "json") + .WithWorkingDirectory(projectDirectory) + .Execute(); + listPackageCommandResult.Should() + .Pass() + .And.NotHaveStdErr(); + + var updatedPackageVersionString = JObject.Parse(listPackageCommandResult.StdOut) + .SelectToken("$.projects[0].frameworks[0].topLevelPackages[?(@.id == 'dotnet-hello')].requestedVersion") + .ToString(); + + var v1 = NuGetVersion.Parse("1.0.0"); + var updatedVersion = NuGetVersion.Parse(updatedPackageVersionString); + + updatedVersion.Should().BeGreaterThan(v1); + } } } diff --git a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh index b4041b1e123c..9961ab63690c 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh +++ b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh @@ -1006,7 +1006,7 @@ _testhost_package() { prev="${COMP_WORDS[COMP_CWORD-1]}" COMPREPLY=() - opts="search add list remove --help" + opts="search add list remove update --help" if [[ $COMP_CWORD == "$1" ]]; then COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) @@ -1034,6 +1034,11 @@ _testhost_package() { return ;; + (update) + _testhost_package_update $(($1+1)) + return + ;; + esac COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) @@ -1126,6 +1131,23 @@ _testhost_package_remove() { } +_testhost_package_update() { + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + COMPREPLY=() + + opts="--project --help" + + if [[ $COMP_CWORD == "$1" ]]; then + COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) + return + fi + + COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) +} + + _testhost_project() { cur="${COMP_WORDS[COMP_CWORD]}" diff --git a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 index 3d96499b00d8..ff1e1e2022f0 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 +++ b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 @@ -573,6 +573,7 @@ Register-ArgumentCompleter -Native -CommandName 'testhost' -ScriptBlock { [CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, "Add a NuGet package reference to the project.") [CompletionResult]::new('list', 'list', [CompletionResultType]::ParameterValue, "List all package references of the project or solution.") [CompletionResult]::new('remove', 'remove', [CompletionResultType]::ParameterValue, "Remove a NuGet package reference from the project.") + [CompletionResult]::new('update', 'update', [CompletionResultType]::ParameterValue, "Update referenced packages in a project or solution.") ) $completions += $staticCompletions break @@ -656,6 +657,15 @@ Register-ArgumentCompleter -Native -CommandName 'testhost' -ScriptBlock { $completions += $staticCompletions break } + 'testhost;package;update' { + $staticCompletions = @( + [CompletionResult]::new('--project', '--project', [CompletionResultType]::ParameterName, "Path to a project or solution file, or a directory.") + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, "Show command line help.") + [CompletionResult]::new('--help', '-h', [CompletionResultType]::ParameterName, "Show command line help.") + ) + $completions += $staticCompletions + break + } 'testhost;project' { $staticCompletions = @( [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, "Show command line help.") diff --git a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh index a35e334962a1..f5f123f8be71 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh +++ b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh @@ -646,6 +646,14 @@ _testhost() { '*::PACKAGE_NAME -- The package reference to remove.: ' \ && ret=0 ;; + (update) + _arguments "${_arguments_options[@]}" : \ + '--project=[Path to a project or solution file, or a directory.]: : ' \ + '--help[Show command line help.]' \ + '-h[Show command line help.]' \ + '*::packages: ' \ + && ret=0 + ;; esac ;; esac @@ -1640,6 +1648,7 @@ _testhost__package_commands() { 'add:Add a NuGet package reference to the project.' \ 'list:List all package references of the project or solution.' \ 'remove:Remove a NuGet package reference from the project.' \ + 'update:Update referenced packages in a project or solution.' \ ) _describe -t commands 'testhost package commands' commands "$@" } @@ -1668,6 +1677,12 @@ _testhost__package__remove_commands() { _describe -t commands 'testhost package remove commands' commands "$@" } +(( $+functions[_testhost__package__update_commands] )) || +_testhost__package__update_commands() { + local commands; commands=() + _describe -t commands 'testhost package update commands' commands "$@" +} + (( $+functions[_testhost__project_commands] )) || _testhost__project_commands() { local commands; commands=(