< Summary - ZhEaIsNsAaBn.Libraries coverage (affected: 23 packages)

Information
Class: ZhEaIsNsAaBn.DbSeeder.Tool.ToolProcess
Assembly: ZhEaIsNsAaBn.DbSeeder.Tool
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.DbSeeder.Tool/ToolProcess.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 33
Coverable lines: 33
Total lines: 88
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
get_Dotnet()0%4260%
CaptureAsync()0%620%
RunAsync()0%2040%
Start(...)0%2040%
Trace(...)0%620%

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.DbSeeder.Tool/ToolProcess.cs

#LineLine coverage
 1using System.Diagnostics;
 2
 3namespace ZhEaIsNsAaBn.DbSeeder.Tool;
 4
 5/// <summary>Runs <c>dotnet</c>: captured (msbuild, build) or on the real terminal (the command itself).</summary>
 6internal sealed class ToolProcess
 7{
 8    private readonly TextWriter _log;
 9    private readonly bool       _verbose;
 10
 11
 012    public ToolProcess( TextWriter log, bool verbose )
 13    {
 014        _log     = log;
 015        _verbose = verbose;
 016    }
 17
 18
 19    /// The dotnet that runs this tool when the SDK says so, else the one on PATH.
 020    public static string Dotnet => System.Environment.GetEnvironmentVariable( "DOTNET_HOST_PATH" ) is { Length: > 0 } ho
 21
 22
 23    /// <summary>Runs <c>dotnet <paramref name="args"/></c> with stdout + stderr captured.</summary>
 24    public async Task<(int Code, string Output)> CaptureAsync( IReadOnlyList<string> args )
 25    {
 026        var start = Start( args, null );
 027        start.RedirectStandardOutput = true;
 028        start.RedirectStandardError  = true;
 29        // A reused MSBuild node (or the MSBuild server) inherits the redirected output and lives on for minutes:
 30        // reading the output to its end would wait for it.
 031        start.Environment[ "MSBUILDDISABLENODEREUSE" ]       = "1";
 032        start.Environment[ "DOTNET_CLI_USE_MSBUILD_SERVER" ] = "0";
 33
 034        Trace( start );
 35
 036        using var process = Process.Start( start ) ?? throw new ToolException( "dotnet could not be started." );
 37
 038        var stdout = process.StandardOutput.ReadToEndAsync();
 039        var stderr = process.StandardError.ReadToEndAsync();
 40
 041        await process.WaitForExitAsync().ConfigureAwait( false );
 42
 043        return ( process.ExitCode, ( await stdout.ConfigureAwait( false ) ) + ( await stderr.ConfigureAwait( false ) ) )
 044    }
 45
 46    /// <summary>
 47    /// Runs <c>dotnet <paramref name="args"/></c> on the inherited terminal (nothing redirected: prompts and colours wo
 48    /// stdin stays redirected), in <paramref name="workingDirectory"/>. Ctrl+C reaches it directly; this process just w
 49    /// </summary>
 50    public async Task<int> RunAsync( IReadOnlyList<string> args, string workingDirectory, IReadOnlyDictionary<string, st
 51    {
 052        var start = Start( args, workingDirectory );
 53
 054        foreach ( var (name, value) in environment ) { start.Environment[ name ] = value; }
 55
 056        Trace( start );
 57
 058        using var process = Process.Start( start ) ?? throw new ToolException( "dotnet could not be started." );
 59
 060        ConsoleCancelEventHandler wait = ( _, e ) => e.Cancel = true;
 061        Console.CancelKeyPress += wait;
 62
 63        try
 64        {
 065            await process.WaitForExitAsync().ConfigureAwait( false );
 66
 067            return process.ExitCode;
 68        }
 069        finally { Console.CancelKeyPress -= wait; }
 070    }
 71
 72
 73    private static ProcessStartInfo Start( IReadOnlyList<string> args, string? workingDirectory )
 74    {
 075        var start = new ProcessStartInfo( Dotnet ) { UseShellExecute = false };
 76
 077        foreach ( var arg in args ) { start.ArgumentList.Add( arg ); }
 78
 079        if ( workingDirectory is not null ) { start.WorkingDirectory = workingDirectory; }
 80
 081        return start;
 82    }
 83
 84    private void Trace( ProcessStartInfo start )
 85    {
 086        if ( _verbose ) { _log.WriteLine( $"> {start.FileName} {string.Join( " ", start.ArgumentList.Select( a => a.Cont
 087    }
 88}