Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement dotnet format execution in separated process #54

Merged
merged 4 commits into from
Sep 6, 2023
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
32 changes: 32 additions & 0 deletions Sources/Kysect.Configuin.Core/CliExecution/CmdExecutionResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace Kysect.Configuin.Core.CliExecution;

public class CmdExecutionResult
{
public int ExitCode { get; init; }
public IReadOnlyCollection<string> Errors { get; init; }

public CmdExecutionResult(int exitCode, IReadOnlyCollection<string> errors)
{
ExitCode = exitCode;
Errors = errors;
}

public void ThrowIfAnyError()
{
if (Errors.Count == 1)
throw new CmdProcessException(Errors.Single());

if (Errors.Count > 0)
{
var exceptions = Errors
.Select(m => new CmdProcessException(m))
.ToList();
throw new AggregateException(exceptions);
}

if (ExitCode != 0)
{
throw new CmdProcessException($"Return {ExitCode} exit code.");
}
}
}
67 changes: 67 additions & 0 deletions Sources/Kysect.Configuin.Core/CliExecution/CmdProcess.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Kysect.Configuin.Core.CliExecution;

public class CmdProcess
{
public CmdExecutionResult ExecuteCommand(string command)
{
using var process = new Process();

ProcessStartInfo startInfo = CreateProcessStartInfo(command);

process.StartInfo = startInfo;
process.Start();
process.WaitForExit();

int exitCode = process.ExitCode;
IReadOnlyCollection<string> errors = GetErrors(process);
process.Close();

return new CmdExecutionResult(exitCode, errors);
}

private ProcessStartInfo CreateProcessStartInfo(string command)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
RedirectStandardError = true,
FileName = "cmd.exe",
Arguments = $"/C {command}"
};
}

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
RedirectStandardError = true,
FileName = "sh",
Arguments = $"-c {command}"
};
}

throw new NotSupportedException(RuntimeInformation.OSDescription);
}

private IReadOnlyCollection<string> GetErrors(Process process)
{
var errors = new List<string>();

// TODO: fixed error stream reading
// Line splitting triggered by char limit =_=
while (!process.StandardError.EndOfStream)
{
string? line = process.StandardError.ReadLine();
if (line is not null)
errors.Add(line);
}

return errors;
}
}
12 changes: 12 additions & 0 deletions Sources/Kysect.Configuin.Core/CliExecution/CmdProcessException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Kysect.Configuin.Core.CliExecution;

public class CmdProcessException : Exception
{
public CmdProcessException(string message) : base(message)
{
}

public CmdProcessException() : base("Failed to execute cmd command")
{
}
}
19 changes: 19 additions & 0 deletions Sources/Kysect.Configuin.Core/DotnetFormat/DotnetFormatCli.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Kysect.Configuin.Core.CliExecution;

namespace Kysect.Configuin.Core.DotnetFormat;

public class DotnetFormatCli
{
private readonly CmdProcess _cmdProcess = new CmdProcess();

public void Validate()
{
_cmdProcess.ExecuteCommand("dotnet format -h").ThrowIfAnyError();
}

public void GenerateWarnings(string pathToSolution, string pathToJson)
{

_cmdProcess.ExecuteCommand($"dotnet format \"{pathToSolution}\" --verify-no-changes --report \"{pathToJson}\"").ThrowIfAnyError();
}
}
18 changes: 18 additions & 0 deletions Sources/Kysect.Configuin.Tests/CmdProcessTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using FluentAssertions;
using Kysect.Configuin.Core.CliExecution;
using NUnit.Framework;

namespace Kysect.Configuin.Tests;

public class CmdProcessTests
{
[Test]
public void Execute_ForInvalidCommand_ThrowError()
{
var cmdProcess = new CmdProcess();

CmdExecutionResult cmdExecutionResult = cmdProcess.ExecuteCommand("qwerasdf1234");

cmdExecutionResult.ExitCode.Should().NotBe(0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Kysect.Configuin.Core.DotnetFormat;
using NUnit.Framework;

namespace Kysect.Configuin.Tests.DotnetFormat;

public class DotnetFormatCliTests
{
private readonly DotnetFormatCli _dotnetFormatCli;

public DotnetFormatCliTests()
{
_dotnetFormatCli = new DotnetFormatCli();
}

[Test]
[Ignore("This test require infrastructure")]
public void Validate_FinishedWithoutErrors()
{
_dotnetFormatCli.Validate();
}

[Test]
[Ignore("This test require infrastructure")]
public void GenerateWarnings_CreateReportFile()
{
const string pathToSln = "./../../../../";

_dotnetFormatCli.GenerateWarnings(pathToSln, "sample.json");
}
}