Skip to content

Commit

Permalink
Use distro detection from Microsoft.DotNet.PlatformAbstractions (dotn…
Browse files Browse the repository at this point in the history
  • Loading branch information
krwq authored Nov 3, 2017
1 parent 03e849f commit f3f741e
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public static partial class PlatformDetection
public static System.PlatformDetection.Range[] FrameworkRanges { get { throw null; } }
public static bool HasWindowsShell { get { throw null; } }
public static bool IsArmProcess { get { throw null; } }
public static bool IsCentos7 { get { throw null; } }
public static bool IsDebian { get { throw null; } }
public static bool IsDebian8 { get { throw null; } }
public static bool IsDrawingSupported { get { throw null; } }
Expand All @@ -55,7 +54,7 @@ public static partial class PlatformDetection
public static bool IsNetNative { get { throw null; } }
public static bool IsNonZeroLowerBoundArraySupported { get { throw null; } }
public static bool IsNotArmProcess { get { throw null; } }
public static bool IsNotFedoraOrRedHatOrCentos { get { throw null; } }
public static bool IsNotFedoraOrRedHatFamily { get { throw null; } }
public static bool IsNotMacOsHighSierraOrHigher { get { throw null; } }
public static bool IsNotNetNativeRunningAsConsoleApp { get { throw null; } }
public static bool IsNotOneCoreUAP { get { throw null; } }
Expand All @@ -70,10 +69,11 @@ public static partial class PlatformDetection
public static bool IsOSX { get { throw null; } }
public static bool IsSuperUser { get { throw null; } }
public static bool IsTizen { get { throw null; } }
public static bool IsRedHat { get { throw null; } }
public static bool IsNotRedHat { get { throw null; } }
public static bool IsRedHat69 { get { throw null; } }
public static bool IsNotRedHat69 { get { throw null; } }
public static bool IsRedHatFamily { get { throw null; } }
public static bool IsNotRedHatFamily { get { throw null; } }
public static bool IsRedHatFamily6 { get { throw null; } }
public static bool IsRedHatFamily7 { get { throw null; } }
public static bool IsNotRedHatFamily6 { get { throw null; } }
public static bool IsUap { get { throw null; } }
public static Version ICUVersion { get { return null; } }
public static bool IsUbuntu { get { throw null; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
<ReferenceFromRuntime Include="xunit.core" />
<ReferenceFromRuntime Include="Xunit.NetCore.Extensions" />
<ReferenceFromRuntime Include="xunit.assert" />
<ReferenceFromRuntime Include="Microsoft.DotNet.PlatformAbstractions" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<Reference Include="System.Security.Principal.Windows" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,27 @@ public static partial class PlatformDetection
public static bool IsOpenSUSE => IsDistroAndVersion("opensuse");
public static bool IsUbuntu => IsDistroAndVersion("ubuntu");
public static bool IsDebian => IsDistroAndVersion("debian");
public static bool IsDebian8 => IsDistroAndVersion("debian", "8");
public static bool IsUbuntu1404 => IsDistroAndVersion("ubuntu", "14.04");
public static bool IsUbuntu1604 => IsDistroAndVersion("ubuntu", "16.04");
public static bool IsUbuntu1704 => IsDistroAndVersion("ubuntu", "17.04");
public static bool IsUbuntu1710 => IsDistroAndVersion("ubuntu", "17.10");
public static bool IsCentos7 => IsDistroAndVersion("centos", "7");
public static bool IsDebian8 => IsDistroAndVersion("debian", 8);
public static bool IsUbuntu1404 => IsDistroAndVersion("ubuntu", 14, 4);
public static bool IsUbuntu1604 => IsDistroAndVersion("ubuntu", 16, 4);
public static bool IsUbuntu1704 => IsDistroAndVersion("ubuntu", 17, 4);
public static bool IsUbuntu1710 => IsDistroAndVersion("ubuntu", 17, 10);
public static bool IsTizen => IsDistroAndVersion("tizen");
public static bool IsNotFedoraOrRedHatOrCentos => !IsDistroAndVersion("fedora") && !IsDistroAndVersion("rhel") && !IsDistroAndVersion("centos");
public static bool IsFedora => IsDistroAndVersion("fedora");
public static bool IsWindowsNanoServer => false;
public static bool IsWindowsServerCore => false;
public static bool IsWindowsAndElevated => false;
public static bool IsWindowsRedStone2 => false;
public static bool IsWindowsRedStone2 => false;

public static bool IsRedHat => IsDistroAndVersion("rhel") || IsDistroAndVersion("rhl");
public static bool IsNotRedHat => !IsRedHat;
public static bool IsRedHat69 => IsDistroAndVersion("rhel", "6.9") || IsDistroAndVersion("rhl", "6.9");
public static bool IsNotRedHat69 => !IsRedHat69;
// RedHat family covers RedHat and CentOS
public static bool IsRedHatFamily => IsRedHatFamilyAndVersion();
public static bool IsNotRedHatFamily => !IsRedHatFamily;
public static bool IsRedHatFamily6 => IsRedHatFamilyAndVersion(6);
public static bool IsNotRedHatFamily6 => !IsRedHatFamily6;
public static bool IsRedHatFamily7 => IsRedHatFamilyAndVersion(7);
public static bool IsNotFedoraOrRedHatFamily => !IsFedora && !IsRedHatFamily;

public static Version OSXKernelVersion { get; } = GetOSXKernelVersion();
public static Version OSXKernelVersion { get; } = ToVersion(Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion);

public static string GetDistroVersionString()
{
Expand All @@ -59,9 +60,9 @@ public static string GetDistroVersionString()
return "OSX Version=" + s_osxProductVersion.ToString();
}

DistroInfo v = ParseOsReleaseFile();
DistroInfo v = GetDistroInfo();

return "Distro=" + v.Id + " VersionId=" + v.VersionId + " Pretty=" + v.PrettyName + " Version=" + v.Version;
return "Distro=" + v.Id + " VersionId=" + v.VersionId;
}

private static readonly Version s_osxProductVersion = GetOSXProductVersion();
Expand All @@ -81,131 +82,25 @@ private static Version GetICUVersion()
ver >> 24);
}

private static DistroInfo ParseOsReleaseFile()
static Version ToVersion(string versionString)
{
Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Linux));
if (versionString.IndexOf('.') != -1)
return new Version(versionString);

DistroInfo ret = new DistroInfo();
ret.Id = "";
ret.VersionId = "";
ret.Version = "";
ret.PrettyName = "";

if (File.Exists("/etc/os-release"))
{
foreach (string line in File.ReadLines("/etc/os-release"))
{
if (line.StartsWith("ID=", System.StringComparison.Ordinal))
{
ret.Id = RemoveQuotes(line.Substring("ID=".Length));
}
else if (line.StartsWith("VERSION_ID=", System.StringComparison.Ordinal))
{
ret.VersionId = RemoveQuotes(line.Substring("VERSION_ID=".Length));
}
else if (line.StartsWith("VERSION=", System.StringComparison.Ordinal))
{
ret.Version = RemoveQuotes(line.Substring("VERSION=".Length));
}
else if (line.StartsWith("PRETTY_NAME=", System.StringComparison.Ordinal))
{
ret.PrettyName = RemoveQuotes(line.Substring("PRETTY_NAME=".Length));
}
}
}
else
{
string fileName = null;
if (File.Exists("/etc/redhat-release"))
fileName = "/etc/redhat-release";

if (fileName == null && File.Exists("/etc/system-release"))
fileName = "/etc/system-release";

if (fileName != null)
{
// Parse the format like the following line:
// Red Hat Enterprise Linux Server release 7.3 (Maipo)
using (StreamReader file = new StreamReader(fileName))
{
string line = file.ReadLine();
if (!String.IsNullOrEmpty(line))
{
if (line.StartsWith("Red Hat Enterprise Linux", StringComparison.OrdinalIgnoreCase))
{
ret.Id = "rhel";
}
else if (line.StartsWith("Centos", StringComparison.OrdinalIgnoreCase))
{
ret.Id = "centos";
}
else if (line.StartsWith("Red Hat", StringComparison.OrdinalIgnoreCase))
{
ret.Id = "rhl";
}
else
{
// automatically generate the distro label
string [] words = line.Split(' ');
StringBuilder sb = new StringBuilder();

foreach (string word in words)
{
if (word.Length > 0)
{
if (Char.IsNumber(word[0]) ||
word.Equals("release", StringComparison.OrdinalIgnoreCase) ||
word.Equals("server", StringComparison.OrdinalIgnoreCase))
{
break;
}
sb.Append(Char.ToLower(word[0]));
}
}
ret.Id = sb.ToString();
}

int i = 0;
while (i < line.Length && !Char.IsNumber(line[i])) // stop at first number
i++;

if (i < line.Length)
{
int j = i + 1;
while (j < line.Length && (Char.IsNumber(line[j]) || line[j] == '.'))
j++;

ret.VersionId = line.Substring(i, j - i);
ret.Version = line.Substring(i, line.Length - i);
}

ret.PrettyName = line;
}
}
}
}

return ret;
// minor version is required by Version
// let's default it to 0
return new Version(int.Parse(versionString), 0);
}

private static string RemoveQuotes(string s)
private static DistroInfo GetDistroInfo() => new DistroInfo()
{
s = s.Trim();
if (s.Length >= 2 && s[0] == '"' && s[s.Length - 1] == '"')
{
// Remove quotes.
s = s.Substring(1, s.Length - 2);
}

return s;
}
Id = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystem,
VersionId = ToVersion(Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion)
};

private struct DistroInfo
private static bool IsRedHatFamilyAndVersion(int major = -1, int minor = -1, int build = -1, int revision = -1)
{
public string Id { get; set; }
public string VersionId { get; set; }
public string Version { get; set; }
public string PrettyName { get; set; }
return IsDistroAndVersion((distro) => distro == "rhel" || distro == "centos", major, minor, build, revision);
}

/// <summary>
Expand All @@ -214,12 +109,17 @@ private struct DistroInfo
/// <param name="distroId">The distribution id.</param>
/// <param name="versionId">The distro version. If omitted, compares the distro only.</param>
/// <returns>Whether the OS platform matches the given Linux distro and optional version.</returns>
private static bool IsDistroAndVersion(string distroId, string versionId = null)
private static bool IsDistroAndVersion(string distroId, int major = -1, int minor = -1, int build = -1, int revision = -1)
{
return IsDistroAndVersion((distro) => distro == distroId, major, minor, build, revision);
}

private static bool IsDistroAndVersion(Predicate<string> distroPredicate, int major = -1, int minor = -1, int build = -1, int revision = -1)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
DistroInfo v = ParseOsReleaseFile();
if (v.Id == distroId && (versionId == null || v.VersionId == versionId))
DistroInfo v = GetDistroInfo();
if (distroPredicate(v.Id) && VersionEquivalentWith(major, minor, build, revision, v.VersionId))
{
return true;
}
Expand All @@ -228,18 +128,12 @@ private static bool IsDistroAndVersion(string distroId, string versionId = null)
return false;
}

private static Version GetOSXKernelVersion()
private static bool VersionEquivalentWith(int major, int minor, int build, int revision, Version actualVersionId)
{
if (IsOSX)
{
byte[] bytes = new byte[256];
IntPtr bytesLength = new IntPtr(bytes.Length);
Assert.Equal(0, sysctlbyname("kern.osrelease", bytes, ref bytesLength, null, IntPtr.Zero));
string versionString = Encoding.UTF8.GetString(bytes);
return Version.Parse(versionString);
}

return new Version(0, 0, 0);
return (major == -1 || major == actualVersionId.Major)
&& (minor == -1 || minor == actualVersionId.Minor)
&& (build == -1 || build == actualVersionId.Build)
&& (revision == -1 || revision == actualVersionId.Revision);
}

private static Version GetOSXProductVersion()
Expand Down Expand Up @@ -302,5 +196,11 @@ private static Version GetOSXProductVersion()
private static extern int GlobalizationNative_GetICUVersion();

public static bool IsSuperUser => geteuid() == 0;

private struct DistroInfo
{
public string Id { get; set; }
public Version VersionId { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ public static partial class PlatformDetection
public static bool IsUbuntu1604 => false;
public static bool IsUbuntu1704 => false;
public static bool IsUbuntu1710 => false;
public static bool IsCentos7 => false;
public static bool IsTizen => false;
public static bool IsNotFedoraOrRedHatOrCentos => true;
public static bool IsNotFedoraOrRedHatFamily => true;
public static bool IsFedora => false;
public static bool IsWindowsNanoServer => (IsNotWindowsIoTCore && GetInstallationType().Equals("Nano Server", StringComparison.OrdinalIgnoreCase));
public static bool IsWindowsServerCore => GetInstallationType().Equals("Server Core", StringComparison.OrdinalIgnoreCase);
public static int WindowsVersion => GetWindowsVersion();
public static bool IsMacOsHighSierraOrHigher { get; } = false;
public static Version ICUVersion => new Version(0, 0, 0, 0);
public static bool IsRedHat => false;
public static bool IsNotRedHat => true;
public static bool IsRedHat69 => false;
public static bool IsNotRedHat69 => true;
public static bool IsRedHatFamily => false;
public static bool IsNotRedHatFamily => true;
public static bool IsRedHatFamily6 => false;
public static bool IsRedHatFamily7 => false;
public static bool IsNotRedHatFamily6 => true;

public static bool IsWindows10Version1607OrGreater =>
GetWindowsVersion() == 10 && GetWindowsMinorVersion() == 0 && GetWindowsBuildNumber() >= 14393;
Expand Down
10 changes: 5 additions & 5 deletions src/libraries/System.Drawing.Common/tests/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public static bool GetGdiplusIsAvailable()

public static bool GetRecentGdiPlusIsAvailable2()
{
// CentOS 7, RHEL 7 and Ubuntu 14.04, as well as Fedora 25 and OpenSUSE 4.22 are running outdated versions of libgdiplus
if (PlatformDetection.IsCentos7 || PlatformDetection.IsRedHat || PlatformDetection.IsUbuntu1404 || PlatformDetection.IsFedora || PlatformDetection.IsOpenSUSE)
// RedHat and Ubuntu 14.04, as well as Fedora 25 and OpenSUSE 4.22 are running outdated versions of libgdiplus
if (PlatformDetection.IsRedHatFamily || PlatformDetection.IsUbuntu1404 || PlatformDetection.IsFedora || PlatformDetection.IsOpenSUSE)
{
return false;
}
Expand All @@ -58,7 +58,7 @@ public static bool GetRecentGdiPlusIsAvailable2()

public static bool GetGdiPlusIsAvailableNotRedhat73()
{
if (PlatformDetection.IsRedHat)
if (PlatformDetection.IsRedHatFamily)
{
return false;
}
Expand All @@ -78,8 +78,8 @@ public static bool GetGdiPlusIsAvailableNotWindows7()

public static bool GetRecentGdiPlusIsAvailable()
{
// CentOS 7, RHEL 7 and Ubuntu 14.04 are running outdated versions of libgdiplus
if (PlatformDetection.IsCentos7 || PlatformDetection.IsRedHat || PlatformDetection.IsUbuntu1404)
// RedHat and Ubuntu 14.04 are running outdated versions of libgdiplus
if (PlatformDetection.IsRedHatFamily || PlatformDetection.IsUbuntu1404)
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static string JaJPAbbreviatedEraName()
public static string[] FrFRDayNames()
{
#if !uap
if (PlatformDetection.IsOSX && PlatformDetection.OSXKernelVersion < new Version(16, 0))
if (PlatformDetection.IsOSX && PlatformDetection.OSXKernelVersion < new Version(10, 12))
{
return new string[] { "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" };
}
Expand All @@ -41,7 +41,7 @@ public static string[] FrFRDayNames()
public static string[] FrFRAbbreviatedDayNames()
{
#if !uap
if (PlatformDetection.IsOSX && PlatformDetection.OSXKernelVersion < new Version(16, 0))
if (PlatformDetection.IsOSX && PlatformDetection.OSXKernelVersion < new Version(10, 12))
{
return new string[] { "Dim.", "Lun.", "Mar.", "Mer.", "Jeu.", "Ven.", "Sam." };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public void UnixShouldBeAbleToDeleteHiddenDirectory()
[Trait(XunitConstants.Category, XunitConstants.RequiresElevation)]
public void Unix_NotFoundDirectory_ReadOnlyVolume()
{
if (PlatformDetection.IsRedHat69)
if (PlatformDetection.IsRedHatFamily6)
return; // [ActiveIssue(https://github.com/dotnet/corefx/issues/21920)]

ReadOnly_FileSystemHelper(readOnlyDirectory =>
Expand Down
Loading

0 comments on commit f3f741e

Please sign in to comment.