From 973021b21451317067b76794ab10853334bd0723 Mon Sep 17 00:00:00 2001 From: jonsequitur Date: Thu, 16 Mar 2017 13:22:08 -0700 Subject: [PATCH] publish, cache, text fixes; rename ForwardAs and introduce ForwardAsMany --- src/dotnet/ArgumentForwardingExtensions.cs | 31 ++++++++------- src/dotnet/CommonOptions.cs | 10 ++--- .../commands/dotnet-add/AddCommandParser.cs | 8 ++-- .../dotnet-build/BuildCommandParser.cs | 2 +- .../dotnet-cache/CacheCommandParser.cs | 38 ++++++++++++------- .../dotnet-clean/CleanCommandParser.cs | 2 +- .../commands/dotnet-pack/PackCommandParser.cs | 2 +- .../dotnet-publish/PublishCommandParser.cs | 6 +-- .../dotnet-restore/RestoreCommandParser.cs | 8 ++-- .../commands/dotnet-test/TestCommandParser.cs | 16 ++++---- .../GivenDotnetListReference.cs | 2 +- .../GivenDotnetCacheInvocation.cs | 1 + .../GivenDotnetSlnList.cs | 2 +- .../GivenDotnetSlnRemove.cs | 3 +- .../ArgumentForwardingExtensionsTests.cs | 4 +- 15 files changed, 72 insertions(+), 63 deletions(-) diff --git a/src/dotnet/ArgumentForwardingExtensions.cs b/src/dotnet/ArgumentForwardingExtensions.cs index ac8aa9c4a..da4a3cdc9 100644 --- a/src/dotnet/ArgumentForwardingExtensions.cs +++ b/src/dotnet/ArgumentForwardingExtensions.cs @@ -13,37 +13,36 @@ namespace Microsoft.DotNet.Cli public static ArgumentsRule ForwardAs( this ArgumentsRule rule, - string template) => - rule.MaterializeAs(o => new ForwardedArgument(template)); + string value) => + rule.MaterializeAs(o => new ForwardedArgument(value)); - public static ArgumentsRule ForwardAs( + public static ArgumentsRule ForwardAsSingle( this ArgumentsRule rule, Func format) => rule.MaterializeAs(o => - new ForwardedArgument(format(o))); + new ForwardedArgument(format(o))); + + public static ArgumentsRule ForwardAsMany( + this ArgumentsRule rule, + Func> format) => + rule.MaterializeAs(o => + new ForwardedArgument(format(o).ToArray())); public static IEnumerable OptionValuesToBeForwarded( this AppliedOption command) => command.AppliedOptions .Select(o => o.Value()) .OfType() - .Select(o => o.ToString()); + .SelectMany(o => o.Values); private class ForwardedArgument { - private readonly string _value; - - public ForwardedArgument(string value) + public ForwardedArgument(params string[] values) { - _value = value; + Values = values; } - public override string ToString() => _value; - - public static explicit operator string(ForwardedArgument argument) - { - return argument.ToString(); - } + public string[] Values { get; } } } -} +} \ No newline at end of file diff --git a/src/dotnet/CommonOptions.cs b/src/dotnet/CommonOptions.cs index f20359963..4dc1dfacf 100644 --- a/src/dotnet/CommonOptions.cs +++ b/src/dotnet/CommonOptions.cs @@ -25,7 +25,7 @@ namespace Microsoft.DotNet.Cli "n", "normal", "d", "detailed", "diag", "diagnostic") - .ForwardAs(o => $"/verbosity:{o.Arguments.Single()}")); + .ForwardAsSingle(o => $"/verbosity:{o.Arguments.Single()}")); public static Option FrameworkOption() => Create.Option( @@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Cli Accept.ExactlyOneArgument() .WithSuggestionsFrom(_ => Suggest.TargetFrameworksFromProjectFile()) .With(name: "FRAMEWORK") - .ForwardAs(o => $"/p:TargetFramework={o.Arguments.Single()}")); + .ForwardAsSingle(o => $"/p:TargetFramework={o.Arguments.Single()}")); public static Option RuntimeOption() => Create.Option( @@ -43,7 +43,7 @@ namespace Microsoft.DotNet.Cli Accept.ExactlyOneArgument() .WithSuggestionsFrom(_ => Suggest.RunTimesFromProjectFile()) .With(name: "RUNTIME_IDENTIFIER") - .ForwardAs(o => $"/p:RuntimeIdentifier={o.Arguments.Single()}")); + .ForwardAsSingle(o => $"/p:RuntimeIdentifier={o.Arguments.Single()}")); public static Option ConfigurationOption() => Create.Option( @@ -52,7 +52,7 @@ namespace Microsoft.DotNet.Cli Accept.ExactlyOneArgument() .With(name: "CONFIGURATION") .WithSuggestionsFrom("DEBUG", "RELEASE") - .ForwardAs(o => $"/p:Configuration={o.Arguments.Single()}")); + .ForwardAsSingle(o => $"/p:Configuration={o.Arguments.Single()}")); public static Option VersionSuffixOption() => Create.Option( @@ -60,7 +60,7 @@ namespace Microsoft.DotNet.Cli "Defines the value for the $(VersionSuffix) property in the project.", Accept.ExactlyOneArgument() .With(name: "VERSION_SUFFIX") - .ForwardAs(o => $"/p:VersionSuffix={o.Arguments.Single()}")); + .ForwardAsSingle(o => $"/p:VersionSuffix={o.Arguments.Single()}")); public static ArgumentsRule DefaultToCurrentDirectory(this ArgumentsRule rule) => rule.With(defaultValue: () => PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory())); diff --git a/src/dotnet/commands/dotnet-add/AddCommandParser.cs b/src/dotnet/commands/dotnet-add/AddCommandParser.cs index fd1dcde1e..ed816ace3 100644 --- a/src/dotnet/commands/dotnet-add/AddCommandParser.cs +++ b/src/dotnet/commands/dotnet-add/AddCommandParser.cs @@ -34,24 +34,24 @@ namespace Microsoft.DotNet.Cli "Version for the package to be added.", Accept.ExactlyOneArgument() .With(name: "VERSION") - .ForwardAs(o => $"--version {o.Arguments.Single()}")), + .ForwardAsSingle(o => $"--version {o.Arguments.Single()}")), Create.Option("-f|--framework", LocalizableStrings.CmdFrameworkDescription, Accept.ExactlyOneArgument() .With(name: "FRAMEWORK") - .ForwardAs(o => $"--framework {o.Arguments.Single()}")), + .ForwardAsSingle(o => $"--framework {o.Arguments.Single()}")), Create.Option("-n|--no-restore ", "Add reference without performing restore preview and compatibility check."), Create.Option("-s|--source", "Use specific NuGet package sources to use during the restore.", Accept.ExactlyOneArgument() .With(name: "SOURCE") - .ForwardAs(o => $"--source {o.Arguments.Single()}")), + .ForwardAsSingle(o => $"--source {o.Arguments.Single()}")), Create.Option("--package-directory", "Restore the packages to this Directory .", Accept.ExactlyOneArgument() .With(name: "PACKAGE_DIRECTORY") - .ForwardAs(o => $"--package-directory {o.Arguments.Single()}"))), + .ForwardAsSingle(o => $"--package-directory {o.Arguments.Single()}"))), Create.Command( "reference", Tools.Add.ProjectToProjectReference.LocalizableStrings.AppFullName, diff --git a/src/dotnet/commands/dotnet-build/BuildCommandParser.cs b/src/dotnet/commands/dotnet-build/BuildCommandParser.cs index b1a492318..e75d179e6 100644 --- a/src/dotnet/commands/dotnet-build/BuildCommandParser.cs +++ b/src/dotnet/commands/dotnet-build/BuildCommandParser.cs @@ -23,7 +23,7 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.OutputOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.OutputOptionName) - .ForwardAs(o => $"/p:OutputPath={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:OutputPath={o.Arguments.Single()}")), CommonOptions.FrameworkOption(), CommonOptions.RuntimeOption(), CommonOptions.ConfigurationOption(), diff --git a/src/dotnet/commands/dotnet-cache/CacheCommandParser.cs b/src/dotnet/commands/dotnet-cache/CacheCommandParser.cs index 1c5985152..382795680 100644 --- a/src/dotnet/commands/dotnet-cache/CacheCommandParser.cs +++ b/src/dotnet/commands/dotnet-cache/CacheCommandParser.cs @@ -19,24 +19,34 @@ namespace Microsoft.DotNet.Cli "-e|--entries", LocalizableStrings.ProjectEntryDescription, Accept.OneOrMoreArguments() - .With(name: LocalizableStrings.ProjectEntries) - .ForwardAs(o => - { - var materializedString = $"{o.Arguments.First()}"; + .With(name: LocalizableStrings.ProjectEntries) + .ForwardAsMany(o => + { + var materializedString = $"{o.Arguments.First()}"; - if (o.Arguments.Count() == 1) return materializedString; - - var additionalProjects = string.Join("%3B", o.Arguments.Skip(1)); - - return $"{materializedString} /p:AdditionalProjects={additionalProjects}"; - })), + if (o.Arguments.Count == 1) + { + return new[] + { + materializedString + }; + } + else + { + return new[] + { + materializedString, + $"/p:AdditionalProjects={string.Join("%3B", o.Arguments.Skip(1))}" + }; + } + })), CommonOptions.FrameworkOption(), Create.Option( "--framework-version", LocalizableStrings.FrameworkVersionOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.FrameworkVersionOption) - .ForwardAs(o => $"/p:FX_Version={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:FX_Version={o.Arguments.Single()}")), CommonOptions.RuntimeOption(), CommonOptions.ConfigurationOption(), Create.Option( @@ -44,18 +54,18 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.OutputOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.OutputOption) - .ForwardAs(o => $"/p:ComposeDir={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:ComposeDir={o.Arguments.Single()}")), Create.Option( "-w|--working-dir", LocalizableStrings.IntermediateWorkingDirOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.IntermediateWorkingDirOption) - .ForwardAs(o => $"/p:ComposeWorkingDir={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:ComposeWorkingDir={o.Arguments.Single()}")), Create.Option( "--preserve-working-dir", LocalizableStrings.PreserveIntermediateWorkingDirOptionDescription, Accept.NoArguments() - .ForwardAs(o => $"/p:PreserveComposeWorkingDir=true")), + .ForwardAsSingle(o => $"/p:PreserveComposeWorkingDir=true")), Create.Option( "--skip-optimization", LocalizableStrings.SkipOptimizationOptionDescription, diff --git a/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs b/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs index d157d9d52..3a78ebfa9 100644 --- a/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs +++ b/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs @@ -19,7 +19,7 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.CmdOutputDirDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdOutputDir) - .ForwardAs(o => $"/p:OutputPath={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:OutputPath={o.Arguments.Single()}")), CommonOptions.FrameworkOption(), CommonOptions.ConfigurationOption(), CommonOptions.VerbosityOption()); diff --git a/src/dotnet/commands/dotnet-pack/PackCommandParser.cs b/src/dotnet/commands/dotnet-pack/PackCommandParser.cs index d470d0127..56be1ee3d 100644 --- a/src/dotnet/commands/dotnet-pack/PackCommandParser.cs +++ b/src/dotnet/commands/dotnet-pack/PackCommandParser.cs @@ -20,7 +20,7 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.CmdOutputDirDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdOutputDir) - .ForwardAs(o => $"/p:PackageOutputPath={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:PackageOutputPath={o.Arguments.Single()}")), Create.Option( "--no-build", LocalizableStrings.CmdNoBuildOptionDescription, diff --git a/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs b/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs index c6ca8361f..0372ae89f 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs @@ -22,15 +22,15 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.OutputOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.OutputOption) - .ForwardAs(o => $"/p:PublishDir={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:PublishDir={o.Arguments.Single()}")), CommonOptions.ConfigurationOption(), CommonOptions.VersionSuffixOption(), Create.Option( "--filter", LocalizableStrings.FilterProjOptionDescription, - Accept.ExactlyOneArgument() + Accept.OneOrMoreArguments() .With(name: LocalizableStrings.FilterProjOption) - .ForwardAs(o => $"/p:FilterProjectFiles={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:FilterProjectFiles={string.Join("%3B", o.Arguments)}")), CommonOptions.VerbosityOption()); } } \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs b/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs index 34a98764c..f42acad6b 100644 --- a/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs +++ b/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs @@ -20,20 +20,20 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.CmdSourceOptionDescription, Accept.OneOrMoreArguments() .With(name: LocalizableStrings.CmdSourceOption) - .ForwardAs(o => $"/p:RestoreSources={string.Join("%3B", o.Arguments)}")), + .ForwardAsSingle(o => $"/p:RestoreSources={string.Join("%3B", o.Arguments)}")), Create.Option( "-r|--runtime", LocalizableStrings.CmdRuntimeOptionDescription, Accept.OneOrMoreArguments() .WithSuggestionsFrom(_ => Suggest.RunTimesFromProjectFile()) .With(name: LocalizableStrings.CmdRuntimeOption) - .ForwardAs(o => $"/p:RuntimeIdentifiers={string.Join("%3B", o.Arguments)}")), + .ForwardAsSingle(o => $"/p:RuntimeIdentifiers={string.Join("%3B", o.Arguments)}")), Create.Option( "--packages", LocalizableStrings.CmdPackagesOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdPackagesOption) - .ForwardAs(o => $"/p:RestorePackagesPath={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:RestorePackagesPath={o.Arguments.Single()}")), Create.Option( "--disable-parallel", LocalizableStrings.CmdDisableParallelOptionDescription, @@ -44,7 +44,7 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.CmdConfigFileOptionDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdConfigFileOption) - .ForwardAs(o => $"/p:RestoreConfigFile={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:RestoreConfigFile={o.Arguments.Single()}")), Create.Option( "--no-cache", LocalizableStrings.CmdNoCacheOptionDescription, diff --git a/src/dotnet/commands/dotnet-test/TestCommandParser.cs b/src/dotnet/commands/dotnet-test/TestCommandParser.cs index b885acf3b..029734404 100644 --- a/src/dotnet/commands/dotnet-test/TestCommandParser.cs +++ b/src/dotnet/commands/dotnet-test/TestCommandParser.cs @@ -20,30 +20,30 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.CmdSettingsDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdSettingsFile) - .ForwardAs(o => $"/p:VSTestSetting={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:VSTestSetting={o.Arguments.Single()}")), Create.Option( "-t|--list-tests", LocalizableStrings.CmdListTestsDescription, Accept.NoArguments() - .ForwardAs(o => "/p:VSTestListTests=true")), + .ForwardAsSingle(o => "/p:VSTestListTests=true")), Create.Option( "--filter", LocalizableStrings.CmdTestCaseFilterDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdTestCaseFilterExpression) - .ForwardAs(o => $"/p:VSTestTestCaseFilter={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:VSTestTestCaseFilter={o.Arguments.Single()}")), Create.Option( "-a|--test-adapter-path", LocalizableStrings.CmdTestAdapterPathDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdTestAdapterPath) - .ForwardAs(o => $"/p:VSTestTestAdapterPath={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:VSTestTestAdapterPath={o.Arguments.Single()}")), Create.Option( "-l|--logger", LocalizableStrings.CmdLoggerDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdLoggerOption) - .ForwardAs(o => + .ForwardAsSingle(o => { var loggersString = string.Join(";", GetSemiColonEscapedArgs(o.Arguments)); @@ -56,18 +56,18 @@ namespace Microsoft.DotNet.Cli LocalizableStrings.CmdOutputDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdOutputDir) - .ForwardAs(o => $"/p:OutputPath={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:OutputPath={o.Arguments.Single()}")), Create.Option( "-d|--diag", LocalizableStrings.CmdPathTologFileDescription, Accept.ExactlyOneArgument() .With(name: LocalizableStrings.CmdPathToLogFile) - .ForwardAs(o => $"/p:VSTestDiag={o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/p:VSTestDiag={o.Arguments.Single()}")), Create.Option( "--no-build", LocalizableStrings.CmdNoBuildDescription, Accept.NoArguments() - .ForwardAs(o => "/p:VSTestNoBuild=true")), + .ForwardAsSingle(o => "/p:VSTestNoBuild=true")), CommonOptions.VerbosityOption()); private static string GetSemiColonEsacpedstring(string arg) diff --git a/test/dotnet-list-reference.Tests/GivenDotnetListReference.cs b/test/dotnet-list-reference.Tests/GivenDotnetListReference.cs index a4337273b..f82c98700 100644 --- a/test/dotnet-list-reference.Tests/GivenDotnetListReference.cs +++ b/test/dotnet-list-reference.Tests/GivenDotnetListReference.cs @@ -58,7 +58,7 @@ Options: .Execute("proj.csproj"); cmd.ExitCode.Should().NotBe(0); cmd.StdErr.Should().BeVisuallyEquivalentTo( - "Unrecognized command or argument 'one'\r\nUnrecognized command or argument 'two'\r\nUnrecognized command or argument 'three'"); + "Unrecognized command or argument 'two'\r\nUnrecognized command or argument 'three'"); } [Theory] diff --git a/test/dotnet-msbuild.Tests/GivenDotnetCacheInvocation.cs b/test/dotnet-msbuild.Tests/GivenDotnetCacheInvocation.cs index a65a6793d..29ee67a13 100644 --- a/test/dotnet-msbuild.Tests/GivenDotnetCacheInvocation.cs +++ b/test/dotnet-msbuild.Tests/GivenDotnetCacheInvocation.cs @@ -31,6 +31,7 @@ namespace Microsoft.DotNet.Cli.MSBuild.Tests [InlineData(new string[] { "--framework", "" }, @"/p:TargetFramework=")] [InlineData(new string[] { "-r", "" }, @"/p:RuntimeIdentifier=")] [InlineData(new string[] { "--runtime", "" }, @"/p:RuntimeIdentifier=")] + [InlineData(new string[] { "--entries", "one.xml", "--entries", "two.xml", "--entries", "three.xml" }, @"/p:AdditionalProjects=one.xml%3Btwo.xml%3Bthree.xml")] public void MsbuildInvocationIsCorrect(string[] args, string expectedAdditionalArgs) { args = ArgsPrefix.Concat(args).ToArray(); diff --git a/test/dotnet-sln-list.Tests/GivenDotnetSlnList.cs b/test/dotnet-sln-list.Tests/GivenDotnetSlnList.cs index f8f785071..abaa51cea 100644 --- a/test/dotnet-sln-list.Tests/GivenDotnetSlnList.cs +++ b/test/dotnet-sln-list.Tests/GivenDotnetSlnList.cs @@ -52,7 +52,7 @@ Options: var cmd = new DotnetCommand() .ExecuteWithCapturedOutput("sln one.sln two.sln three.sln list"); cmd.Should().Fail(); - cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'"); + cmd.StdErr.Should().BeVisuallyEquivalentTo("Unrecognized command or argument 'two.sln'\r\nUnrecognized command or argument 'three.sln'"); } [Theory] diff --git a/test/dotnet-sln-remove.Tests/GivenDotnetSlnRemove.cs b/test/dotnet-sln-remove.Tests/GivenDotnetSlnRemove.cs index bc3594607..c0e51ff8a 100644 --- a/test/dotnet-sln-remove.Tests/GivenDotnetSlnRemove.cs +++ b/test/dotnet-sln-remove.Tests/GivenDotnetSlnRemove.cs @@ -175,8 +175,7 @@ EndGlobal var cmd = new DotnetCommand() .ExecuteWithCapturedOutput("sln one.sln two.sln three.sln remove"); cmd.Should().Fail(); - cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'"); - cmd.StdOut.Should().Be("Specify --help for a list of available options and commands."); + cmd.StdErr.Should().BeVisuallyEquivalentTo("Unrecognized command or argument 'two.sln'\r\nUnrecognized command or argument 'three.sln'\r\nYou must specify at least one project to remove."); } [Theory] diff --git a/test/dotnet.Tests/ParserTests/ArgumentForwardingExtensionsTests.cs b/test/dotnet.Tests/ParserTests/ArgumentForwardingExtensionsTests.cs index 99fe3fb88..c445c9812 100644 --- a/test/dotnet.Tests/ParserTests/ArgumentForwardingExtensionsTests.cs +++ b/test/dotnet.Tests/ParserTests/ArgumentForwardingExtensionsTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.DotNet.Tests.ParserTests var command = Command("the-command", "", Option("-o|--one", "", ZeroOrOneArgument() - .ForwardAs(o => $"/i:{o.Arguments.Single()}")), + .ForwardAsSingle(o => $"/i:{o.Arguments.Single()}")), Option("-t|--two", "", NoArguments() .ForwardAs("/s:true"))); @@ -38,7 +38,7 @@ namespace Microsoft.DotNet.Tests.ParserTests var command = Command("the-command", "", Option("-x", "", ZeroOrMoreArguments() - .ForwardAs(o => $"/x:{string.Join("&", o.Arguments)}"))); + .ForwardAsSingle(o => $"/x:{string.Join("&", o.Arguments)}"))); var result = command.Parse("the-command -x one -x two");