Skip to content

Instantly share code, notes, and snippets.

@abock
Created May 21, 2018 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abock/eb676f07b344234f280ccb6adf5a19af to your computer and use it in GitHub Desktop.
Save abock/eb676f07b344234f280ccb6adf5a19af to your computer and use it in GitHub Desktop.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Xamarin.Interactive
{
static class RuntimeIdentifier
{
public static string CurrentProcessRid { get; }
static RuntimeIdentifier ()
{
string rid;
if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows))
rid = "win-";
else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX))
rid = "osx-";
else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux))
rid = "linux-";
else
rid = "any-";
CurrentProcessRid = rid + RuntimeInformation
.ProcessArchitecture
.ToString ()
.ToLowerInvariant ();
}
static Lazy<IReadOnlyDictionary<string, IReadOnlyList<string>>> allRids
= new Lazy<IReadOnlyDictionary<string, IReadOnlyList<string>>> (() => {
var rids = new Dictionary<string, IReadOnlyList<string>> ();
using (var stream = typeof (RuntimeIdentifier)
.Assembly
.GetManifestResourceStream ("netcore-rids.json"))
using (var streamReader = new StreamReader (stream))
using (var jsonReader = new JsonTextReader (streamReader)) {
var root = JObject.Load (jsonReader);
if (root ["runtimes"] is JObject runtimes) {
foreach (var rid in runtimes) {
List<string> imports = null;
if (rid.Value is JObject ridObject &&
ridObject ["#import"] is JArray importsArray) {
imports = importsArray.ToObject<List<string>> ();
}
rids [rid.Key] = imports;
}
}
}
return rids;
});
static readonly ReaderWriterLockSlim expansionCacheLock
= new ReaderWriterLockSlim ();
static readonly Dictionary<string, List<string>> expansionCache
= new Dictionary<string, List<string>> ();
public static IReadOnlyList<string> Expand (string rid)
{
expansionCacheLock.EnterUpgradeableReadLock ();
try {
if (!expansionCache.TryGetValue (rid, out var expandedRids)) {
expansionCacheLock.EnterWriteLock ();
try {
var ridEnum = CoreExpand (rid);
expandedRids = new List<string> (ridEnum);
expansionCache [rid] = expandedRids;
} finally {
expansionCacheLock.ExitWriteLock ();
}
}
return expandedRids;
} finally {
expansionCacheLock.ExitUpgradeableReadLock ();
}
}
static IEnumerable<string> CoreExpand (string rid)
{
yield return rid;
var visitedRids = new HashSet<string> ();
var expandedRids = new List<string> ();
visitedRids.Add (rid);
expandedRids.Add (rid);
for (var i = 0; i < expandedRids.Count; i++) {
if (allRids.Value.TryGetValue (expandedRids [i], out var imports) && imports != null) {
foreach (var importedRid in imports) {
if (visitedRids.Add (importedRid)) {
yield return importedRid;
expandedRids.Add (importedRid);
}
}
}
}
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using Xunit;
namespace Xamarin.Interactive
{
public class RuntimeIdentifierTests
{
[Theory]
[MemberData (nameof (GetTestCases))]
public void Expand (string [] expectedExpansion)
=> Assert.Equal (expectedExpansion, RuntimeIdentifier.Expand (expectedExpansion [0]));
// sampling of https://raw.githubusercontent.com/dotnet/corefx/master/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json
public static IEnumerable<object []> GetTestCases ()
{
yield return new [] {
new [] {
"osx.10.12-x64",
"osx.10.12",
"osx.10.11-x64",
"osx.10.11",
"osx.10.10-x64",
"osx.10.10",
"osx-x64",
"osx",
"unix-x64",
"unix",
"any",
"base"
}
};
yield return new [] {
new [] {
"win7-x64",
"win7",
"win-x64",
"win",
"any",
"base"
}
};
yield return new [] {
new [] {
"fedora.26-x64",
"fedora.26",
"fedora-x64",
"fedora",
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
}
};
yield return new [] {
new [] {
"linux",
"unix",
"any",
"base"
}
};
yield return new [] {
new [] {
"osx",
"unix",
"any",
"base"
}
};
yield return new [] {
new [] {
"any",
"base"
}
};
yield return new [] {
new [] {
"base"
}
};
yield return new [] {
new [] {
"unknown-rid"
}
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment