-
-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
… --info output.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
#nullable enable | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
|
||
namespace Buildalyzer.Environment; | ||
|
||
public sealed class DotNetInfo | ||
{ | ||
public Version? SdkVersion { get; init; } | ||
public string? OSName { get; init; } | ||
public string? OSPlatform { get; init; } | ||
public Version? OSVersion { get; init; } | ||
|
||
public DirectoryInfo? BasePath { get; init; } | ||
|
||
public FileInfo? GlobalJson { get; init; } | ||
|
||
public IReadOnlyDictionary<string, DirectoryInfo> SDKs { get; init; } = new Dictionary<string, DirectoryInfo>(); | ||
|
||
public IReadOnlyDictionary<string, DirectoryInfo> Runtimes { get; init; } = new Dictionary<string, DirectoryInfo>(); | ||
|
||
public static DotNetInfo Parse(string? s) | ||
=> Parse(s?.Split([System.Environment.NewLine], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) ?? []); | ||
Check warning on line 26 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 26 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 26 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
|
||
public static DotNetInfo Parse(IEnumerable<string> lines) | ||
{ | ||
var header = string.Empty; | ||
Check warning on line 30 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 30 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
|
||
|
||
Version? sdkVersion = null; | ||
string? osName = null; | ||
string? osPlatform = null; | ||
Version? osVersion = null; | ||
DirectoryInfo? basePath = null; | ||
FileInfo? globalJson = null; | ||
var sdks = new Dictionary<string, DirectoryInfo>(); | ||
Check warning on line 38 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 38 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
|
||
var runtimes = new Dictionary<string, DirectoryInfo>(); | ||
|
||
Check warning on line 40 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 40 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 40 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
foreach (var line in lines?.Select(l => l.Trim()).Where(l => l is { Length: > 0 }) ?? []) | ||
Check warning on line 41 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 41 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 41 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 41 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 41 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
{ | ||
// Update read header. | ||
if (Headers.Contains(line)) | ||
{ | ||
header = line.ToUpperInvariant(); | ||
continue; | ||
} | ||
|
||
switch (header) | ||
{ | ||
case ".NET SDK:": | ||
sdkVersion ??= Version("Version:", line); | ||
break; | ||
|
||
case "RUNTIME ENVIRONMENT:": | ||
basePath ??= BasePath(line); | ||
osName ??= Label("OS Name:", line); | ||
osPlatform ??= Label("OS Platform:", line); | ||
osVersion ??= Version("OS Version:", line); | ||
break; | ||
|
||
case ".NET SDKS INSTALLED:": | ||
case ".NET CORE SDKS INSTALLED:": | ||
AddSdk(line); | ||
break; | ||
|
||
case ".NET RUNTIMES INSTALLED:": | ||
AddRunTime(line); | ||
break; | ||
|
||
case "GLOBAL.JSON FILE:": | ||
globalJson ??= GlobalJson(line); | ||
break; | ||
} | ||
} | ||
|
||
return new DotNetInfo() | ||
{ | ||
SdkVersion = sdkVersion, | ||
OSName = osName, | ||
OSPlatform = osPlatform, | ||
OSVersion = osVersion, | ||
BasePath = basePath, | ||
GlobalJson = globalJson, | ||
SDKs = sdks, | ||
Runtimes = runtimes, | ||
}; | ||
|
||
static Version? Version(string prefix, string line) | ||
=> line.StartsWith(prefix, IgnoreCase) && System.Version.TryParse(line[prefix.Length..].Trim(), out var parsed) | ||
? parsed | ||
: null; | ||
|
||
static string? Label(string prefix,string line) | ||
Check warning on line 95 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 95 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 95 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
=> line.StartsWith(prefix, IgnoreCase) && line[prefix.Length..].Trim() is { Length: > 0 } label | ||
? label | ||
: null; | ||
|
||
static DirectoryInfo? BasePath(string line) | ||
{ | ||
if (line.StartsWith("Base Path:", IgnoreCase)) | ||
{ | ||
var path = line[10..].Trim(); | ||
|
||
// Make sure the base path matches the runtime architecture if on Windows | ||
// Note that this only works for the default installation locations under "Program Files" | ||
if (path.Contains(@"\Program Files\") && !System.Environment.Is64BitProcess) | ||
{ | ||
string newBasePath = path.Replace(@"\Program Files\", @"\Program Files (x86)\"); | ||
if (Directory.Exists(newBasePath)) | ||
{ | ||
path = newBasePath; | ||
} | ||
} | ||
else if (path.Contains(@"\Program Files (x86)\") && System.Environment.Is64BitProcess) | ||
{ | ||
string newBasePath = path.Replace(@"\Program Files (x86)\", @"\Program Files\"); | ||
if (Directory.Exists(newBasePath)) | ||
{ | ||
path = newBasePath; | ||
} | ||
} | ||
|
||
return new DirectoryInfo(path); | ||
} | ||
else | ||
{ | ||
return null; | ||
} | ||
} | ||
|
||
static FileInfo? GlobalJson(string line) | ||
=> line.Equals("Not found", IgnoreCase) | ||
? null | ||
: new FileInfo(line); | ||
|
||
void AddSdk(string line) | ||
{ | ||
if (line.Split(new[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) is { Length: 2 } parts) | ||
{ | ||
sdks[parts[0]] = new(Path.Combine(parts[1], parts[0])); | ||
Check warning on line 142 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 142 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 142 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
} | ||
} | ||
void AddRunTime(string line) | ||
{ | ||
if (line.Split(new[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) is { Length: 2 } parts) | ||
{ | ||
runtimes[parts[0]] = new(parts[1]); | ||
Check warning on line 149 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 149 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 149 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
} | ||
} | ||
} | ||
|
||
private const StringComparison IgnoreCase = StringComparison.OrdinalIgnoreCase; | ||
|
||
private static readonly HashSet<string> Headers = new(StringComparer.InvariantCultureIgnoreCase) | ||
Check warning on line 156 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (windows-latest)
Check warning on line 156 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (ubuntu-latest)
Check warning on line 156 in src/Buildalyzer/Environment/DotNetInfo.cs GitHub Actions / Build (macos-latest)
|
||
{ | ||
".NET SDK:", | ||
"Runtime Environment:", | ||
".NET SDKs installed:", | ||
".NET Core SDKs installed:", | ||
".NET runtimes installed:", | ||
"Other architectures found:", | ||
"global.json file:", | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using System; | ||
using Buildalyzer.Environment; | ||
using FluentAssertions; | ||
using NUnit.Framework; | ||
|
||
namespace Buildalyzer.Tests.Environment; | ||
|
||
public class DotNetInfoFixture | ||
{ | ||
[Test] | ||
public void Parses() | ||
{ | ||
var lines = @" | ||
.NET SDK: | ||
Version: 8.0.200 | ||
Commit: 438cab6a9d | ||
Workload version: 8.0.200-manifests.e575128c | ||
Runtime Environment: | ||
OS Name: Windows | ||
OS Version: 10.0.22631 | ||
OS Platform: Windows10 | ||
RID: win-x64 | ||
Base Path: C:\Program Files\dotnet\sdk\8.0.200\ | ||
.NET workloads installed: | ||
There are no installed workloads to display. | ||
Host: | ||
Version: 8.0.2 | ||
Architecture: x64 | ||
Commit: 1381d5ebd2 | ||
.NET SDKs installed: | ||
8.0.200 [C:\Program Files\dotnet\sdk] | ||
.NET runtimes installed: | ||
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] | ||
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.AspNetCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.AspNetCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.AspNetCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.AspNetCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] | ||
Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 6.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 7.0.0-rc.2.22472.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.NETCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] | ||
Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Microsoft.WindowsDesktop.App 6.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Microsoft.WindowsDesktop.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Microsoft.WindowsDesktop.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Microsoft.WindowsDesktop.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Microsoft.WindowsDesktop.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] | ||
Other architectures found: | ||
x86 [C:\Program Files (x86)\dotnet] | ||
registered at [HKLM\SOFTWARE\dotn | ||
et\Setup\InstalledVersions\x86\InstallLocation] | ||
Environment variables: | ||
Not set | ||
global.json file: | ||
Not found | ||
Learn more: | ||
https://aka.ms/dotnet/info | ||
Download .NET: | ||
https://aka.ms/dotnet/download"; | ||
|
||
var info = DotNetInfo.Parse(lines); | ||
|
||
info.Should().BeEquivalentTo(new | ||
{ | ||
SdkVersion = new Version(8, 0, 200), | ||
OSName = "Windows", | ||
OSVersion = new Version(10, 0, 22631), | ||
OSPlatform = "Windows10", | ||
SDKs = new { Count = 1, }, | ||
Runtimes = new { Count = 25, }, | ||
}); | ||
info.BasePath.ToString().Should().Be(@"C:\Program Files\dotnet\sdk\8.0.200\"); | ||
} | ||
} |