Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/dotnet-ef/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ internal static class Program
{
private static int Main(string[] args)
{
// Redirect Console.Out to stderr so that help text and diagnostics
// don't pollute stdout. Actual data output uses the original stdout saved by Reporter.
Reporter.SetStdOut(Console.Out);
Console.SetOut(Console.Error);

var app = new CommandLineApplication(throwOnUnexpectedArg: false) { Name = "dotnet ef" };

new RootCommand().Configure(app);
Expand Down
10 changes: 6 additions & 4 deletions src/dotnet-ef/RootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected override int Execute(string[] _)
{
var commands = _args!.TakeWhile(a => a[0] != '-').ToList();
if (_help!.HasValue()
|| ShouldHelp(commands))
|| ShouldHelp(commands, _args!))
{
return ShowHelp(_help.HasValue(), commands);
}
Expand Down Expand Up @@ -333,9 +333,11 @@ private static string GetVersion()
=> typeof(RootCommand).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()!
.InformationalVersion;

private static bool ShouldHelp(IReadOnlyList<string> commands)
=> commands.Count == 0
|| (commands.Count == 1
private static bool ShouldHelp(IReadOnlyList<string> commands, IList<string> args)
=> args.Count == 0
|| commands.Count == 0
|| (args.Count == 1
&& commands.Count == 1
&& (commands[0] == "database"
|| commands[0] == "dbcontext"
|| commands[0] == "migrations"));
Expand Down
1 change: 1 addition & 0 deletions src/ef/AnsiConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.EntityFrameworkCore.Tools;
internal static class AnsiConsole
{
public static readonly AnsiTextWriter Out = new(Console.Out);
public static readonly AnsiTextWriter Error = new(Console.Error);

public static void WriteLine(string? text)
=> Out.WriteLine(text);
Expand Down
6 changes: 6 additions & 0 deletions src/ef/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ private static int Main(string[] args)
Console.OutputEncoding = Encoding.UTF8;
}

// Redirect Console.Out to stderr so that any user-configured logging providers
// (e.g. ConsoleLogger) don't pollute stdout with diagnostic messages.
// Actual data output uses the original stdout saved by Reporter.
Reporter.SetStdOut(Console.Out);
Console.SetOut(Console.Error);

var app = new CommandLineApplication { Name = "ef" };

new RootCommand().Configure(app);
Expand Down
39 changes: 33 additions & 6 deletions src/ef/Reporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,31 @@ internal static class Reporter
public const string DataPrefix = "data: ";
public const string VerbosePrefix = "verbose: ";

private static TextWriter _stdOut = Console.Out;
private static AnsiTextWriter _stdOutAnsi = new(Console.Out);

public static bool IsVerbose { get; set; }
public static bool NoColor { get; set; }
public static bool PrefixOutput { get; set; }

public static void SetStdOut(TextWriter writer)
{
_stdOut = writer;
_stdOutAnsi = new AnsiTextWriter(writer);
}

[return: NotNullIfNotNull(nameof(value))]
public static string? Colorize(string? value, Func<string?, string> colorizeFunc)
=> NoColor ? value : colorizeFunc(value);

public static void WriteError(string? message)
=> WriteLine(Prefix(ErrorPrefix, Colorize(message, x => Bold + Red + x + Reset)));
=> WriteStdErr(Prefix(ErrorPrefix, Colorize(message, x => Bold + Red + x + Reset)));

public static void WriteWarning(string? message)
=> WriteLine(Prefix(WarningPrefix, Colorize(message, x => Bold + Yellow + x + Reset)));
=> WriteStdErr(Prefix(WarningPrefix, Colorize(message, x => Bold + Yellow + x + Reset)));

public static void WriteInformation(string? message)
=> WriteLine(Prefix(InfoPrefix, message));
=> WriteStdErr(Prefix(InfoPrefix, message));

public static void WriteData(string? message)
=> WriteLine(Prefix(DataPrefix, Colorize(message, x => Bold + Gray + x + Reset)));
Expand All @@ -38,7 +47,7 @@ public static void WriteVerbose(string? message)
{
if (IsVerbose)
{
WriteLine(Prefix(VerbosePrefix, Colorize(message, x => Bold + Black + x + Reset)));
WriteStdErr(Prefix(VerbosePrefix, Colorize(message, x => Bold + Black + x + Reset)));
}
}

Expand All @@ -55,11 +64,29 @@ private static void WriteLine(string? value)
{
if (NoColor)
{
Console.WriteLine(value);
_stdOut.WriteLine(value);
}
else
{
_stdOutAnsi.WriteLine(value);
}
}

private static void WriteStdErr(string? value)
{
if (PrefixOutput)
{
WriteLine(value);
return;
}

if (NoColor)
{
Console.Error.WriteLine(value);
}
else
{
AnsiConsole.WriteLine(value);
AnsiConsole.Error.WriteLine(value);
}
}
}
Loading