From 0da7e641f17a8f6459ed02ac4c6304829d244456 Mon Sep 17 00:00:00 2001 From: Frank Ray <52075808+FrankRay78@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:34:04 +0100 Subject: [PATCH] Within Cake.Commands.DefaultCommand.Execute(...), explicitly create the CakeArguments from CommandContext.Remaining, adding in the DefaultCommandSettings.Recompile flag, if necessary. Follows the same pattern already established in Cake.Frosting.Internal.DefaultCommand --- src/Cake.Cli/Cake.Cli.csproj | 4 +-- .../Internal/Commands/DefaultCommand.cs | 2 +- .../Fixtures/BuildFeatureFixture.cs | 11 ++++-- src/Cake.Tests/Unit/ProgramTests.cs | 8 ++--- .../Utilities/TestContainerConfigurator.cs | 4 +-- src/Cake/Commands/DefaultCommand.cs | 35 +++++++++++++++++-- .../Bootstrapping/BootstrapFeature.cs | 4 +-- src/Cake/Features/Building/BuildFeature.cs | 6 ++-- src/Cake/Features/CakeFeature.cs | 6 ++-- .../Infrastructure/ContainerConfigurator.cs | 4 +-- .../Infrastructure/IContainerConfigurator.cs | 4 +-- 11 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/Cake.Cli/Cake.Cli.csproj b/src/Cake.Cli/Cake.Cli.csproj index 48b5859f13..64a6fd31e2 100644 --- a/src/Cake.Cli/Cake.Cli.csproj +++ b/src/Cake.Cli/Cake.Cli.csproj @@ -19,7 +19,7 @@ - - + + \ No newline at end of file diff --git a/src/Cake.Frosting/Internal/Commands/DefaultCommand.cs b/src/Cake.Frosting/Internal/Commands/DefaultCommand.cs index cce55ad5de..6a172970a2 100644 --- a/src/Cake.Frosting/Internal/Commands/DefaultCommand.cs +++ b/src/Cake.Frosting/Internal/Commands/DefaultCommand.cs @@ -82,6 +82,7 @@ public override int Execute(CommandContext context, DefaultCommandSettings setti private static CakeArguments CreateCakeArguments(IRemainingArguments remainingArguments, DefaultCommandSettings settings) { var arguments = new Dictionary>(StringComparer.OrdinalIgnoreCase); + // Keep the actual remaining arguments in the cake arguments foreach (var group in remainingArguments.Parsed) { @@ -98,7 +99,6 @@ private static CakeArguments CreateCakeArguments(IRemainingArguments remainingAr { arguments[targetArgumentName] = new List(); } - foreach (var target in settings.Targets) { arguments[targetArgumentName].Add(target); diff --git a/src/Cake.Tests/Fixtures/BuildFeatureFixture.cs b/src/Cake.Tests/Fixtures/BuildFeatureFixture.cs index 4c28658bc1..a17c879381 100644 --- a/src/Cake.Tests/Fixtures/BuildFeatureFixture.cs +++ b/src/Cake.Tests/Fixtures/BuildFeatureFixture.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using System.Text; using Cake.Core; using Cake.Core.Composition; @@ -63,7 +65,10 @@ public BuildFeatureFixture( public BuildFeatureFixtureResult Run(BuildFeatureSettings settings, IDictionary arguments = null) { - var remaining = new FakeRemainingArguments(arguments); + var parsed = (arguments ?? new Dictionary()) + .ToLookup(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase); + + var remaining = new CakeArguments(parsed); var exitCode = ((IBuildFeature)this).Run(remaining, settings); return new BuildFeatureFixtureResult @@ -88,7 +93,7 @@ private string GetDefaultScriptContent() return builder.ToString(); } - int IBuildFeature.Run(IRemainingArguments arguments, BuildFeatureSettings settings) + int IBuildFeature.Run(ICakeArguments arguments, BuildFeatureSettings settings) { var feature = new BuildFeature(FileSystem, Environment, Bootstrapper, ModuleSearcher, Log); return feature.Run(arguments, settings); diff --git a/src/Cake.Tests/Unit/ProgramTests.cs b/src/Cake.Tests/Unit/ProgramTests.cs index 34ceaf2dc1..704bf94cd0 100644 --- a/src/Cake.Tests/Unit/ProgramTests.cs +++ b/src/Cake.Tests/Unit/ProgramTests.cs @@ -27,7 +27,7 @@ public async Task Should_Use_Default_Parameters_By_Default() // Then feature.Received(1).Run( - Arg.Any(), + Arg.Any(), Arg.Is(settings => settings.BuildHostKind == BuildHostKind.Build && settings.Debug == false && @@ -53,7 +53,7 @@ public async Task The_DryRun_Option_Should_Perform_A_Dry_Run_Of_Script(params st // Then feature.Received(1).Run( - Arg.Any(), + Arg.Any(), Arg.Is(settings => settings.BuildHostKind == BuildHostKind.DryRun)); } @@ -73,7 +73,7 @@ public async Task The_Tree_Option_Should_Show_The_Script_Tree(params string[] ar // Then feature.Received(1).Run( - Arg.Any(), + Arg.Any(), Arg.Is(settings => settings.BuildHostKind == BuildHostKind.Tree)); } @@ -93,7 +93,7 @@ public async Task The_Description_Option_Should_Show_Script_Descriptions(params // Then feature.Received(1).Run( - Arg.Any(), + Arg.Any(), Arg.Is(settings => settings.BuildHostKind == BuildHostKind.Description)); } diff --git a/src/Cake.Tests/Utilities/TestContainerConfigurator.cs b/src/Cake.Tests/Utilities/TestContainerConfigurator.cs index 9c4dcfd5ea..8e419295d0 100644 --- a/src/Cake.Tests/Utilities/TestContainerConfigurator.cs +++ b/src/Cake.Tests/Utilities/TestContainerConfigurator.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; +using Cake.Core; using Cake.Core.Composition; using Cake.Core.Configuration; using Cake.Infrastructure; -using Spectre.Console.Cli; namespace Cake.Tests.Fakes { @@ -21,7 +21,7 @@ public TestContainerConfigurator() public void Configure( ICakeContainerRegistrar registrar, ICakeConfiguration configuration, - IRemainingArguments arguments) + ICakeArguments arguments) { _decorated.Configure(registrar, configuration, arguments); diff --git a/src/Cake/Commands/DefaultCommand.cs b/src/Cake/Commands/DefaultCommand.cs index eafcfa72cf..9b860e4c38 100644 --- a/src/Cake/Commands/DefaultCommand.cs +++ b/src/Cake/Commands/DefaultCommand.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.Linq; using Cake.Cli; using Cake.Core; @@ -69,8 +70,10 @@ public override int Execute(CommandContext context, DefaultCommandSettings setti } } + var arguments = CreateCakeArguments(context.Remaining, settings); + // Run the build feature. - return _builder.Run(context.Remaining, new BuildFeatureSettings(host) + return _builder.Run(arguments, new BuildFeatureSettings(host) { Script = settings.Script, Verbosity = settings.Verbosity, @@ -110,11 +113,39 @@ private int PerformBootstrapping(CommandContext context, DefaultCommandSettings return 0; } - return _bootstrapper.Run(context.Remaining, new BootstrapFeatureSettings + var arguments = CreateCakeArguments(context.Remaining, settings); + + return _bootstrapper.Run(arguments, new BootstrapFeatureSettings { Script = settings.Script, Verbosity = settings.Verbosity }); } + + private static CakeArguments CreateCakeArguments(IRemainingArguments remainingArguments, DefaultCommandSettings settings) + { + var arguments = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + // Keep the actual remaining arguments in the cake arguments + foreach (var group in remainingArguments.Parsed) + { + arguments[group.Key] = new List(); + foreach (var argument in group) + { + arguments[group.Key].Add(argument); + } + } + + // Fixes #4157, We have to add arguments manually which are defined within the DefaultCommandSettings type. Those are not considered "as remaining" because they could be parsed + const string recompileArgumentName = Infrastructure.Constants.Cache.InvalidateScriptCache; + if (settings.Recompile && !arguments.ContainsKey(recompileArgumentName)) + { + arguments[recompileArgumentName] = new List(); + arguments[recompileArgumentName].Add(true.ToString()); + } + + var argumentLookUp = arguments.SelectMany(a => a.Value, Tuple.Create).ToLookup(a => a.Item1.Key, a => a.Item2); + return new CakeArguments(argumentLookUp); + } } } diff --git a/src/Cake/Features/Bootstrapping/BootstrapFeature.cs b/src/Cake/Features/Bootstrapping/BootstrapFeature.cs index c3f355b94c..4c1b666c7b 100644 --- a/src/Cake/Features/Bootstrapping/BootstrapFeature.cs +++ b/src/Cake/Features/Bootstrapping/BootstrapFeature.cs @@ -17,7 +17,7 @@ namespace Cake.Features.Bootstrapping { public interface IBootstrapFeature { - int Run(IRemainingArguments arguments, BootstrapFeatureSettings settings); + int Run(ICakeArguments arguments, BootstrapFeatureSettings settings); } public sealed class BootstrapFeature : Feature, IBootstrapFeature @@ -32,7 +32,7 @@ public BootstrapFeature( _environment = environment; } - public int Run(IRemainingArguments arguments, BootstrapFeatureSettings settings) + public int Run(ICakeArguments arguments, BootstrapFeatureSettings settings) { // Fix the script path. settings.Script = settings.Script ?? new FilePath("build.cake"); diff --git a/src/Cake/Features/Building/BuildFeature.cs b/src/Cake/Features/Building/BuildFeature.cs index 1dd9b82fc6..4a8fa4ec40 100644 --- a/src/Cake/Features/Building/BuildFeature.cs +++ b/src/Cake/Features/Building/BuildFeature.cs @@ -21,7 +21,7 @@ namespace Cake.Features.Building { public interface IBuildFeature { - int Run(IRemainingArguments arguments, BuildFeatureSettings settings); + int Run(ICakeArguments arguments, BuildFeatureSettings settings); } public sealed class BuildFeature : Feature, IBuildFeature @@ -42,7 +42,7 @@ public BuildFeature( _log = log; } - public int Run(IRemainingArguments arguments, BuildFeatureSettings settings) + public int Run(ICakeArguments arguments, BuildFeatureSettings settings) { using (new ScriptAssemblyResolver(_environment, _log)) { @@ -50,7 +50,7 @@ public int Run(IRemainingArguments arguments, BuildFeatureSettings settings) } } - private int RunCore(IRemainingArguments arguments, BuildFeatureSettings settings) + private int RunCore(ICakeArguments arguments, BuildFeatureSettings settings) { // Fix the script path. settings.Script = settings.Script ?? new FilePath("build.cake"); diff --git a/src/Cake/Features/CakeFeature.cs b/src/Cake/Features/CakeFeature.cs index c9eee80edd..3d47f8bc88 100644 --- a/src/Cake/Features/CakeFeature.cs +++ b/src/Cake/Features/CakeFeature.cs @@ -33,7 +33,7 @@ public Feature( protected IContainer CreateScope( ICakeConfiguration configuration, - IRemainingArguments arguments, + ICakeArguments arguments, Action action = null) { var registrar = new AutofacTypeRegistrar(new ContainerBuilder()); @@ -45,10 +45,10 @@ protected IContainer CreateScope( } protected ICakeConfiguration ReadConfiguration( - IRemainingArguments remaining, DirectoryPath root) + ICakeArguments arguments, DirectoryPath root) { var provider = new CakeConfigurationProvider(_fileSystem, _environment); - var args = remaining.Parsed.ToDictionary(x => x.Key, x => x.FirstOrDefault() ?? string.Empty); + var args = arguments.GetArguments().ToDictionary(x => x.Key, x => x.Value?.FirstOrDefault() ?? string.Empty); return provider.CreateConfiguration(root, args); } diff --git a/src/Cake/Infrastructure/ContainerConfigurator.cs b/src/Cake/Infrastructure/ContainerConfigurator.cs index e817a84cff..f2c4f59d4e 100644 --- a/src/Cake/Infrastructure/ContainerConfigurator.cs +++ b/src/Cake/Infrastructure/ContainerConfigurator.cs @@ -24,10 +24,10 @@ public sealed class ContainerConfigurator : IContainerConfigurator public void Configure( ICakeContainerRegistrar registrar, ICakeConfiguration configuration, - IRemainingArguments arguments) + ICakeArguments arguments) { // Arguments - registrar.RegisterInstance(new CakeArguments(arguments.Parsed)).AsSelf().As(); + registrar.RegisterInstance(arguments).AsSelf().As(); // Scripting registrar.RegisterType().As().Singleton(); diff --git a/src/Cake/Infrastructure/IContainerConfigurator.cs b/src/Cake/Infrastructure/IContainerConfigurator.cs index 3548c7bfec..41e5a07ef1 100644 --- a/src/Cake/Infrastructure/IContainerConfigurator.cs +++ b/src/Cake/Infrastructure/IContainerConfigurator.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Core; using Cake.Core.Composition; using Cake.Core.Configuration; -using Spectre.Console.Cli; namespace Cake.Infrastructure { @@ -17,6 +17,6 @@ public interface IContainerConfigurator void Configure( ICakeContainerRegistrar registrar, ICakeConfiguration configuration, - IRemainingArguments arguments); + ICakeArguments arguments); } }