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

Information
Class: ZhEaIsNsAaBn.DbSeeder.Tool.ToolException
Assembly: ZhEaIsNsAaBn.DbSeeder.Tool
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.DbSeeder.Tool/ProjectMetadata.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 1
Coverable lines: 1
Total lines: 86
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%

File(s)

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

#LineLine coverage
 1using System.Text.Json;
 2
 3namespace ZhEaIsNsAaBn.DbSeeder.Tool;
 4
 5/// <summary>A project's build facts, from <c>dotnet msbuild -getProperty</c> (evaluation only, no injected targets).</s
 6internal sealed record ProjectMetadata( string ProjectFile, string Name, string ProjectDirectory, string TargetFramework
 7                                        string RuntimeConfigFile, IReadOnlyList<string> PackageFolders )
 8{
 9    /// <summary>The project file for <paramref name="path"/>: a .csproj, or the folder holding exactly one.</summary>
 10    /// <exception cref="ToolException">No project or several.</exception>
 11    public static string ResolveProjectFile( string? path, string currentDirectory )
 12    {
 13        var full = Path.GetFullPath( path ?? ".", currentDirectory );
 14
 15        if ( File.Exists( full ) ) { return full; }
 16
 17        if ( !Directory.Exists( full ) ) { throw new ToolException( $"{full} doesn't exist." ); }
 18
 19        var projects = Directory.GetFiles( full, "*.csproj" );
 20
 21        return projects.Length switch
 22        {
 23            1 => projects[ 0 ],
 24            0 => throw new ToolException( $"No project in {full}. Use --project (and --startup-project)." ),
 25            _ => throw new ToolException( $"More than one project in {full}: {string.Join( ", ", projects.Select( Path.G
 26        };
 27    }
 28
 29    /// <summary>The target framework to use: <paramref name="framework"/>, else the project's only one.</summary>
 30    /// <exception cref="ToolException">The project has several and none was picked.</exception>
 31    public static async Task<string> TargetFrameworkAsync( string projectFile, string? framework, string configuration, 
 32    {
 33        if ( framework is not null ) { return framework; }
 34
 35        var properties = await PropertiesAsync( projectFile, null, configuration, process, "TargetFramework", "TargetFra
 36
 37        if ( properties[ "TargetFramework" ] is { Length: > 0 } single ) { return single; }
 38
 39        var frameworks = properties[ "TargetFrameworks" ].Split( ';', StringSplitOptions.RemoveEmptyEntries | StringSpli
 40
 41        return frameworks.Length == 1
 42                   ? frameworks[ 0 ]
 43                   : throw new ToolException( $"{Path.GetFileNameWithoutExtension( projectFile )} targets {string.Join( 
 44    }
 45
 46    /// <summary>The metadata after a build (NuGetPackageFolders comes from the restore).</summary>
 47    public static async Task<ProjectMetadata> ReadAsync( string projectFile, string framework, string configuration, Too
 48    {
 49        var properties = await PropertiesAsync( projectFile, framework, configuration, process, "MSBuildProjectName", "P
 50                                                "ProjectRuntimeConfigFilePath", "NuGetPackageFolders" ).ConfigureAwait( 
 51
 52        return new ProjectMetadata( projectFile, properties[ "MSBuildProjectName" ], properties[ "ProjectDir" ], framewo
 53                                    properties[ "ProjectDepsFilePath" ], properties[ "ProjectRuntimeConfigFilePath" ],
 54                                    properties[ "NuGetPackageFolders" ].Split( ';', StringSplitOptions.RemoveEmptyEntrie
 55    }
 56
 57
 58    private static async Task<Dictionary<string, string>> PropertiesAsync( string projectFile, string? framework, string
 59                                                                            params string[] names )
 60    {
 61        List<string> args = [ "msbuild", projectFile, "-nologo", $"-p:Configuration={configuration}", .. names.Select( n
 62
 63        if ( framework is not null ) { args.Add( $"-p:TargetFramework={framework}" ); }
 64
 65        var (code, output) = await process.CaptureAsync( args ).ConfigureAwait( false );
 66
 67        if ( code != 0 ) { throw new ToolException( $"Reading {Path.GetFileName( projectFile )} failed:\n{output}" ); }
 68
 69        try
 70        {
 71            using var document = JsonDocument.Parse( output );
 72
 73            return names.ToDictionary( n => n, n => document.RootElement.GetProperty( "Properties" ).GetProperty( n ).Ge
 74        }
 75        catch ( JsonException )
 76        {
 77            throw new ToolException( $"Unexpected output from dotnet msbuild -getProperty (SDK 8 or later needed):\n{out
 78        }
 79    }
 80}
 81
 82/// <summary>A tool error: printed as <c>error: …</c>, exit code 2.</summary>
 83internal sealed class ToolException : Exception
 84{
 085    public ToolException( string message ) : base( message ) { }
 86}

Methods/Properties

.ctor(System.String)