forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRuntime.cs
More file actions
129 lines (113 loc) · 4.75 KB
/
Runtime.cs
File metadata and controls
129 lines (113 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using NuGet.Versioning;
using Semmle.Util;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
/// <summary>
/// Locates .NET Runtimes.
/// </summary>
internal partial class Runtime
{
private const string netCoreApp = "Microsoft.NETCore.App";
private const string aspNetCoreApp = "Microsoft.AspNetCore.App";
private readonly IDotNet dotNet;
private readonly Lazy<Dictionary<string, DotNetVersion>> newestRuntimes;
private Dictionary<string, DotNetVersion> NewestRuntimes => newestRuntimes.Value;
public Runtime(IDotNet dotNet)
{
this.dotNet = dotNet;
this.newestRuntimes = new(GetNewestRuntimes);
}
[GeneratedRegex(@"^(\S+)\s(\d+\.\d+\.\d+(-[a-z]+\.\d+\.\d+\.\d+)?)\s\[(.+)\]$")]
private static partial Regex RuntimeRegex();
/// <summary>
/// Parses the output of `dotnet --list-runtimes` to get a map from a runtime to the location of
/// the newest version of the runtime.
/// It is assume that the format of a listed runtime is something like:
/// Microsoft.NETCore.App 7.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
/// </summary>
private static Dictionary<string, DotNetVersion> ParseRuntimes(IList<string> listed)
{
// Parse listed runtimes.
var runtimes = new Dictionary<string, DotNetVersion>();
var regex = RuntimeRegex();
listed.ForEach(r =>
{
var match = regex.Match(r);
if (match.Success && NuGetVersion.TryParse(match.Groups[2].Value, out var version))
{
runtimes.AddOrUpdateToLatest(match.Groups[1].Value, new DotNetVersion(match.Groups[4].Value, version));
}
});
return runtimes;
}
/// <summary>
/// Returns a dictionary mapping runtimes to their newest version.
/// </summary>
internal Dictionary<string, DotNetVersion> GetNewestRuntimes()
{
var listed = dotNet.GetListedRuntimes();
return ParseRuntimes(listed);
}
/// <summary>
/// Locates .NET Desktop Runtimes.
/// This includes Mono and Microsoft.NET.
/// </summary>
private IEnumerable<string> DesktopRuntimes
{
get
{
if (Directory.Exists(@"C:\Windows\Microsoft.NET\Framework64"))
{
return Directory.EnumerateDirectories(@"C:\Windows\Microsoft.NET\Framework64", "v*")
.OrderByDescending(Path.GetFileName);
}
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
string[] monoDirs = monoPath is not null
? [Path.GetFullPath(Path.Combine(monoPath, "..", "lib", "mono")), monoPath]
: ["/usr/lib/mono", "/usr/local/mono", "/usr/local/bin/mono", @"C:\Program Files\Mono\lib\mono"];
var monoDir = monoDirs.FirstOrDefault(Directory.Exists);
if (monoDir is not null)
{
return Directory.EnumerateDirectories(monoDir)
.Where(d => char.IsDigit(Path.GetFileName(d)[0]))
.OrderByDescending(Path.GetFileName);
}
return [];
}
}
private string? GetVersion(string framework)
{
if (NewestRuntimes.TryGetValue(framework, out var version))
{
var refAssemblies = version.FullPathReferenceAssemblies;
return Directory.Exists(refAssemblies)
? refAssemblies
: version.FullPath;
}
return null;
}
/// <summary>
/// Gets the Dotnet Core location.
/// </summary>
public string? NetCoreRuntime => GetVersion(netCoreApp);
/// <summary>
/// Gets the .NET Framework location. Either the installation folder on Windows or Mono
/// </summary>
public string? DesktopRuntime => DesktopRuntimes?.FirstOrDefault();
/// <summary>
/// Gets the executing runtime location, this is the self contained runtime shipped in the CodeQL CLI bundle.
/// </summary>
public string ExecutingRuntime => RuntimeEnvironment.GetRuntimeDirectory();
/// <summary>
/// Gets the ASP.NET Core location.
/// </summary>
public string? AspNetCoreRuntime => GetVersion(aspNetCoreApp);
}
}