TeamCity.CSharpInteractive/ProcessMonitor.cs (72 lines of code) (raw):
// ReSharper disable ClassNeverInstantiated.Global
namespace TeamCity.CSharpInteractive;
using HostApi;
internal class ProcessMonitor : IProcessMonitor
{
private readonly ILog<ProcessMonitor> _log;
private readonly IEnvironment _environment;
private int? _processId;
public ProcessMonitor(
ILog<ProcessMonitor> log,
IEnvironment environment)
{
_log = log;
_environment = environment;
}
public void Started(IStartInfo startInfo, int processId)
{
_processId = processId;
var executable = new List<Text>
{
new($"{startInfo.GetDescription(processId)} process started ", Color.Highlighted),
new(startInfo.ExecutablePath.EscapeArg())
};
foreach (var arg in startInfo.Args)
{
executable.Add(Text.Space);
executable.Add(new Text(arg.EscapeArg()));
}
_log.Info(executable.ToArray());
var workingDirectory = startInfo.WorkingDirectory;
if (string.IsNullOrWhiteSpace(workingDirectory))
{
workingDirectory = _environment.GetPath(SpecialFolder.Working);
}
if (!string.IsNullOrWhiteSpace(workingDirectory))
{
_log.Info(new Text("in directory: "), new Text(workingDirectory.EscapeArg()));
}
}
public ProcessResult Finished(IStartInfo startInfo, long elapsedMilliseconds, ProcessState state, int? exitCode = default, Exception? error = default) =>
new(
startInfo,
_processId,
state,
elapsedMilliseconds,
GetFooter(startInfo,exitCode, elapsedMilliseconds, state).ToArray(),
exitCode,
error);
private IEnumerable<Text> GetFooter(IStartInfo startInfo, int? exitCode, long elapsedMilliseconds, ProcessState? state)
{
string? stateText;
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
switch (state)
{
case ProcessState.Failed:
stateText = exitCode.HasValue ? "failed" : "failed to start";
break;
case ProcessState.Canceled:
stateText = "canceled";
break;
default:
stateText = "finished";
break;
}
yield return new Text($"{startInfo.GetDescription(_processId)} process ", Color.Highlighted);
yield return new Text(stateText, Color.Highlighted);
yield return new Text($" (in {elapsedMilliseconds} ms)");
if (exitCode.HasValue)
{
yield return new Text($" with exit code {exitCode}");
}
yield return new Text(".");
}
}