From 618a15c0f70b5cf645c0e77ab1aabac3ff5f9533 Mon Sep 17 00:00:00 2001 From: Douglas Cunha Date: Thu, 26 Jun 2025 11:55:06 -0300 Subject: [PATCH 1/2] chore: migrate to system.commandline beta5 --- NetTools.Tests/Commands/RemoveCommandTests.cs | 74 +++++++++--------- .../Commands/StandardizeCommandTests.cs | 30 ++++---- NetTools.Tests/Commands/UpdateCommandTests.cs | 32 ++++---- NetTools/Commands/RemoveCommand.cs | 62 ++++++++++----- NetTools/Commands/StandardizeCommand.cs | 62 +++++++++------ NetTools/Commands/UpdateCommand.cs | 77 +++++++++++-------- NetTools/NetTools.csproj | 2 +- NetTools/Program.cs | 5 +- 8 files changed, 198 insertions(+), 146 deletions(-) diff --git a/NetTools.Tests/Commands/RemoveCommandTests.cs b/NetTools.Tests/Commands/RemoveCommandTests.cs index 803f54f..4ca4ad8 100644 --- a/NetTools.Tests/Commands/RemoveCommandTests.cs +++ b/NetTools.Tests/Commands/RemoveCommandTests.cs @@ -47,10 +47,10 @@ public void Constructor_AddsRequiredOptions() _command.Options.Count.ShouldBe(4); var optionNames = _command.Options.Select(static o => o.Name).ToList(); - optionNames.ShouldContain("clean"); - optionNames.ShouldContain("restore"); - optionNames.ShouldContain("build"); - optionNames.ShouldContain("verbose"); + optionNames.ShouldContain("--clean"); + optionNames.ShouldContain("--restore"); + optionNames.ShouldContain("--build"); + optionNames.ShouldContain("--verbose"); } [Fact] @@ -76,12 +76,12 @@ public async Task Invoke_ValidPackageAndSolution_RemovesPackageFromSelectedProje var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -109,11 +109,11 @@ public async Task Invoke_NoProjectsSelected_DoesNotRemovePackages() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync([ + var result = await rootCommand.Parse([ "rm", PACKAGE_ID, SOLUTION_FILE - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -146,12 +146,12 @@ public async Task Invoke_MultipleProjects_RemovesPackageFromAllSelected() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -182,13 +182,13 @@ public async Task Invoke_WithCleanOption_RunsDotnetCommandsWithClean() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE, "--clean" - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -225,13 +225,13 @@ public async Task Invoke_WithRestoreOption_RunsDotnetCommandsWithRestore() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE, "--restore" - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -268,13 +268,13 @@ public async Task Invoke_WithBuildOption_RunsDotnetCommandsWithBuild() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE, "--build" - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -311,13 +311,13 @@ public async Task Invoke_WithVerboseOption_RunsDotnetCommandsWithVerbose() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE, "--verbose" - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -354,8 +354,8 @@ public async Task Invoke_WithAllOptions_RunsDotnetCommandsWithAllFlags() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE, @@ -363,7 +363,7 @@ public async Task Invoke_WithAllOptions_RunsDotnetCommandsWithAllFlags() "--restore", "--build", "--verbose" - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -400,13 +400,13 @@ public async Task Invoke_WithShortOptions_RunsDotnetCommandsCorrectly() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE, "-c", "-r", "-b", "-v" - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -443,10 +443,10 @@ public async Task Invoke_WithNullSolutionFile_UsesPromptedSolution() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync([ + var result = await rootCommand.Parse([ "rm", PACKAGE_ID - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -484,12 +484,12 @@ public async Task Invoke_ChangesCurrentDirectoryToSolutionDirectory() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync - ([ + var result = await rootCommand.Parse( + [ "rm", PACKAGE_ID, SOLUTION_FILE - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -522,11 +522,11 @@ public async Task Invoke_UsesPredicateToFilterProjectsWithPackage() var rootCommand = new RootCommand { _command }; // Act - var result = await rootCommand.InvokeAsync([ + var result = await rootCommand.Parse([ "rm", PACKAGE_ID, SOLUTION_FILE - ]); + ]).InvokeAsync(); // Assert result.ShouldBe(0); diff --git a/NetTools.Tests/Commands/StandardizeCommandTests.cs b/NetTools.Tests/Commands/StandardizeCommandTests.cs index 3c8480d..189be36 100644 --- a/NetTools.Tests/Commands/StandardizeCommandTests.cs +++ b/NetTools.Tests/Commands/StandardizeCommandTests.cs @@ -32,7 +32,7 @@ public StandardizeCommandTests() _environment ); - _rootCommand.AddCommand(_command); + _rootCommand.Subcommands.Add(_command); } [Fact] @@ -58,10 +58,10 @@ public void Constructor_AddsRequiredOptions() _command.Options.Count.ShouldBe(4); var optionNames = _command.Options.Select(static o => o.Name).ToList(); - optionNames.ShouldContain("clean"); - optionNames.ShouldContain("restore"); - optionNames.ShouldContain("build"); - optionNames.ShouldContain("verbose"); + optionNames.ShouldContain("--clean"); + optionNames.ShouldContain("--restore"); + optionNames.ShouldContain("--build"); + optionNames.ShouldContain("--verbose"); } [Fact] @@ -82,7 +82,7 @@ public async Task HandleAsync_NoProjectsSelected_DoNothing() .Returns([]); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -110,7 +110,7 @@ public async Task HandleAsync_WithProjectsSelected_CallsStandardizer() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -147,7 +147,7 @@ public async Task HandleAsync_WithCleanOption_PassesCleanToStandardizer() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE, "--clean"]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE, "--clean"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -184,7 +184,7 @@ public async Task HandleAsync_WithRestoreOption_PassesRestoreToStandardizer() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE, "--restore"]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE, "--restore"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -221,7 +221,7 @@ public async Task HandleAsync_WithBuildOption_PassesBuildToStandardizer() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE, "--build"]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE, "--build"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -258,7 +258,7 @@ public async Task HandleAsync_WithVerboseOption_PassesVerboseToStandardizer() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE, "--verbose"]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE, "--verbose"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -295,7 +295,7 @@ public async Task HandleAsync_WithAllOptions_PassesAllParametersCorrectly() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE, "--clean", "--restore", "--build", "--verbose"]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE, "--clean", "--restore", "--build", "--verbose"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -332,7 +332,7 @@ public async Task HandleAsync_WithShortOptions_PassesAllParametersCorrectly() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE, "-c", "-r", "-b", "-v"]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE, "-c", "-r", "-b", "-v"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -369,7 +369,7 @@ public async Task HandleAsync_WithNullSolutionFile_CallsGetOrPromptSolutionFile( .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st"]); + int result = await _rootCommand.Parse(["st"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -397,7 +397,7 @@ public async Task HandleAsync_MultipleProjects_PassesAllProjectsToStandardizer() .Returns(projects); // Act - int result = await _rootCommand.InvokeAsync(["st", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["st", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); diff --git a/NetTools.Tests/Commands/UpdateCommandTests.cs b/NetTools.Tests/Commands/UpdateCommandTests.cs index 1eb91db..96a1bb3 100644 --- a/NetTools.Tests/Commands/UpdateCommandTests.cs +++ b/NetTools.Tests/Commands/UpdateCommandTests.cs @@ -38,7 +38,7 @@ public UpdateCommandTests() _environment ); - _rootCommand.AddCommand(_command); + _rootCommand.Subcommands.Add(_command); } [Fact] @@ -64,11 +64,11 @@ public void Constructor_AddsRequiredOptions() _command.Options.Count.ShouldBe(5); var optionNames = _command.Options.Select(static o => o.Name).ToList(); - optionNames.ShouldContain("include-prerelease"); - optionNames.ShouldContain("clean"); - optionNames.ShouldContain("restore"); - optionNames.ShouldContain("build"); - optionNames.ShouldContain("verbose"); + optionNames.ShouldContain("--include-prerelease"); + optionNames.ShouldContain("--clean"); + optionNames.ShouldContain("--restore"); + optionNames.ShouldContain("--build"); + optionNames.ShouldContain("--verbose"); } [Fact] @@ -89,7 +89,7 @@ public async Task HandleAsync_NoProjectsSelected_DoNothing() .Returns([]); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -120,7 +120,7 @@ public async Task HandleAsync_AllPackagesUpToDate_ReturnsOneAndDisplaysMessage() SetupBasicMocks(projects, projectPackages, consolidatedPackages, latestVersions); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -163,7 +163,7 @@ public async Task HandleAsync_OutdatedPackagesButNoneSelected_ReturnsOneAndDispl _console.Input.PushKey(ConsoleKey.Enter); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -211,7 +211,7 @@ public async Task HandleAsync_OutdatedPackagesSelected_UpdatesAndReturnsZero() _console.Input.PushKey(ConsoleKey.Enter); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -256,7 +256,7 @@ public async Task HandleAsync_WithIncludePrereleaseOption_PassesToNugetService() .Returns("2.0.0-beta"); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE, "--include-prerelease"]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE, "--include-prerelease"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -303,7 +303,7 @@ public async Task HandleAsync_WithCleanOption_PassesToDotnetRunner() _console.Input.PushTextWithEnter(" "); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE, "--clean"]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE, "--clean"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -350,7 +350,7 @@ public async Task HandleAsync_WithRestoreOption_PassesToDotnetRunner() _console.Input.PushTextWithEnter(" "); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE, "--restore"]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE, "--restore"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -397,7 +397,7 @@ public async Task HandleAsync_WithBuildOption_PassesToDotnetRunner() _console.Input.PushTextWithEnter(" "); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE, "--build"]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE, "--build"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -444,7 +444,7 @@ public async Task HandleAsync_WithVerboseOption_PassesToDotnetRunner() _console.Input.PushTextWithEnter(" "); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE, "--verbose"]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE, "--verbose"]).InvokeAsync(); // Assert result.ShouldBe(0); @@ -496,7 +496,7 @@ public async Task HandleAsync_WithAllOptions_PassesAllParametersCorrectly() _console.Input.PushKey(ConsoleKey.Enter); // Act - int result = await _rootCommand.InvokeAsync(["upd", SOLUTION_FILE, "--include-prerelease", "--clean", "--restore", "--build", "--verbose"]); + int result = await _rootCommand.Parse(["upd", SOLUTION_FILE, "--include-prerelease", "--clean", "--restore", "--build", "--verbose"]).InvokeAsync(); // Assert result.ShouldBe(0); diff --git a/NetTools/Commands/RemoveCommand.cs b/NetTools/Commands/RemoveCommand.cs index 614e940..d1a7f7e 100644 --- a/NetTools/Commands/RemoveCommand.cs +++ b/NetTools/Commands/RemoveCommand.cs @@ -18,29 +18,53 @@ public sealed class RemoveCommand : Command IEnvironmentService environment ) : base("rm", "Remove a NuGet package from selected projects in a solution.") { - var packageIdArgument = new Argument("packageId", "The NuGet package id to remove."); + var packageIdArgument = new Argument("packageId") + { + Description = "The NuGet package id to remove." + }; + + var solutionFileArgument = new Argument("solutionFile") + { + Description = "The path to the .sln file to discover projects (optional). If omitted, the tool will search for a solution file in the current directory or prompt for selection.", + Arity = ArgumentArity.ZeroOrOne + }; + + var cleanOption = new Option("--clean", "-c") + { + Description = "Clean the solution after removal." + }; - var solutionFileArgument = new Argument - ( - "solutionFile", - static () => null, - "The path to the .sln file to discover projects (optional). If omitted, the tool will search for a solution file in the current directory or prompt for selection." - ); + var restoreOption = new Option("--restore", "-r") + { + Description = "Restore the solution after removal." + }; - var cleanOption = new Option(["--clean", "-c"], static () => false, "Clean the solution after removal."); - var restoreOption = new Option(["--restore", "-r"], static () => false, "Restore the solution after removal."); - var buildOption = new Option(["--build", "-b"], static () => false, "Build the solution after removal."); - var verboseOption = new Option(["--verbose", "-v"], static () => false, "Show detailed output of dotnet commands."); + var buildOption = new Option("--build", "-b") + { + Description = "Build the solution after removal." + }; - AddArgument(packageIdArgument); - AddArgument(solutionFileArgument); - AddOption(cleanOption); - AddOption(restoreOption); - AddOption(buildOption); - AddOption(verboseOption); + var verboseOption = new Option("--verbose", "-v") + { + Description = "Show detailed output of dotnet commands." + }; - this.SetHandler((packageId, solutionFile, clean, restore, build, verbose) => + Add(packageIdArgument); + Add(solutionFileArgument); + Add(cleanOption); + Add(restoreOption); + Add(buildOption); + Add(verboseOption); + + SetAction(result => { + var packageId = result.GetValue(packageIdArgument); + var solutionFile = result.GetValue(solutionFileArgument); + var clean = result.GetValue(cleanOption); + var restore = result.GetValue(restoreOption); + var build = result.GetValue(buildOption); + var verbose = result.GetValue(verboseOption); + solutionFile = solutionExplorer.GetOrPromptSolutionFile(solutionFile); var solutionDir = Path.GetDirectoryName(solutionFile ?? string.Empty)!; environment.CurrentDirectory = solutionDir; @@ -65,6 +89,6 @@ IEnvironmentService environment var solutionName = Path.GetFileName(solutionFile); dotnetRunner.RunSequentialCommands(solutionDir, solutionName, verbose, clean, restore, build); - }, packageIdArgument, solutionFileArgument, cleanOption, restoreOption, buildOption, verboseOption); + }); } } diff --git a/NetTools/Commands/StandardizeCommand.cs b/NetTools/Commands/StandardizeCommand.cs index 54d5586..2089e10 100644 --- a/NetTools/Commands/StandardizeCommand.cs +++ b/NetTools/Commands/StandardizeCommand.cs @@ -22,28 +22,48 @@ IEnvironmentService environment "Standardize NuGet package versions in a solution." ) { - var solutionFileArgument = new Argument - ( - "solutionFile", - static () => null, - "The path to the .sln file to discover projects (optional). If omitted, the tool will search for a solution file in the current directory or prompt for selection." - ); + var solutionFileArgument = new Argument("solutionFile") + { + Description = "The path to the .sln file to discover projects (optional). If omitted, the tool will search for a solution file in the current directory or prompt for selection.", + Arity = ArgumentArity.ZeroOrOne + }; + + var cleanOption = new Option("--clean", "-c") + { + Description = "Clean the solution after standardization." + }; + + var restoreOption = new Option("--restore", "-r") + { + Description = "Restore the solution after standardization." + }; - var cleanOption = new Option(["--clean", "-c"], static () => false, "Clean the solution after standardization."); - var restoreOption = new Option(["--restore", "-r"], static () => false, "Restore the solution after standardization."); - var buildOption = new Option(["--build", "-b"], static () => false, "Build the solution after standardization."); - var verboseOption = new Option(["--verbose", "-v"], static () => false, "Show detailed output of dotnet commands."); + var buildOption = new Option("--build", "-b") + { + Description = "Build the solution after standardization." + }; - AddArgument(solutionFileArgument); - AddOption(cleanOption); - AddOption(restoreOption); - AddOption(buildOption); - AddOption(verboseOption); + var verboseOption = new Option("--verbose", "-v") + { + Description = "Show detailed output of dotnet commands." + }; - this.SetHandler + Add(solutionFileArgument); + Add(cleanOption); + Add(restoreOption); + Add(buildOption); + Add(verboseOption); + + SetAction ( - (solutionFile, verbose, clean, restore, build) => + result => { + var solutionFile = result.GetValue(solutionFileArgument); + var verbose = result.GetValue(verboseOption); + var clean = result.GetValue(cleanOption); + var restore = result.GetValue(restoreOption); + var build = result.GetValue(buildOption); + var options = new StandardizeCommandOptions { SolutionFile = solutionExplorer.GetOrPromptSolutionFile(solutionFile), @@ -66,12 +86,6 @@ IEnvironmentService environment return; standardizer.StandardizeVersions(options, [.. selectedProjects]); - }, - solutionFileArgument, - verboseOption, - cleanOption, - restoreOption, - buildOption - ); + }); } } diff --git a/NetTools/Commands/UpdateCommand.cs b/NetTools/Commands/UpdateCommand.cs index 1c7815d..1ae98de 100644 --- a/NetTools/Commands/UpdateCommand.cs +++ b/NetTools/Commands/UpdateCommand.cs @@ -37,42 +37,55 @@ IEnvironmentService environment _dotnetRunner = dotnetRunner; _environment = environment; - var includePrereleaseArgument = new Option - ( - ["--include-prerelease", "-p"], - static () => false, - "If true, includes prerelease versions when checking for updates." - ); + var includePrereleaseArgument = new Option("--include-prerelease", "-p") + { + Description = "If true, includes prerelease versions when checking for updates." + }; - var cleanOption = new Option(["--clean", "-c"], static () => false, "Clean the solution after update."); - var restoreOption = new Option(["--restore", "-r"], static () => false, "Restore the solution after update."); - var buildOption = new Option(["--build", "-b"], static () => false, "Build the solution after update."); - var verboseOption = new Option(["--verbose", "-v"], static () => false, "Show detailed output of dotnet commands."); + var cleanOption = new Option("--clean", "-c") + { + Description = "Clean the solution after update." + }; - var solutionFileArgument = new Argument - ( - "solutionFile", - static () => null, - "The path to the .sln file to discover projects (optional). If omitted, the tool will search for a solution file in the current directory or prompt for selection." - ); + var restoreOption = new Option("--restore", "-r") + { + Description = "Restore the solution after update." + }; - AddArgument(solutionFileArgument); - AddOption(includePrereleaseArgument); - AddOption(cleanOption); - AddOption(restoreOption); - AddOption(buildOption); - AddOption(verboseOption); + var buildOption = new Option("--build", "-b") + { + Description = "Build the solution after update." + }; - this.SetHandler - ( - HandleAsync, - solutionFileArgument, - includePrereleaseArgument, - cleanOption, - restoreOption, - buildOption, - verboseOption - ); + var verboseOption = new Option("--verbose", "-v") + { + Description = "Show detailed output of dotnet commands." + }; + + var solutionFileArgument = new Argument("solutionFile") + { + Description = "The path to the .sln file to discover projects (optional). If omitted, the tool will search for a solution file in the current directory or prompt for selection.", + Arity = ArgumentArity.ZeroOrOne + }; + + Add(solutionFileArgument); + Add(includePrereleaseArgument); + Add(cleanOption); + Add(restoreOption); + Add(buildOption); + Add(verboseOption); + + SetAction(async (result) => + { + var solutionFile = result.GetValue(solutionFileArgument); + var includePrerelease = result.GetValue(includePrereleaseArgument); + var clean = result.GetValue(cleanOption); + var restore = result.GetValue(restoreOption); + var build = result.GetValue(buildOption); + var verbose = result.GetValue(verboseOption); + + await HandleAsync(solutionFile, includePrerelease, clean, restore, build, verbose).ConfigureAwait(false); + }); } /// diff --git a/NetTools/NetTools.csproj b/NetTools/NetTools.csproj index 92c379f..e38d2be 100644 --- a/NetTools/NetTools.csproj +++ b/NetTools/NetTools.csproj @@ -17,7 +17,7 @@ - + diff --git a/NetTools/Program.cs b/NetTools/Program.cs index ec15ed9..17a3f51 100644 --- a/NetTools/Program.cs +++ b/NetTools/Program.cs @@ -1,4 +1,5 @@ -using System.CommandLine; +using System.CommandLine; +using System.CommandLine.Parsing; using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using NetTools; @@ -8,7 +9,7 @@ .BuildServiceProvider() .CreateRootCommand(); -await rootCommand.InvokeAsync(args).ConfigureAwait(false); +await rootCommand.Parse(args).InvokeAsync(); if (Debugger.IsAttached) { From 48cfafe72e71f72979737d7fdd135ec602ac9bb5 Mon Sep 17 00:00:00 2001 From: Douglas Cunha Date: Thu, 26 Jun 2025 13:18:42 -0300 Subject: [PATCH 2/2] chore: update dependencies and refactor code for clarity - Add a global suppressions file to suppress a specific code analysis message for a test command. - Update package references to xunit.runner.visualstudio and Microsoft.NET.Test.Sdk to newer versions. - Refines argument definitions and enforces non-null extraction of package id to improve command robustness. - Refactor conditional statement formatting and add success message for package update. - Update dependency versions for Microsoft.Extensions packages to 9.0.6 in project configuration. - Refactor Program class to include an asynchronous Main method with dependency injection setup and conditional console pause when debugger is attached - Remove unnecessary braces to streamline the code and improve readability. Signed-off-by: Douglas Cunha --- NetTools.Tests/GlobalSuppressions.cs | 8 +++++++ NetTools.Tests/NetTools.Tests.csproj | 4 ++-- NetTools/Commands/RemoveCommand.cs | 5 ++-- NetTools/Commands/UpdateCommand.cs | 7 +++--- NetTools/NetTools.csproj | 4 ++-- NetTools/Program.cs | 33 ++++++++++++++++----------- NetTools/Services/SolutionExplorer.cs | 2 -- 7 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 NetTools.Tests/GlobalSuppressions.cs diff --git a/NetTools.Tests/GlobalSuppressions.cs b/NetTools.Tests/GlobalSuppressions.cs new file mode 100644 index 0000000..e0b472b --- /dev/null +++ b/NetTools.Tests/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Style", "IDE0028:Simplify collection initialization", Justification = "", Scope = "member", Target = "~F:NetTools.Tests.Commands.UpdateCommandTests._rootCommand")] diff --git a/NetTools.Tests/NetTools.Tests.csproj b/NetTools.Tests/NetTools.Tests.csproj index 7aa2bdf..f2e5aff 100644 --- a/NetTools.Tests/NetTools.Tests.csproj +++ b/NetTools.Tests/NetTools.Tests.csproj @@ -18,13 +18,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/NetTools/Commands/RemoveCommand.cs b/NetTools/Commands/RemoveCommand.cs index d1a7f7e..cede4b1 100644 --- a/NetTools/Commands/RemoveCommand.cs +++ b/NetTools/Commands/RemoveCommand.cs @@ -20,7 +20,8 @@ IEnvironmentService environment { var packageIdArgument = new Argument("packageId") { - Description = "The NuGet package id to remove." + Description = "The NuGet package id to remove.", + Arity = ArgumentArity.ExactlyOne }; var solutionFileArgument = new Argument("solutionFile") @@ -58,7 +59,7 @@ IEnvironmentService environment SetAction(result => { - var packageId = result.GetValue(packageIdArgument); + var packageId = result.GetValue(packageIdArgument)!; var solutionFile = result.GetValue(solutionFileArgument); var clean = result.GetValue(cleanOption); var restore = result.GetValue(restoreOption); diff --git a/NetTools/Commands/UpdateCommand.cs b/NetTools/Commands/UpdateCommand.cs index 1ae98de..d9737b8 100644 --- a/NetTools/Commands/UpdateCommand.cs +++ b/NetTools/Commands/UpdateCommand.cs @@ -168,7 +168,7 @@ private async Task HandleAsync _csprojHelpers.UpdatePackagesInProjects(projectPackages, latestVersions, selected); - if (_dotnetRunner.RunSequentialCommands + if (_dotnetRunner.RunSequentialCommands ( Path.GetDirectoryName(solutionFile)!, Path.GetFileName(solutionFile), @@ -176,9 +176,10 @@ private async Task HandleAsync clean, restore, build - ) - ) + )) + { _console.MarkupLine("[green]Selected packages updated successfully.[/]"); + } return true; } diff --git a/NetTools/NetTools.csproj b/NetTools/NetTools.csproj index e38d2be..58d45b2 100644 --- a/NetTools/NetTools.csproj +++ b/NetTools/NetTools.csproj @@ -13,8 +13,8 @@ win-x64 - - + + diff --git a/NetTools/Program.cs b/NetTools/Program.cs index 17a3f51..d9e925b 100644 --- a/NetTools/Program.cs +++ b/NetTools/Program.cs @@ -1,18 +1,25 @@ -using System.CommandLine; -using System.CommandLine.Parsing; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.DependencyInjection; -using NetTools; -var rootCommand = new ServiceCollection() - .RegisterServices() - .BuildServiceProvider() - .CreateRootCommand(); +namespace NetTools; -await rootCommand.Parse(args).InvokeAsync(); - -if (Debugger.IsAttached) +[ExcludeFromCodeCoverage] +file static class Program { - Console.WriteLine("Press any key to exit..."); - Console.Read(); -} + private static async Task Main(string[] args) + { + var rootCommand = new ServiceCollection() + .RegisterServices() + .BuildServiceProvider() + .CreateRootCommand(); + + await rootCommand.Parse(args).InvokeAsync().ConfigureAwait(false); + + if (Debugger.IsAttached) + { + Console.WriteLine("Press any key to exit..."); + Console.Read(); + } + } +} \ No newline at end of file diff --git a/NetTools/Services/SolutionExplorer.cs b/NetTools/Services/SolutionExplorer.cs index e65fc39..41ff737 100644 --- a/NetTools/Services/SolutionExplorer.cs +++ b/NetTools/Services/SolutionExplorer.cs @@ -116,9 +116,7 @@ private List DiscoverProjectPaths(string solutionFile, Func