Skip to content

Commit 3ec6972

Browse files
committed
model the usage of --nologo for MSBuild forwarding and infer it from the DOTNET_NOLOGO environment variable
1 parent 30287ee commit 3ec6972

30 files changed

+307
-131
lines changed

src/Cli/Microsoft.DotNet.Cli.Utils/Env.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
5+
46
namespace Microsoft.DotNet.Cli.Utils;
57

68
public static class Env
@@ -21,6 +23,9 @@ public static class Env
2123
public static bool GetEnvironmentVariableAsBool(string name, bool defaultValue = false) =>
2224
s_environment.GetEnvironmentVariableAsBool(name, defaultValue);
2325

26+
public static bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value) =>
27+
s_environment.TryGetEnvironmentVariableAsBool(name, out value);
28+
2429
public static int? GetEnvironmentVariableAsNullableInt(string name) =>
2530
s_environment.GetEnvironmentVariableAsNullableInt(name);
2631

src/Cli/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
45
using Microsoft.DotNet.Cli.Utils.Extensions;
56

67
namespace Microsoft.DotNet.Cli.Utils;
@@ -136,6 +137,12 @@ public bool GetEnvironmentVariableAsBool(string name, bool defaultValue)
136137
return Environment.GetEnvironmentVariable(variable, target);
137138
}
138139

140+
public bool TryGetEnvironmentVariable(string name, [NotNullWhen(true)] out string? value)
141+
{
142+
value = Environment.GetEnvironmentVariable(name);
143+
return value != null;
144+
}
145+
139146
public void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
140147
{
141148
Environment.SetEnvironmentVariable(variable, value, target);
@@ -150,4 +157,57 @@ public void SetEnvironmentVariable(string variable, string value, EnvironmentVar
150157

151158
return null;
152159
}
160+
161+
public bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value)
162+
{
163+
if (TryGetEnvironmentVariable(name, out string? strValue) &&
164+
(bool.TryParse(strValue, out bool boolValue)
165+
|| TryParseNonBoolConstantStringAsBool(strValue, out boolValue)))
166+
{
167+
value = boolValue;
168+
return true;
169+
}
170+
else
171+
{
172+
value = false;
173+
return false;
174+
}
175+
}
176+
177+
/// <summary>
178+
/// Parses non-boolean constant strings like "1", "0", "yes", "no", "on", "off" as boolean values.
179+
/// </summary>
180+
private static bool TryParseNonBoolConstantStringAsBool(string? strValue, out bool value)
181+
{
182+
switch (strValue?.ToLowerInvariant())
183+
{
184+
case "1":
185+
case "yes":
186+
case "on":
187+
value = true;
188+
return true;
189+
case "0":
190+
case "no":
191+
case "off":
192+
value = false;
193+
return true;
194+
default:
195+
value = false;
196+
return false;
197+
}
198+
}
199+
200+
public bool TryGetEnvironmentVariableAsInt(string name, [NotNullWhen(true)] out int value)
201+
{
202+
if (TryGetEnvironmentVariable(name, out string? strValue) && int.TryParse(strValue, out int intValue))
203+
{
204+
value = intValue;
205+
return true;
206+
}
207+
else
208+
{
209+
value = -1;
210+
return false;
211+
}
212+
}
153213
}

src/Cli/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
namespace Microsoft.DotNet.Cli.Utils;
55

6+
using System.Diagnostics.CodeAnalysis;
7+
8+
69
public interface IEnvironmentProvider
710
{
811
IEnumerable<string> ExecutableExtensions { get; }
@@ -19,6 +22,10 @@ public interface IEnvironmentProvider
1922

2023
string? GetEnvironmentVariable(string name);
2124

25+
bool TryGetEnvironmentVariable(string name, [NotNullWhen(true)] out string? value);
26+
bool TryGetEnvironmentVariableAsBool(string name, [NotNullWhen(true)] out bool value);
27+
bool TryGetEnvironmentVariableAsInt(string name, [NotNullWhen(true)] out int value);
28+
2229
string? GetEnvironmentVariable(string variable, EnvironmentVariableTarget target);
2330

2431
void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target);

src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ private MSBuildArgs(
2121
string[]? getTargetResult,
2222
string[]? getResultOutputFile,
2323
VerbosityOptions? verbosity,
24-
string[]? otherMSBuildArgs)
24+
bool noLogo,
25+
string[]? otherMSBuildArgs
26+
)
2527
{
2628
GlobalProperties = properties;
2729
RestoreGlobalProperties = restoreProperties;
@@ -31,6 +33,7 @@ private MSBuildArgs(
3133
GetTargetResult = getTargetResult;
3234
GetResultOutputFile = getResultOutputFile;
3335
Verbosity = verbosity;
36+
NoLogo = noLogo;
3437
OtherMSBuildArgs = otherMSBuildArgs is not null
3538
? [.. otherMSBuildArgs]
3639
: new List<string>();
@@ -51,16 +54,33 @@ private MSBuildArgs(
5154
/// </summary>
5255
public string[]? RequestedTargets { get; }
5356

57+
/// <summary>
58+
/// If specified, the list of MSBuild Property names to retrieve and report directly for this build of a single project.
59+
/// </summary>
5460
public string[]? GetProperty { get; }
5561

62+
/// <summary>
63+
/// If specified, the list of MSBuild Item names to retrieve and report directly for this build of a single project.
64+
/// </summary>
5665
public string[]? GetItem { get; }
5766

67+
/// <summary>
68+
/// If specified, the list of MSBuild Target Output/Return Items to retrieve and report directly for this build of a single project.
69+
/// </summary>
5870
public string[]? GetTargetResult { get; }
5971

72+
/// <summary>
73+
/// If specified, the list of output files to which to write --getProperty, --getItem, and --getTargetResult outputs.
74+
/// </summary>
6075
public string[]? GetResultOutputFile { get; }
6176

6277
public VerbosityOptions? Verbosity { get; }
6378

79+
/// <summary>
80+
/// Wether or not the MSBuild product header text should be emitted at the start of this build
81+
/// </summary>
82+
public bool NoLogo { get; }
83+
6484
/// <summary>
6585
/// All other arguments that aren't already explicitly modeled by this structure.
6686
/// The main categories of these today are logger configurations
@@ -99,6 +119,9 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable<string> forwardedA
99119
var verbosity = parseResult.GetResult("--verbosity") is OptionResult verbosityResult
100120
? verbosityResult.GetValueOrDefault<VerbosityOptions?>()
101121
: null;
122+
var nologo = parseResult.GetResult("--nologo") is OptionResult nologoResult
123+
? nologoResult.GetValueOrDefault<bool>()
124+
: false;
102125
var otherMSBuildArgs = parseResult.UnmatchedTokens.ToArray();
103126
return new MSBuildArgs(
104127
properties: globalProperties,
@@ -109,7 +132,8 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable<string> forwardedA
109132
getTargetResult: getTargetResult,
110133
getResultOutputFile: getResultOutputFile,
111134
otherMSBuildArgs: otherMSBuildArgs,
112-
verbosity: verbosity);
135+
verbosity: verbosity,
136+
noLogo: nologo);
113137

114138
T? TryGetValue<T>(string name)
115139
{
@@ -120,19 +144,19 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable<string> forwardedA
120144

121145
public static MSBuildArgs FromProperties(ReadOnlyDictionary<string, string>? properties)
122146
{
123-
return new MSBuildArgs(properties, null, null, null, null, null, null, null, null);
147+
return new MSBuildArgs(properties, null, null, null, null, null, null, null, noLogo: false, null);
124148
}
125149

126150
public static MSBuildArgs FromOtherArgs(params ReadOnlySpan<string> args)
127151
{
128-
return new MSBuildArgs(null, null, null, null, null, null, null, null, args.ToArray());
152+
return new MSBuildArgs(null, null, null, null, null, null, null, null, noLogo: false, args.ToArray());
129153
}
130154
public static MSBuildArgs FromVerbosity(VerbosityOptions verbosity)
131155
{
132-
return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, null);
156+
return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, noLogo: false, null);
133157
}
134158

135-
public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, ["--help"]);
159+
public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, noLogo: true, ["--help"]);
136160

137161
/// <summary>
138162
/// Completely replaces the MSBuild arguments with the provided <paramref name="newArgs"/>.
@@ -148,6 +172,7 @@ public MSBuildArgs CloneWithExplicitArgs(string[] newArgs)
148172
getTargetResult: GetTargetResult,
149173
getResultOutputFile: GetResultOutputFile,
150174
otherMSBuildArgs: newArgs,
175+
noLogo: NoLogo,
151176
verbosity: Verbosity);
152177
}
153178

@@ -168,6 +193,7 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs)
168193
GetTargetResult,
169194
GetResultOutputFile,
170195
Verbosity,
196+
NoLogo,
171197
OtherMSBuildArgs.ToArray());
172198
}
173199

@@ -180,6 +206,7 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs)
180206
GetTargetResult,
181207
GetResultOutputFile,
182208
Verbosity,
209+
NoLogo,
183210
[.. OtherMSBuildArgs, .. additionalArgs]);
184211
}
185212

@@ -197,6 +224,7 @@ public MSBuildArgs CloneWithAdditionalRestoreProperties(ReadOnlyDictionary<strin
197224
GetTargetResult,
198225
GetResultOutputFile,
199226
Verbosity,
227+
NoLogo,
200228
OtherMSBuildArgs.ToArray());
201229
}
202230
if (RestoreGlobalProperties is null)
@@ -210,6 +238,7 @@ public MSBuildArgs CloneWithAdditionalRestoreProperties(ReadOnlyDictionary<strin
210238
GetTargetResult,
211239
GetResultOutputFile,
212240
Verbosity,
241+
NoLogo,
213242
OtherMSBuildArgs.ToArray());
214243
}
215244

@@ -227,6 +256,7 @@ public MSBuildArgs CloneWithAdditionalRestoreProperties(ReadOnlyDictionary<strin
227256
GetTargetResult,
228257
GetResultOutputFile,
229258
Verbosity,
259+
NoLogo,
230260
OtherMSBuildArgs.ToArray());
231261
}
232262

@@ -244,6 +274,7 @@ public MSBuildArgs CloneWithAdditionalProperties(ReadOnlyDictionary<string, stri
244274
GetTargetResult,
245275
GetResultOutputFile,
246276
Verbosity,
277+
NoLogo,
247278
OtherMSBuildArgs.ToArray());
248279
}
249280
if (GlobalProperties is null)
@@ -257,6 +288,7 @@ public MSBuildArgs CloneWithAdditionalProperties(ReadOnlyDictionary<string, stri
257288
GetTargetResult,
258289
GetResultOutputFile,
259290
Verbosity,
291+
NoLogo,
260292
OtherMSBuildArgs.ToArray());
261293
}
262294

@@ -274,6 +306,7 @@ public MSBuildArgs CloneWithAdditionalProperties(ReadOnlyDictionary<string, stri
274306
GetTargetResult,
275307
GetResultOutputFile,
276308
Verbosity,
309+
NoLogo,
277310
OtherMSBuildArgs.ToArray());
278311
}
279312

@@ -291,6 +324,7 @@ public MSBuildArgs CloneWithAdditionalTargets(params ReadOnlySpan<string> additi
291324
GetTargetResult,
292325
GetResultOutputFile,
293326
Verbosity,
327+
NoLogo,
294328
OtherMSBuildArgs.ToArray());
295329
}
296330

@@ -305,6 +339,22 @@ public MSBuildArgs CloneWithVerbosity(VerbosityOptions newVerbosity)
305339
GetTargetResult,
306340
GetResultOutputFile,
307341
newVerbosity,
342+
NoLogo,
343+
OtherMSBuildArgs.ToArray());
344+
}
345+
346+
public MSBuildArgs CloneWithNoLogo(bool noLogo)
347+
{
348+
return new MSBuildArgs(
349+
GlobalProperties,
350+
RestoreGlobalProperties,
351+
RequestedTargets,
352+
GetProperty,
353+
GetItem,
354+
GetTargetResult,
355+
GetResultOutputFile,
356+
Verbosity,
357+
noLogo,
308358
OtherMSBuildArgs.ToArray());
309359
}
310360

src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,11 @@ public static string MSBuildVersion
4444

4545
private readonly List<string> _msbuildRequiredParameters = ["-maxcpucount", $"--verbosity:{DefaultVerbosity}"];
4646

47-
public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null, bool includeLogo = false, bool isRestoring = true)
47+
public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null)
4848
{
4949
string defaultMSBuildPath = GetMSBuildExePath();
5050
_msbuildArgs = msbuildArgs;
51-
if (!includeLogo && !msbuildArgs.OtherMSBuildArgs.Contains("-nologo", StringComparer.OrdinalIgnoreCase))
52-
{
53-
// If the user didn't explicitly ask for -nologo, we add it to avoid the MSBuild logo.
54-
// This is useful for scenarios like restore where we don't want to print the logo.
55-
// Note that this is different from the default behavior of MSBuild, which prints the logo.
56-
msbuildArgs.OtherMSBuildArgs.Add("-nologo");
57-
}
51+
5852
string? tlpDefault = TerminalLoggerDefault;
5953
if (string.IsNullOrWhiteSpace(tlpDefault))
6054
{
@@ -101,6 +95,7 @@ private string[] EmitMSBuildArgs(MSBuildArgs msbuildArgs) => [
10195
.. msbuildArgs.RestoreGlobalProperties?.Select(kvp => EmitProperty(kvp, "restoreProperty")) ?? [],
10296
.. msbuildArgs.RequestedTargets?.Select(target => $"--target:{target}") ?? [],
10397
.. msbuildArgs.Verbosity is not null ? new string[1] { $"--verbosity:{msbuildArgs.Verbosity}" } : [],
98+
.. msbuildArgs.NoLogo is true ? new string[1] { "--nologo" } : [],
10499
.. msbuildArgs.OtherMSBuildArgs
105100
];
106101

src/Cli/Microsoft.DotNet.Cli.Utils/Polyfills.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,24 @@
44
#if NET472
55

66
#pragma warning disable IDE0130 // Namespace does not match folder structure
7-
namespace System.Runtime.CompilerServices;
8-
#pragma warning restore IDE0130 // Namespace does not match folder structure
7+
namespace System.Runtime.CompilerServices {
8+
9+
internal static class IsExternalInit
10+
{
11+
}
12+
13+
}
914

10-
internal static class IsExternalInit
15+
namespace System.Diagnostics.CodeAnalysis
1116
{
17+
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
18+
internal sealed class NotNullWhenAttribute : Attribute
19+
{
20+
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
21+
22+
public bool ReturnValue { get; }
23+
}
1224
}
25+
#pragma warning restore IDE0130 // Namespace does not match folder structure
1326

1427
#endif

src/Cli/dotnet/Commands/Build/BuildCommandParser.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,7 @@ internal static class BuildCommandParser
3535
Arity = ArgumentArity.Zero
3636
}.ForwardAs("--property:BuildProjectReferences=false");
3737

38-
public static readonly Option<bool> NoLogoOption = new ForwardedOption<bool>("--nologo")
39-
{
40-
Description = CliCommandStrings.BuildCmdNoLogo,
41-
Arity = ArgumentArity.Zero
42-
}.ForwardAs("-nologo");
38+
public static readonly Option<bool> NoLogoOption = CommonOptions.NoLogoOption();
4339

4440
public static readonly Option<bool> NoRestoreOption = CommonOptions.NoRestoreOption;
4541

0 commit comments

Comments
 (0)