diff --git a/.editorconfig b/.editorconfig index bc17bbe69267..e35b5cd19b0f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -511,11 +511,11 @@ dotnet_diagnostic.IDE0040.severity = warning insert_final_newline = false # Verify settings -[*.{received,verified}.{txt,xml,json}] +[*.{received,verified}.{txt,xml,json,sh,zsh,nu,fish,ps1}] charset = "utf-8-bom" end_of_line = lf indent_size = unset indent_style = unset insert_final_newline = false tab_width = unset -trim_trailing_whitespace = false \ No newline at end of file +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes index 2f46e347155a..a7c35ea1b75a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -67,3 +67,7 @@ *.verified.txt text eol=lf working-tree-encoding=UTF-8 *.verified.xml text eol=lf working-tree-encoding=UTF-8 *.verified.json text eol=lf working-tree-encoding=UTF-8 +*.verified.sh text eol=lf working-tree-encoding=UTF-8 +*.verified.zsh text eol=lf working-tree-encoding=UTF-8 +*.verified.nu text eol=lf working-tree-encoding=UTF-8 +*.verified.fish text eol=lf working-tree-encoding=UTF-8 diff --git a/.vscode/settings.json b/.vscode/settings.json index 1cdcc7c1869e..212ebd955c26 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,11 @@ { "dotnet.testWindow.disableAutoDiscovery": true, - "dotnet.defaultSolution": "sdk.slnx" + "dotnet.testWindow.disableBuildOnRun": true, + "dotnet.defaultSolution": "cli.slnf", + "files.associations": { + "*.slnf": "json", + "*.props": "xml", + "*.targets": "xml", + "*.*proj": "xml" + } } diff --git a/cli.slnf b/cli.slnf new file mode 100644 index 000000000000..a300800156bf --- /dev/null +++ b/cli.slnf @@ -0,0 +1,15 @@ +{ + "solution": { + "path": "sdk.slnx", + "projects": [ + "src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj", + "src\\Cli\\dotnet\\dotnet.csproj", + "src\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj", + "test\\dotnet-new.IntegrationTests\\dotnet-new.IntegrationTests.csproj", + "test\\dotnet-watch.Tests\\dotnet-watch.Tests.csproj", + "test\\dotnet.Tests\\dotnet.Tests.csproj", + "test\\Microsoft.DotNet.Cli.Utils.Tests\\Microsoft.DotNet.Cli.Utils.Tests.csproj", + "test\\Microsoft.NET.TestFramework\\Microsoft.NET.TestFramework.csproj" + ] + } +} diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs index dbedb133bfc0..c85eaa1d0bf7 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.DotNet.Cli.Utils; public static class Env @@ -21,6 +23,9 @@ public static class Env public static bool GetEnvironmentVariableAsBool(string name, bool defaultValue = false) => s_environment.GetEnvironmentVariableAsBool(name, defaultValue); + public static bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value) => + s_environment.TryGetEnvironmentVariableAsBool(name, out value); + public static int? GetEnvironmentVariableAsNullableInt(string name) => s_environment.GetEnvironmentVariableAsNullableInt(name); diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs index 50984a692d1c..06c64b67110a 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.DotNet.Cli.Utils.Extensions; namespace Microsoft.DotNet.Cli.Utils; @@ -136,6 +137,12 @@ public bool GetEnvironmentVariableAsBool(string name, bool defaultValue) return Environment.GetEnvironmentVariable(variable, target); } + public bool TryGetEnvironmentVariable(string name, [NotNullWhen(true)] out string? value) + { + value = Environment.GetEnvironmentVariable(name); + return value != null; + } + public void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) { Environment.SetEnvironmentVariable(variable, value, target); @@ -150,4 +157,57 @@ public void SetEnvironmentVariable(string variable, string value, EnvironmentVar return null; } + + public bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value) + { + if (TryGetEnvironmentVariable(name, out string? strValue) && + (bool.TryParse(strValue, out bool boolValue) + || TryParseNonBoolConstantStringAsBool(strValue, out boolValue))) + { + value = boolValue; + return true; + } + else + { + value = false; + return false; + } + } + + /// + /// Parses non-boolean constant strings like "1", "0", "yes", "no", "on", "off" as boolean values. + /// + private static bool TryParseNonBoolConstantStringAsBool(string? strValue, out bool value) + { + switch (strValue?.ToLowerInvariant()) + { + case "1": + case "yes": + case "on": + value = true; + return true; + case "0": + case "no": + case "off": + value = false; + return true; + default: + value = false; + return false; + } + } + + public bool TryGetEnvironmentVariableAsInt(string name, [NotNullWhen(true)] out int value) + { + if (TryGetEnvironmentVariable(name, out string? strValue) && int.TryParse(strValue, out int intValue)) + { + value = intValue; + return true; + } + else + { + value = -1; + return false; + } + } } diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs index 385f989d4990..8aaacf30fbad 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs @@ -3,6 +3,9 @@ namespace Microsoft.DotNet.Cli.Utils; +using System.Diagnostics.CodeAnalysis; + + public interface IEnvironmentProvider { IEnumerable ExecutableExtensions { get; } @@ -19,6 +22,10 @@ public interface IEnvironmentProvider string? GetEnvironmentVariable(string name); + bool TryGetEnvironmentVariable(string name, [NotNullWhen(true)] out string? value); + bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value); + bool TryGetEnvironmentVariableAsInt(string name, [NotNullWhen(true)] out int value); + string? GetEnvironmentVariable(string variable, EnvironmentVariableTarget target); void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target); diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs index 12226f42f0d6..7fedc17f3878 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs @@ -21,7 +21,9 @@ private MSBuildArgs( string[]? getTargetResult, string[]? getResultOutputFile, VerbosityOptions? verbosity, - string[]? otherMSBuildArgs) + bool noLogo, + string[]? otherMSBuildArgs + ) { GlobalProperties = properties; RestoreGlobalProperties = restoreProperties; @@ -31,6 +33,7 @@ private MSBuildArgs( GetTargetResult = getTargetResult; GetResultOutputFile = getResultOutputFile; Verbosity = verbosity; + NoLogo = noLogo; OtherMSBuildArgs = otherMSBuildArgs is not null ? [.. otherMSBuildArgs] : new List(); @@ -51,16 +54,33 @@ private MSBuildArgs( /// public string[]? RequestedTargets { get; } + /// + /// If specified, the list of MSBuild Property names to retrieve and report directly for this build of a single project. + /// public string[]? GetProperty { get; } + /// + /// If specified, the list of MSBuild Item names to retrieve and report directly for this build of a single project. + /// public string[]? GetItem { get; } + /// + /// If specified, the list of MSBuild Target Output/Return Items to retrieve and report directly for this build of a single project. + /// public string[]? GetTargetResult { get; } + /// + /// If specified, the list of output files to which to write --getProperty, --getItem, and --getTargetResult outputs. + /// public string[]? GetResultOutputFile { get; } public VerbosityOptions? Verbosity { get; } + /// + /// Whether or not the MSBuild product header text should be emitted at the start of this build + /// + public bool NoLogo { get; } + /// /// All other arguments that aren't already explicitly modeled by this structure. /// The main categories of these today are logger configurations @@ -89,16 +109,15 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable forwardedA } var parseResult = fakeCommand.Parse([.. forwardedAndUserFacingArgs], _analysisParsingConfiguration); - var globalProperties = parseResult.GetResult("--property") is OptionResult propResult ? propResult.GetValueOrDefault?>() : null; - var restoreProperties = parseResult.GetResult("--restoreProperty") is OptionResult restoreResult ? restoreResult.GetValueOrDefault?>() : null; - var requestedTargets = parseResult.GetResult("--target") is OptionResult targetResult ? targetResult.GetValueOrDefault() : null; + var globalProperties = TryGetValue?>("--property"); + var restoreProperties = TryGetValue?>("--restoreProperty"); + var requestedTargets = TryGetValue("--target"); var getProperty = TryGetValue("--getProperty"); var getItem = TryGetValue("--getItem"); var getTargetResult = TryGetValue("--getTargetResult"); var getResultOutputFile = TryGetValue("--getResultOutputFile"); - var verbosity = parseResult.GetResult("--verbosity") is OptionResult verbosityResult - ? verbosityResult.GetValueOrDefault() - : null; + var verbosity = TryGetValue("--verbosity"); + var nologo = TryGetValue("--no-logo") ?? true; // Default to nologo if not specified var otherMSBuildArgs = parseResult.UnmatchedTokens.ToArray(); return new MSBuildArgs( properties: globalProperties, @@ -109,8 +128,12 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable forwardedA getTargetResult: getTargetResult, getResultOutputFile: getResultOutputFile, otherMSBuildArgs: otherMSBuildArgs, - verbosity: verbosity); + verbosity: verbosity, + noLogo: nologo); + /// We can't use to check if the names of the options we care + /// about were specified, because if they weren't specified it throws. + /// So we first check if the option was specified, and only then get its value. T? TryGetValue(string name) { return options.Any(o => o.Name == name) ? parseResult.GetValue(name) : default; @@ -120,19 +143,19 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable forwardedA public static MSBuildArgs FromProperties(ReadOnlyDictionary? properties) { - return new MSBuildArgs(properties, null, null, null, null, null, null, null, null); + return new MSBuildArgs(properties, null, null, null, null, null, null, null, noLogo: false, null); } public static MSBuildArgs FromOtherArgs(params ReadOnlySpan args) { - return new MSBuildArgs(null, null, null, null, null, null, null, null, args.ToArray()); + return new MSBuildArgs(null, null, null, null, null, null, null, null, noLogo: false, args.ToArray()); } public static MSBuildArgs FromVerbosity(VerbosityOptions verbosity) { - return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, null); + return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, noLogo: false, null); } - public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, ["--help"]); + public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, noLogo: true, ["--help"]); /// /// Completely replaces the MSBuild arguments with the provided . @@ -148,6 +171,7 @@ public MSBuildArgs CloneWithExplicitArgs(string[] newArgs) getTargetResult: GetTargetResult, getResultOutputFile: GetResultOutputFile, otherMSBuildArgs: newArgs, + noLogo: NoLogo, verbosity: Verbosity); } @@ -168,6 +192,7 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs) GetTargetResult, GetResultOutputFile, Verbosity, + NoLogo, OtherMSBuildArgs.ToArray()); } @@ -180,6 +205,7 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs) GetTargetResult, GetResultOutputFile, Verbosity, + NoLogo, [.. OtherMSBuildArgs, .. additionalArgs]); } @@ -197,6 +223,7 @@ public MSBuildArgs CloneWithAdditionalRestoreProperties(ReadOnlyDictionary additi GetTargetResult, GetResultOutputFile, Verbosity, + NoLogo, OtherMSBuildArgs.ToArray()); } @@ -305,6 +338,22 @@ public MSBuildArgs CloneWithVerbosity(VerbosityOptions newVerbosity) GetTargetResult, GetResultOutputFile, newVerbosity, + NoLogo, + OtherMSBuildArgs.ToArray()); + } + + public MSBuildArgs CloneWithNoLogo(bool noLogo) + { + return new MSBuildArgs( + GlobalProperties, + RestoreGlobalProperties, + RequestedTargets, + GetProperty, + GetItem, + GetTargetResult, + GetResultOutputFile, + Verbosity, + noLogo, OtherMSBuildArgs.ToArray()); } diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs index e0dca709ac3c..87d021eda157 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs @@ -44,17 +44,11 @@ public static string MSBuildVersion private readonly List _msbuildRequiredParameters = ["-maxcpucount", $"--verbosity:{DefaultVerbosity}"]; - public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null, bool includeLogo = false, bool isRestoring = true) + public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null) { string defaultMSBuildPath = GetMSBuildExePath(); _msbuildArgs = msbuildArgs; - if (!includeLogo && !msbuildArgs.OtherMSBuildArgs.Contains("-nologo", StringComparer.OrdinalIgnoreCase)) - { - // If the user didn't explicitly ask for -nologo, we add it to avoid the MSBuild logo. - // This is useful for scenarios like restore where we don't want to print the logo. - // Note that this is different from the default behavior of MSBuild, which prints the logo. - msbuildArgs.OtherMSBuildArgs.Add("-nologo"); - } + string? tlpDefault = TerminalLoggerDefault; if (string.IsNullOrWhiteSpace(tlpDefault)) { @@ -101,6 +95,7 @@ private string[] EmitMSBuildArgs(MSBuildArgs msbuildArgs) => [ .. msbuildArgs.RestoreGlobalProperties?.Select(kvp => EmitProperty(kvp, "restoreProperty")) ?? [], .. msbuildArgs.RequestedTargets?.Select(target => $"--target:{target}") ?? [], .. msbuildArgs.Verbosity is not null ? new string[1] { $"--verbosity:{msbuildArgs.Verbosity}" } : [], + .. msbuildArgs.NoLogo is true ? new string[1] { "--nologo" } : [], .. msbuildArgs.OtherMSBuildArgs ]; diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs index ab674a2906ee..59668dbae394 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs @@ -4,11 +4,24 @@ #if NET472 #pragma warning disable IDE0130 // Namespace does not match folder structure -namespace System.Runtime.CompilerServices; -#pragma warning restore IDE0130 // Namespace does not match folder structure +namespace System.Runtime.CompilerServices { + + internal static class IsExternalInit + { + } + +} -internal static class IsExternalInit +namespace System.Diagnostics.CodeAnalysis { + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + public bool ReturnValue { get; } + } } +#pragma warning restore IDE0130 // Namespace does not match folder structure #endif diff --git a/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs b/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs index 2f8bb7badd98..aa844850e316 100644 --- a/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs @@ -385,7 +385,7 @@ internal void GenerateDepsJsonFile( string? stdOut; string? stdErr; - var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([..args], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption); + var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([..args], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption, BuildCommandParser.NoLogoOption); var forwardingAppWithoutLogging = new MSBuildForwardingAppWithoutLogging(msbuildArgs, msBuildExePath); if (forwardingAppWithoutLogging.ExecuteMSBuildOutOfProc) { diff --git a/src/Cli/dotnet/Commands/Build/BuildCommand.cs b/src/Cli/dotnet/Commands/Build/BuildCommand.cs index 3d8943315a94..264abdad7d80 100644 --- a/src/Cli/dotnet/Commands/Build/BuildCommand.cs +++ b/src/Cli/dotnet/Commands/Build/BuildCommand.cs @@ -43,7 +43,7 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui noRestore: noRestore, msbuildPath: msbuildPath ), - [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption], + [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, BuildCommandParser.TargetOption, BuildCommandParser.VerbosityOption, BuildCommandParser.NoLogoOption], parseResult, msbuildPath ); diff --git a/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs b/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs index 74b4efa2a712..be2e52c45263 100644 --- a/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs +++ b/src/Cli/dotnet/Commands/Build/BuildCommandParser.cs @@ -36,11 +36,7 @@ internal static class BuildCommandParser Arity = ArgumentArity.Zero }.ForwardAs("--property:BuildProjectReferences=false"); - public static readonly Option NoLogoOption = new Option("--nologo") - { - Description = CliCommandStrings.BuildCmdNoLogo, - Arity = ArgumentArity.Zero - }.ForwardAs("-nologo"); + public static readonly Option NoLogoOption = CommonOptions.NoLogoOption(); public static readonly Option NoRestoreOption = CommonOptions.NoRestoreOption; diff --git a/src/Cli/dotnet/Commands/Clean/CleanCommand.cs b/src/Cli/dotnet/Commands/Clean/CleanCommand.cs index 1290b8b68cfd..c7e48c376ee9 100644 --- a/src/Cli/dotnet/Commands/Clean/CleanCommand.cs +++ b/src/Cli/dotnet/Commands/Clean/CleanCommand.cs @@ -33,7 +33,7 @@ public static CommandBase FromParseResult(ParseResult result, string? msbuildPat NoWriteBuildMarkers = true, }, static (msbuildArgs, msbuildPath) => new CleanCommand(msbuildArgs, msbuildPath), - [ CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CleanCommandParser.TargetOption, CleanCommandParser.VerbosityOption ], + [ CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CleanCommandParser.TargetOption, CleanCommandParser.VerbosityOption, CleanCommandParser.NoLogoOption], result, msbuildPath ); diff --git a/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs b/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs index 24e83acc8b64..117537d7fd1f 100644 --- a/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs +++ b/src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs @@ -24,15 +24,11 @@ internal static class CleanCommandParser HelpName = CliCommandStrings.CleanCmdOutputDir }.ForwardAsOutputPath("OutputPath"); - public static readonly Option NoLogoOption = new Option("--nologo") - { - Description = CliCommandStrings.CleanCmdNoLogo, - Arity = ArgumentArity.Zero - }.ForwardAs("-nologo"); + public static readonly Option NoLogoOption = CommonOptions.NoLogoOption(); - public static readonly Option FrameworkOption = CommonOptions.FrameworkOption(CliCommandStrings.CleanFrameworkOptionDescription); + public static readonly Option FrameworkOption = CommonOptions.FrameworkOption(CliCommandStrings.CleanFrameworkOptionDescription); - public static readonly Option ConfigurationOption = CommonOptions.ConfigurationOption(CliCommandStrings.CleanConfigurationOptionDescription); + public static readonly Option ConfigurationOption = CommonOptions.ConfigurationOption(CliCommandStrings.CleanConfigurationOptionDescription); public static readonly Option TargetOption = CommonOptions.RequiredMSBuildTargetOption("Clean"); diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx index 4fbcfb5e5d2b..2c94953811c9 100644 --- a/src/Cli/dotnet/Commands/CliCommandStrings.resx +++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx @@ -1,17 +1,17 @@  - @@ -166,7 +166,7 @@ .NET Builder - + Do not display the startup banner or the copyright message. @@ -250,9 +250,6 @@ Paths searched: '{1}', '{2}'. .NET Clean Command - - Do not display the startup banner or the copyright message. - OUTPUT_DIR @@ -1322,9 +1319,6 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man .NET Core NuGet Package Packer - - Do not display the startup banner or the copyright message. - OUTPUT_DIR @@ -1597,9 +1591,6 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Publisher for the .NET Platform - - Do not display the startup banner or the copyright message. - The configuration to publish for. The default is 'Release' for NET 8.0 projects and above, but 'Debug' for older projects. diff --git a/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs b/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs index d7edaea57478..7e28945067a3 100644 --- a/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs +++ b/src/Cli/dotnet/Commands/MSBuild/MSBuildCommand.cs @@ -11,7 +11,17 @@ namespace Microsoft.DotNet.Cli.Commands.MSBuild; public class MSBuildCommand( IEnumerable msbuildArgs, string? msbuildPath = null -) : MSBuildForwardingApp(MSBuildArgs.AnalyzeMSBuildArguments([..msbuildArgs], CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, MSBuildCommandParser.TargetOption, CommonOptions.VerbosityOption()), msbuildPath, includeLogo: true) +) : MSBuildForwardingApp(MSBuildArgs.AnalyzeMSBuildArguments( + [.. msbuildArgs], + CommonOptions.PropertiesOption, + CommonOptions.RestorePropertiesOption, + MSBuildCommandParser.TargetOption, + CommonOptions.VerbosityOption(), + // We set the no-logo option to false here to ensure that by default the logo is shown for this command. + // This is different from other commands that default to hiding the logo - but this command is meant to mimic + // the behavior of calling MSBuild directly, which shows the logo by default. + CommonOptions.NoLogoOption(false) + ), msbuildPath) { public static MSBuildCommand FromArgs(string[] args, string? msbuildPath = null) { diff --git a/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs b/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs index 3055de0883f5..df0eaf4d166a 100644 --- a/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs +++ b/src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs @@ -42,18 +42,17 @@ private static MSBuildArgs ConcatTelemetryLogger(MSBuildArgs msbuildArgs) /// Mostly intended for quick/one-shot usage - most 'core' SDK commands should do more hands-on parsing. /// public MSBuildForwardingApp(IEnumerable rawMSBuildArgs, string? msbuildPath = null) : this( - MSBuildArgs.AnalyzeMSBuildArguments(rawMSBuildArgs.ToArray(), CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CommonOptions.MSBuildTargetOption(), CommonOptions.VerbosityOption()), + MSBuildArgs.AnalyzeMSBuildArguments(rawMSBuildArgs.ToArray(), CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, CommonOptions.MSBuildTargetOption(), CommonOptions.VerbosityOption(), CommonOptions.NoLogoOption()), msbuildPath) { } - public MSBuildForwardingApp(MSBuildArgs msBuildArgs, string? msbuildPath = null, bool includeLogo = false) + public MSBuildForwardingApp(MSBuildArgs msBuildArgs, string? msbuildPath = null) { var modifiedMSBuildArgs = CommonRunHelpers.AdjustMSBuildForLLMs(ConcatTelemetryLogger(msBuildArgs)); _forwardingAppWithoutLogging = new MSBuildForwardingAppWithoutLogging( modifiedMSBuildArgs, - msbuildPath: msbuildPath, - includeLogo: includeLogo); + msbuildPath: msbuildPath); // Add the performance log location to the environment of the target process. if (PerformanceLogManager.Instance != null && !string.IsNullOrEmpty(PerformanceLogManager.Instance.CurrentLogDirectory)) diff --git a/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs b/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs index 46ddfe28c4b0..4aae2f0f037e 100644 --- a/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs +++ b/src/Cli/dotnet/Commands/New/DotnetCommandCallbacks.cs @@ -38,7 +38,7 @@ internal static bool RestoreProject(string pathToRestore) { PathUtility.EnsureAllPathsExist([pathToRestore], CliStrings.CommonFileNotFound, allowDirectories: true); // for the implicit restore we do not want the terminal logger to emit any output unless there are errors - return RestoreCommand.Run([pathToRestore, "-tlp:verbosity=quiet"]) == 0; + return RestoreCommand.Run([pathToRestore, "-tlp:verbosity=quiet", "--no-logo"]) == 0; } internal static bool AddProjectsToSolution(string solutionPath, IReadOnlyList projectsToAdd, string? solutionFolder, bool? inRoot) diff --git a/src/Cli/dotnet/Commands/Pack/PackCommand.cs b/src/Cli/dotnet/Commands/Pack/PackCommand.cs index 57342f67bad2..9f31bfa145fe 100644 --- a/src/Cli/dotnet/Commands/Pack/PackCommand.cs +++ b/src/Cli/dotnet/Commands/Pack/PackCommand.cs @@ -60,6 +60,7 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui CommonOptions.RestorePropertiesOption, PackCommandParser.TargetOption, PackCommandParser.VerbosityOption, + PackCommandParser.NoLogoOption ], parseResult, msbuildPath, diff --git a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs index a57aa2fabfcd..23fc1ef58f69 100644 --- a/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs +++ b/src/Cli/dotnet/Commands/Pack/PackCommandParser.cs @@ -49,11 +49,7 @@ internal static class PackCommandParser Arity = ArgumentArity.Zero }.ForwardAs("-property:Serviceable=true"); - public static readonly Option NoLogoOption = new Option("--nologo") - { - Description = CliCommandStrings.PackCmdNoLogo, - Arity = ArgumentArity.Zero - }.ForwardAs("-nologo"); + public static readonly Option NoLogoOption = CommonOptions.NoLogoOption(); public static readonly Option NoRestoreOption = CommonOptions.NoRestoreOption; diff --git a/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs b/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs index d6c1ef2f4afd..a463165828cb 100644 --- a/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs +++ b/src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs @@ -91,7 +91,7 @@ private static void GetProjectDependencyGraph(string projectFilePath, string dgF $"-property:RestoreDotnetCliToolReferences=false", // Output should not include MSBuild version header - "-nologo", + "--nologo", // Set verbosity to quiet to avoid cluttering the output for this 'inner' build "-v:quiet" diff --git a/src/Cli/dotnet/Commands/Publish/PublishCommand.cs b/src/Cli/dotnet/Commands/Publish/PublishCommand.cs index 2bfb835871a9..424a2250c25a 100644 --- a/src/Cli/dotnet/Commands/Publish/PublishCommand.cs +++ b/src/Cli/dotnet/Commands/Publish/PublishCommand.cs @@ -58,7 +58,7 @@ public static CommandBase FromParseResult(ParseResult parseResult, string? msbui noRestore: noRestore, msbuildPath: msbuildPath ), - [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, PublishCommandParser.TargetOption, PublishCommandParser.VerbosityOption], + [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, PublishCommandParser.TargetOption, PublishCommandParser.VerbosityOption, PublishCommandParser.NoLogoOption], parseResult, msbuildPath, (msbuildArgs) => diff --git a/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs b/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs index 9fbe305d4877..2c2b1b20e36f 100644 --- a/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs +++ b/src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs @@ -38,11 +38,7 @@ internal static class PublishCommandParser Arity = ArgumentArity.Zero }.ForwardAs("-property:NoBuild=true"); - public static readonly Option NoLogoOption = new Option("--nologo") - { - Description = CliCommandStrings.PublishCmdNoLogo, - Arity = ArgumentArity.Zero - }.ForwardAs("-nologo"); + public static readonly Option NoLogoOption = CommonOptions.NoLogoOption(); public static readonly Option NoRestoreOption = CommonOptions.NoRestoreOption; diff --git a/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs b/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs index 6eb650b0e261..5a9ff6a37056 100644 --- a/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs +++ b/src/Cli/dotnet/Commands/Restore/RestoreCommand.cs @@ -40,7 +40,7 @@ public static CommandBase FromParseResult(ParseResult result, string? msbuildPat { return CreateForwarding(msbuildArgs, msbuildPath); }, - [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, RestoreCommandParser.TargetOption, RestoreCommandParser.VerbosityOption], + [CommonOptions.PropertiesOption, CommonOptions.RestorePropertiesOption, RestoreCommandParser.TargetOption, RestoreCommandParser.VerbosityOption, RestoreCommandParser.NoLogoOption], result, msbuildPath ); diff --git a/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs b/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs index 7e1f4a48106d..f32a0b1545b7 100644 --- a/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs +++ b/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs @@ -27,36 +27,36 @@ internal static class RestoreCommandParser public static readonly Option TargetOption = CommonOptions.RequiredMSBuildTargetOption("Restore"); public static readonly Option VerbosityOption = CommonOptions.VerbosityOption(Utils.VerbosityOptions.minimal); - - private static IEnumerable