Fix 4508: CLI verbs that call into msbuild should control their output (#4719)

* Fix 4508: CLI verbs that call into msbuild should control their output

* fix failing tests + tiny bufix in dotnet test
This commit is contained in:
Krzysztof Wicher 2016-11-15 11:56:39 -08:00 committed by GitHub
parent 43df9a170d
commit 7a3bc96f75
11 changed files with 128 additions and 5 deletions

View file

@ -2,15 +2,15 @@
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SayHello"> <Target Name="SayHello">
<Message Text="Hello, from MSBuild!" /> <Message Importance="high" Text="Hello, from MSBuild!" />
</Target> </Target>
<Target Name="SayGoodbye"> <Target Name="SayGoodbye">
<Message Text="Goodbye, from MSBuild. :'(" /> <Message Importance="high" Text="Goodbye, from MSBuild. :'(" />
</Target> </Target>
<Target Name="SayThis"> <Target Name="SayThis">
<Message Text="You want me to say '$(This)'" /> <Message Importance="high" Text="You want me to say '$(This)'" />
</Target> </Target>
</Project> </Project>

View file

@ -13,6 +13,7 @@
<Target Name="Publish" <Target Name="Publish"
DependsOnTargets="Validate" /> DependsOnTargets="Validate" />
<Target Name="Restore" <Target Name="Restore"
DependsOnTargets="Validate" /> DependsOnTargets="Validate" />
@ -28,5 +29,9 @@
<Error Condition=" '$(CscToolExe)' == '' " <Error Condition=" '$(CscToolExe)' == '' "
Text="Expect CscToolExe to be set, but it is not." /> Text="Expect CscToolExe to be set, but it is not." />
<Message Importance="low" Text="Message with low importance" />
<Message Importance="normal" Text="Message with normal importance" />
<Message Importance="high" Text="Message with high importance" />
</Target> </Target>
</Project> </Project>

View file

@ -36,6 +36,7 @@ namespace Microsoft.DotNet.Tools.Build
CommandOption noIncrementalOption = app.Option("--no-incremental", "Set this flag to turn off incremental build", CommandOptionType.NoValue); CommandOption noIncrementalOption = app.Option("--no-incremental", "Set this flag to turn off incremental build", CommandOptionType.NoValue);
CommandOption noDependenciesOption = app.Option("--no-dependencies", "Set this flag to ignore project to project references and only build the root project", CommandOptionType.NoValue); CommandOption noDependenciesOption = app.Option("--no-dependencies", "Set this flag to ignore project to project references and only build the root project", CommandOptionType.NoValue);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(app);
app.OnExecute(() => app.OnExecute(() =>
{ {
@ -85,6 +86,11 @@ namespace Microsoft.DotNet.Tools.Build
msbuildArgs.Add("/p:BuildProjectReferences=false"); msbuildArgs.Add("/p:BuildProjectReferences=false");
} }
if (verbosityOption.HasValue())
{
msbuildArgs.Add($"/verbosity:{verbosityOption.Value()}");
}
msbuildArgs.AddRange(app.RemainingArguments); msbuildArgs.AddRange(app.RemainingArguments);
return new MSBuildForwardingApp(msbuildArgs).Execute(); return new MSBuildForwardingApp(msbuildArgs).Execute();

View file

@ -31,6 +31,7 @@ namespace Microsoft.DotNet.Tools.Clean
CommandOption outputOption = app.Option("-o|--output <OUTPUT_DIR>", "Directory in which the build outputs have been placed", CommandOptionType.SingleValue); CommandOption outputOption = app.Option("-o|--output <OUTPUT_DIR>", "Directory in which the build outputs have been placed", CommandOptionType.SingleValue);
CommandOption frameworkOption = app.Option("-f|--framework <FRAMEWORK>", "Clean a specific framework", CommandOptionType.SingleValue); CommandOption frameworkOption = app.Option("-f|--framework <FRAMEWORK>", "Clean a specific framework", CommandOptionType.SingleValue);
CommandOption configurationOption = app.Option("-c|--configuration <CONFIGURATION>", "Clean a specific configuration", CommandOptionType.SingleValue); CommandOption configurationOption = app.Option("-c|--configuration <CONFIGURATION>", "Clean a specific configuration", CommandOptionType.SingleValue);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(app);
app.OnExecute(() => app.OnExecute(() =>
{ {
@ -58,6 +59,11 @@ namespace Microsoft.DotNet.Tools.Clean
msbuildArgs.Add($"/p:Configuration={configurationOption.Value()}"); msbuildArgs.Add($"/p:Configuration={configurationOption.Value()}");
} }
if (verbosityOption.HasValue())
{
msbuildArgs.Add($"/verbosity:{verbosityOption.Value()}");
}
msbuildArgs.AddRange(app.RemainingArguments); msbuildArgs.AddRange(app.RemainingArguments);
return new MSBuildForwardingApp(msbuildArgs).Execute(); return new MSBuildForwardingApp(msbuildArgs).Execute();

View file

@ -8,6 +8,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
namespace Microsoft.DotNet.Tools.MSBuild namespace Microsoft.DotNet.Tools.MSBuild
{ {
@ -27,7 +28,7 @@ namespace Microsoft.DotNet.Tools.MSBuild
}; };
private readonly IEnumerable<string> _msbuildRequiredParameters = private readonly IEnumerable<string> _msbuildRequiredParameters =
new List<string> { "/m" }; new List<string> { "/m", "/v:m" };
public MSBuildForwardingApp(IEnumerable<string> argsToForward) public MSBuildForwardingApp(IEnumerable<string> argsToForward)
{ {
@ -68,6 +69,11 @@ namespace Microsoft.DotNet.Tools.MSBuild
} }
} }
internal static CommandOption AddVerbosityOption(CommandLineApplication app)
{
return app.Option("-v|--verbosity", "Set the verbosity level of the command. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]", CommandOptionType.SingleValue);
}
private static string GetMSBuildExePath() private static string GetMSBuildExePath()
{ {
return Path.Combine( return Path.Combine(

View file

@ -49,6 +49,7 @@ namespace Microsoft.DotNet.Tools.Pack
var argRoot = cmd.Argument("<PROJECT>", var argRoot = cmd.Argument("<PROJECT>",
"The project to pack, defaults to the project file in the current directory. Can be a path to any project file", "The project to pack, defaults to the project file in the current directory. Can be a path to any project file",
multipleValues:true); multipleValues:true);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(cmd);
cmd.OnExecute(() => cmd.OnExecute(() =>
{ {
@ -92,6 +93,11 @@ namespace Microsoft.DotNet.Tools.Pack
msbuildArgs.Add($"/p:Serviceable=true"); msbuildArgs.Add($"/p:Serviceable=true");
} }
if (verbosityOption.HasValue())
{
msbuildArgs.Add($"/verbosity:{verbosityOption.Value()}");
}
msbuildArgs.AddRange(argRoot.Values); msbuildArgs.AddRange(argRoot.Values);
msbuildArgs.AddRange(cmd.RemainingArguments); msbuildArgs.AddRange(cmd.RemainingArguments);

View file

@ -3,6 +3,7 @@
using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.MSBuild;
namespace Microsoft.DotNet.Tools.Publish namespace Microsoft.DotNet.Tools.Publish
{ {
@ -43,6 +44,7 @@ namespace Microsoft.DotNet.Tools.Publish
CommandOption versionSuffixOption = app.Option( CommandOption versionSuffixOption = app.Option(
"--version-suffix <VERSION_SUFFIX>", "Defines the value for the $(VersionSuffix) property in the project", "--version-suffix <VERSION_SUFFIX>", "Defines the value for the $(VersionSuffix) property in the project",
CommandOptionType.SingleValue); CommandOptionType.SingleValue);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(app);
app.OnExecute(() => app.OnExecute(() =>
{ {
@ -54,6 +56,7 @@ namespace Microsoft.DotNet.Tools.Publish
publish.OutputPath = outputOption.Value(); publish.OutputPath = outputOption.Value();
publish.Configuration = configurationOption.Value(); publish.Configuration = configurationOption.Value();
publish.VersionSuffix = versionSuffixOption.Value(); publish.VersionSuffix = versionSuffixOption.Value();
publish.Verbosity = verbosityOption.Value();
publish.ExtraMSBuildArguments = app.RemainingArguments; publish.ExtraMSBuildArguments = app.RemainingArguments;
return publish.Execute(); return publish.Execute();

View file

@ -16,6 +16,7 @@ namespace Microsoft.DotNet.Tools.Publish
public string OutputPath { get; set; } public string OutputPath { get; set; }
public string Configuration { get; set; } public string Configuration { get; set; }
public string VersionSuffix { get; set; } public string VersionSuffix { get; set; }
public string Verbosity { get; set; }
public List<string> ExtraMSBuildArguments { get; set; } public List<string> ExtraMSBuildArguments { get; set; }
@ -59,6 +60,11 @@ namespace Microsoft.DotNet.Tools.Publish
msbuildArgs.Add($"/p:VersionSuffix={VersionSuffix}"); msbuildArgs.Add($"/p:VersionSuffix={VersionSuffix}");
} }
if (!string.IsNullOrEmpty(Verbosity))
{
msbuildArgs.Add($"/verbosity:{Verbosity}");
}
msbuildArgs.AddRange(ExtraMSBuildArguments); msbuildArgs.AddRange(ExtraMSBuildArguments);
return new MSBuildForwardingApp(msbuildArgs).Execute(); return new MSBuildForwardingApp(msbuildArgs).Execute();

View file

@ -65,6 +65,8 @@ namespace Microsoft.DotNet.Tools.Restore
"Set this flag to ignore project to project references and only restore the root project", "Set this flag to ignore project to project references and only restore the root project",
CommandOptionType.NoValue); CommandOptionType.NoValue);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(cmd);
cmd.OnExecute(() => cmd.OnExecute(() =>
{ {
var msbuildArgs = new List<string>() var msbuildArgs = new List<string>()
@ -109,6 +111,11 @@ namespace Microsoft.DotNet.Tools.Restore
msbuildArgs.Add($"/p:RestoreRecursive=false"); msbuildArgs.Add($"/p:RestoreRecursive=false");
} }
if (verbosityOption.HasValue())
{
msbuildArgs.Add($"/verbosity:{verbosityOption.Value()}");
}
// Add in arguments // Add in arguments
msbuildArgs.AddRange(argRoot.Values); msbuildArgs.AddRange(argRoot.Values);

View file

@ -87,6 +87,8 @@ namespace Microsoft.DotNet.Tools.Test
@"Do not build project before testing.", @"Do not build project before testing.",
CommandOptionType.NoValue); CommandOptionType.NoValue);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(cmd);
cmd.OnExecute(() => cmd.OnExecute(() =>
{ {
var msbuildArgs = new List<string>() var msbuildArgs = new List<string>()
@ -94,7 +96,6 @@ namespace Microsoft.DotNet.Tools.Test
"/t:VSTest" "/t:VSTest"
}; };
msbuildArgs.Add("/verbosity:quiet");
msbuildArgs.Add("/nologo"); msbuildArgs.Add("/nologo");
if (settingOption.HasValue()) if (settingOption.HasValue())
@ -147,6 +148,15 @@ namespace Microsoft.DotNet.Tools.Test
msbuildArgs.Add($"/p:VSTestNoBuild=true"); msbuildArgs.Add($"/p:VSTestNoBuild=true");
} }
if (verbosityOption.HasValue())
{
msbuildArgs.Add($"/verbosity:{verbosityOption.Value()}");
}
else
{
msbuildArgs.Add("/verbosity:quiet");
}
string defaultproject = GetSingleTestProjectToRunTestIfNotProvided(argRoot.Value, cmd.RemainingArguments); string defaultproject = GetSingleTestProjectToRunTestIfNotProvided(argRoot.Value, cmd.RemainingArguments);
if(!string.IsNullOrEmpty(defaultproject)) if(!string.IsNullOrEmpty(defaultproject))

View file

@ -31,5 +31,73 @@ namespace Microsoft.DotNet.Cli.MSBuild.IntegrationTests
.Execute(command) .Execute(command)
.Should().Pass(); .Should().Pass();
} }
[Theory]
[InlineData("build")]
[InlineData("clean")]
[InlineData("pack")]
[InlineData("publish")]
public void When_dotnet_command_invokes_msbuild_with_no_args_verbosity_is_set_to_minimum(string command)
{
var testInstance = TestAssets.Get("MSBuildIntegration")
.CreateInstance(identifier: command)
.WithSourceFiles();
var cmd = new DotnetCommand()
.WithWorkingDirectory(testInstance.Root)
.ExecuteWithCapturedOutput(command);
cmd.Should().Pass();
cmd.StdOut.Should().NotContain("Message with normal importance");
// sanity check
cmd.StdOut.Should().Contain("Message with high importance");
}
[Theory]
[InlineData("build")]
[InlineData("clean")]
[InlineData("pack")]
[InlineData("publish")]
[InlineData("test")]
public void When_dotnet_command_invokes_msbuild_with_diag_verbosity_Then_arg_is_passed(string command)
{
var testInstance = TestAssets.Get("MSBuildIntegration")
.CreateInstance(identifier: command)
.WithSourceFiles();
var cmd = new DotnetCommand()
.WithWorkingDirectory(testInstance.Root)
.ExecuteWithCapturedOutput($"{command} -v diag");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("Message with low importance");
}
[Fact]
public void When_dotnet_test_invokes_msbuild_with_no_args_verbosity_is_set_to_quiet()
{
string command = "test";
var testInstance = TestAssets.Get("MSBuildIntegration")
.CreateInstance(identifier: command)
.WithSourceFiles();
var cmd = new DotnetCommand()
.WithWorkingDirectory(testInstance.Root)
.ExecuteWithCapturedOutput(command);
cmd.Should().Pass();
cmd.StdOut.Should().NotContain("Message with high importance");
}
[Fact]
public void When_dotnet_msbuild_command_is_invoked_with_non_msbuild_switch_Then_it_fails()
{
string command = "msbuild";
var testInstance = TestAssets.Get("MSBuildIntegration")
.CreateInstance(identifier: command)
.WithSourceFiles();
var cmd = new DotnetCommand()
.WithWorkingDirectory(testInstance.Root)
.ExecuteWithCapturedOutput($"{command} -v diag");
cmd.ExitCode.Should().NotBe(0);
}
} }
} }