From edd401b1569c83a5bd606c053f6cf515c0c89878 Mon Sep 17 00:00:00 2001 From: Nathan Clarke Date: Thu, 20 Oct 2016 00:17:08 -0600 Subject: [PATCH] Adding GetStandardError to IProcess and RedirectStandardError to ProcessSettings. (#1175) --- .../Tools/DotCover/DotCoverProcessRunner.cs | 5 ++++ .../Tools/OpenCover/OpenCoverProcessRunner.cs | 5 ++++ .../Tools/SpecFlow/SpecFlowProcessRunner.cs | 5 ++++ src/Cake.Core/IO/IProcess.cs | 6 +++++ src/Cake.Core/IO/ProcessRunner.cs | 20 +++++++++++++++- src/Cake.Core/IO/ProcessSettings.cs | 6 +++++ src/Cake.Core/IO/ProcessWrapper.cs | 24 ++++++++++++++++++- src/Cake.Testing/FakeProcess.cs | 19 +++++++++++++++ 8 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/Cake.Common/Tools/DotCover/DotCoverProcessRunner.cs b/src/Cake.Common/Tools/DotCover/DotCoverProcessRunner.cs index 70e0fd1bae..ed350a5521 100644 --- a/src/Cake.Common/Tools/DotCover/DotCoverProcessRunner.cs +++ b/src/Cake.Common/Tools/DotCover/DotCoverProcessRunner.cs @@ -34,6 +34,11 @@ public int GetExitCode() return 0; } + public IEnumerable GetStandardError() + { + return Enumerable.Empty(); + } + public IEnumerable GetStandardOutput() { return Enumerable.Empty(); diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverProcessRunner.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverProcessRunner.cs index cf057e8135..178dbeab96 100644 --- a/src/Cake.Common/Tools/OpenCover/OpenCoverProcessRunner.cs +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverProcessRunner.cs @@ -34,6 +34,11 @@ public int GetExitCode() return 0; } + public IEnumerable GetStandardError() + { + return Enumerable.Empty(); + } + public IEnumerable GetStandardOutput() { return Enumerable.Empty(); diff --git a/src/Cake.Common/Tools/SpecFlow/SpecFlowProcessRunner.cs b/src/Cake.Common/Tools/SpecFlow/SpecFlowProcessRunner.cs index dc51646870..4ce60c59f0 100644 --- a/src/Cake.Common/Tools/SpecFlow/SpecFlowProcessRunner.cs +++ b/src/Cake.Common/Tools/SpecFlow/SpecFlowProcessRunner.cs @@ -34,6 +34,11 @@ public int GetExitCode() return 0; } + public IEnumerable GetStandardError() + { + return Enumerable.Empty(); + } + public IEnumerable GetStandardOutput() { return Enumerable.Empty(); diff --git a/src/Cake.Core/IO/IProcess.cs b/src/Cake.Core/IO/IProcess.cs index 5594ff6da7..3831e4fbd5 100644 --- a/src/Cake.Core/IO/IProcess.cs +++ b/src/Cake.Core/IO/IProcess.cs @@ -30,6 +30,12 @@ public interface IProcess : IDisposable /// The exit code of the process. int GetExitCode(); + /// + /// Get the standard error of process. + /// + /// Returns process error output RedirectStandardError is true + IEnumerable GetStandardError(); + /// /// Get the standard output of process /// diff --git a/src/Cake.Core/IO/ProcessRunner.cs b/src/Cake.Core/IO/ProcessRunner.cs index 36102d3ebd..92c8797316 100644 --- a/src/Cake.Core/IO/ProcessRunner.cs +++ b/src/Cake.Core/IO/ProcessRunner.cs @@ -103,7 +103,25 @@ public IProcess Start(FilePath filePath, ProcessSettings settings) ? SubscribeStandardConsoleOutputQueue(process) : null; - return new ProcessWrapper(process, _log, arguments.FilterUnsafe, consoleOutputQueue); + var consoleErrorQueue = settings.RedirectStandardError + ? SubscribeStandardConsoleErrorQueue(process) + : null; + + return new ProcessWrapper(process, _log, arguments.FilterUnsafe, consoleOutputQueue, arguments.FilterUnsafe, consoleErrorQueue); + } + + private static ConcurrentQueue SubscribeStandardConsoleErrorQueue(Process process) + { + var consoleErrorQueue = new ConcurrentQueue(); + process.ErrorDataReceived += (s, e) => + { + if (e.Data != null) + { + consoleErrorQueue.Enqueue(e.Data); + } + }; + process.BeginErrorReadLine(); + return consoleErrorQueue; } private static ConcurrentQueue SubscribeStandardConsoleOutputQueue(Process process) diff --git a/src/Cake.Core/IO/ProcessSettings.cs b/src/Cake.Core/IO/ProcessSettings.cs index 13ec206278..defa795095 100644 --- a/src/Cake.Core/IO/ProcessSettings.cs +++ b/src/Cake.Core/IO/ProcessSettings.cs @@ -23,6 +23,12 @@ public sealed class ProcessSettings /// The working directory for the process to be started. public DirectoryPath WorkingDirectory { get; set; } + /// + /// Gets or sets a value indicating whether the error output of an application is written to the stream. + /// + /// true if error output should be written to ; otherwise, false. The default is false. + public bool RedirectStandardError { get; set; } + /// /// Gets or sets a value indicating whether the output of an application is written to the stream. /// diff --git a/src/Cake.Core/IO/ProcessWrapper.cs b/src/Cake.Core/IO/ProcessWrapper.cs index ad0d328ac4..b689db9a90 100644 --- a/src/Cake.Core/IO/ProcessWrapper.cs +++ b/src/Cake.Core/IO/ProcessWrapper.cs @@ -14,15 +14,19 @@ internal sealed class ProcessWrapper : IProcess { private readonly Process _process; private readonly ICakeLog _log; + private readonly Func _filterError; private readonly Func _filterOutput; + private readonly ConcurrentQueue _consoleErrorQueue; private readonly ConcurrentQueue _consoleOutputQueue; - public ProcessWrapper(Process process, ICakeLog log, Func filterOutput, ConcurrentQueue consoleOutputQueue) + public ProcessWrapper(Process process, ICakeLog log, Func filterOutput, ConcurrentQueue consoleOutputQueue, Func filterError, ConcurrentQueue consoleErrorQueue) { _process = process; _log = log; _filterOutput = filterOutput ?? (source => "[REDACTED]"); _consoleOutputQueue = consoleOutputQueue; + _filterError = filterError ?? (source => "[REDACTED]"); + _consoleErrorQueue = consoleErrorQueue; } public void WaitForExit() @@ -49,6 +53,24 @@ public int GetExitCode() return _process.ExitCode; } + public IEnumerable GetStandardError() + { + if (_consoleErrorQueue == null) + { + yield break; + } + while (!_consoleErrorQueue.IsEmpty || !_process.HasExited) + { + string line; + if (!_consoleErrorQueue.TryDequeue(out line)) + { + continue; + } + _log.Debug(log => log("{0}", _filterOutput(line))); + yield return line; + } + } + public IEnumerable GetStandardOutput() { if (_consoleOutputQueue == null) diff --git a/src/Cake.Testing/FakeProcess.cs b/src/Cake.Testing/FakeProcess.cs index eaad028c47..356a25a26c 100644 --- a/src/Cake.Testing/FakeProcess.cs +++ b/src/Cake.Testing/FakeProcess.cs @@ -13,6 +13,7 @@ namespace Cake.Testing public sealed class FakeProcess : IProcess { private int _exitCode; + private IEnumerable _standardError; private IEnumerable _standardOutput; /// @@ -48,6 +49,15 @@ public int GetExitCode() return _exitCode; } + /// + /// Get the standard error of process + /// + /// Returns process error output RedirectStandardError is true + public IEnumerable GetStandardError() + { + return _standardError; + } + /// /// Get the standard output of process /// @@ -73,6 +83,15 @@ public void SetExitCode(int exitCode) _exitCode = exitCode; } + /// + /// Sets the standard error. + /// + /// The standard error. + public void SetStandardError(IEnumerable standardError) + { + _standardError = standardError; + } + /// /// Sets the standard output. ///