diff --git a/JetBrains.HabitatDetector/src/HabitatInfo.cs b/JetBrains.HabitatDetector/src/HabitatInfo.cs
index c0a5ca1..bbf158c 100644
--- a/JetBrains.HabitatDetector/src/HabitatInfo.cs
+++ b/JetBrains.HabitatDetector/src/HabitatInfo.cs
@@ -6,15 +6,21 @@
namespace JetBrains.HabitatDetector
{
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
public static partial class HabitatInfo
{
- public static JetClrImplementation ClrImplementation => Helper.ClrImplementation;
- public static Version? MonoVersion => Helper.MonoVersion;
public static JetPlatform Platform => Helper.Platform;
public static JetArchitecture OSArchitecture => Helper.OSArchitecture;
public static JetArchitecture ProcessArchitecture => Helper.ProcessArchitecture;
- public static JetLinuxLibC? LinuxLibC => Helper.LinuxLibC;
public static string OSName => Helper.OSName;
+
+ public static JetClrImplementation ClrImplementation => Helper.ClrImplementation;
+ public static Version? MonoVersion => Helper.MonoVersion;
+
+ public static JetLinuxLibC? LinuxLibC => Helper.LinuxLibC;
+
+ public static Version? MacOSVersion => Helper.MacOSVersion;
+
public static uint? WindowsBuildNumber => Helper.WindowsBuildNumber;
public static JetWindowsInstallationType? WindowsInstallationType => Helper.WindowsInstallationType;
public static bool? WindowsIsUserAdministrator => Helper.WindowsIsUserAdministrator;
diff --git a/JetBrains.HabitatDetector/src/Impl/Helper.cs b/JetBrains.HabitatDetector/src/Impl/Helper.cs
index 506161f..a5eaa58 100644
--- a/JetBrains.HabitatDetector/src/Impl/Helper.cs
+++ b/JetBrains.HabitatDetector/src/Impl/Helper.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using JetBrains.HabitatDetector.Impl.Linux;
using JetBrains.HabitatDetector.Impl.MacOsX;
@@ -8,15 +9,21 @@
namespace JetBrains.HabitatDetector.Impl
{
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
internal static class Helper
{
- internal static readonly JetClrImplementation ClrImplementation;
- internal static readonly Version? MonoVersion;
internal static readonly JetPlatform Platform;
internal static readonly JetArchitecture OSArchitecture;
internal static readonly JetArchitecture ProcessArchitecture;
- internal static readonly JetLinuxLibC? LinuxLibC;
internal static readonly string OSName;
+
+ internal static readonly JetClrImplementation ClrImplementation;
+ internal static readonly Version? MonoVersion;
+
+ internal static readonly JetLinuxLibC? LinuxLibC;
+
+ internal static readonly Version? MacOSVersion;
+
internal static readonly uint? WindowsBuildNumber;
internal static readonly JetWindowsInstallationType? WindowsInstallationType;
internal static readonly bool? WindowsIsUserAdministrator;
@@ -72,7 +79,8 @@ static Helper()
case JetPlatform.MacOsX:
ProcessArchitecture = unameArchitecture;
OSArchitecture = MacOsHelper.GetRunningUnderRosetta2() ? JetArchitecture.Arm64 : unameArchitecture; // Note(ww898): Process under Rosetta2 works only on ARM64 host!
- OSName = MacOsHelper.GetOSName(unameArchitecture);
+ MacOSVersion = NormalizeVersion(MacOsHelper.GetOSVersion(unameArchitecture));
+ OSName = MacOsHelper.GetOSName(MacOSVersion);
break;
default: throw new PlatformNotSupportedException($"Unsupported platform {Platform}");
}
@@ -89,17 +97,22 @@ static Helper()
var n = displayNameStr.IndexOf(' ');
var versionStr = n >= 0 ? displayNameStr.Substring(0, n) : displayNameStr;
+ Version? monoVersion;
#if NET20 || NET30 || NET35
try
{
- MonoVersion = new Version(versionStr);
+ monoVersion = new Version(versionStr);
}
catch
{
+ monoVersion = null;
}
#else
- Version.TryParse(versionStr, out MonoVersion);
+ Version.TryParse(versionStr, out monoVersion);
#endif
+
+ if (monoVersion != null)
+ MonoVersion = NormalizeVersion(monoVersion);
}
#endif
@@ -109,6 +122,12 @@ static Helper()
ClrImplementation = isNetCore ? JetClrImplementation.NetCore : JetClrImplementation.NetFramework;
}
+ internal static Version NormalizeVersion(Version version) => version.Build > 0
+ ? version.Revision == -1
+ ? version
+ : new(version.Major, version.Minor, version.Build)
+ : new(version.Major, version.Minor);
+
internal static unsafe JetArchitecture GetProcessArchitecture(int processId) => Platform switch
{
JetPlatform.FreeBSD or JetPlatform.Linux => OSArchitecture,
diff --git a/JetBrains.HabitatDetector/src/Impl/MacOsX/MacOsHelper.cs b/JetBrains.HabitatDetector/src/Impl/MacOsX/MacOsHelper.cs
index 0cece4f..a4def89 100644
--- a/JetBrains.HabitatDetector/src/Impl/MacOsX/MacOsHelper.cs
+++ b/JetBrains.HabitatDetector/src/Impl/MacOsX/MacOsHelper.cs
@@ -45,7 +45,7 @@ internal static class MacOsHelper
return new string(Encoding.UTF8.GetChars(buf));
}
- private static unsafe Version GetOSVersion(JetArchitecture processArchitecture)
+ internal static unsafe Version GetOSVersion(JetArchitecture processArchitecture)
{
var processInfo = LibObjC.objc_msgSend(LibObjC.objc_getClass("NSProcessInfo"), LibObjC.sel_getUid("processInfo"));
var operationSystemVersionUid = LibObjC.sel_getUid("operatingSystemVersion");
@@ -73,14 +73,17 @@ private static unsafe Version GetOSVersion(JetArchitecture processArchitecture)
}
// Note(ww898): Compatibility with older software! See also SYSTEM_VERSION_COMPAT=1. Big Sur and newer OSes always returns 10.16!!!
- return major == 10 && minor == 16
- ? new Version(11, 0, patch)
- : new Version(major, minor, patch);
+ if (major == 10 && minor == 16)
+ {
+ major = 11;
+ minor = 0;
+ }
+
+ return new Version(major, minor, patch);
}
- internal static string GetOSName(JetArchitecture processArchitecture)
+ internal static string GetOSName(Version version)
{
- var version = GetOSVersion(processArchitecture);
var build = GetSysctlKernOsVersion();
var builder = new StringBuilder(version.Major switch
@@ -114,7 +117,7 @@ internal static string GetOSName(JetArchitecture processArchitecture)
});
builder.Append(' ').Append(version.Major).Append('.').Append(version.Minor);
- if (version.Build != 0)
+ if (version.Build > 0)
builder.Append('.').Append(version.Build);
if (build != null)
builder.Append(' ').Append(build);
diff --git a/JetBrains.HabitatDetector/src/Impl/Unix/UnixHelper.cs b/JetBrains.HabitatDetector/src/Impl/Unix/UnixHelper.cs
index 1deb4fe..fe74c71 100644
--- a/JetBrains.HabitatDetector/src/Impl/Unix/UnixHelper.cs
+++ b/JetBrains.HabitatDetector/src/Impl/Unix/UnixHelper.cs
@@ -1,9 +1,11 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
namespace JetBrains.HabitatDetector.Impl.Unix
{
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
internal static class UnixHelper
{
internal record struct UnameInfo(JetPlatform Platform, string Sysname, string Release, JetArchitecture Architecture);
diff --git a/JetBrains.HabitatDetector/src/Impl/Windows/WindowsHelper.cs b/JetBrains.HabitatDetector/src/Impl/Windows/WindowsHelper.cs
index dba36b7..9273bf3 100644
--- a/JetBrains.HabitatDetector/src/Impl/Windows/WindowsHelper.cs
+++ b/JetBrains.HabitatDetector/src/Impl/Windows/WindowsHelper.cs
@@ -1,10 +1,12 @@
using System;
using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Text.RegularExpressions;
namespace JetBrains.HabitatDetector.Impl.Windows
{
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
internal static class WindowsHelper
{
internal static unsafe JetArchitecture GetProcessArchitecture()
diff --git a/JetBrains.HabitatDetector/src/JetBrains.HabitatDetector.csproj b/JetBrains.HabitatDetector/src/JetBrains.HabitatDetector.csproj
index a2b3f5c..9313330 100644
--- a/JetBrains.HabitatDetector/src/JetBrains.HabitatDetector.csproj
+++ b/JetBrains.HabitatDetector/src/JetBrains.HabitatDetector.csproj
@@ -27,9 +27,9 @@ Supported frameworks:
• Mono 5.10 and later
https://github.com/JetBrains/habitat-detector
icon.png
- jetbrains habitat detect windows linux macos freebsd netstandard netframework
+ jetbrains windows linux macos freebsd netstandard netframework
Apache-2.0
- 1.2.1
+ 1.3.0
diff --git a/JetBrains.HabitatDetector/tests/HabitatInfoTest.cs b/JetBrains.HabitatDetector/tests/HabitatInfoTest.cs
index 85fcba0..8a2fe4d 100644
--- a/JetBrains.HabitatDetector/tests/HabitatInfoTest.cs
+++ b/JetBrains.HabitatDetector/tests/HabitatInfoTest.cs
@@ -180,11 +180,23 @@ public void ArchitecturePresentableTest(JetArchitecture architecture, string exp
[Test]
public void CurrentTest()
{
+ Console.WriteLine("{0}: {1}", nameof(Environment) + "." + nameof(Environment.OSVersion), Environment.OSVersion);
+ Console.WriteLine("{0}: {1}", nameof(Environment) + "." + nameof(Environment.OSVersion) + "." + nameof(Environment.OSVersion.Platform), Environment.OSVersion.Platform);
+ Console.WriteLine("{0}: {1}", nameof(Environment) + "." + nameof(Environment.OSVersion) + "." + nameof(Environment.OSVersion.Version), Environment.OSVersion.Version);
+ Console.WriteLine("{0}: {1}", nameof(Environment) + "." + nameof(Environment.OSVersion) + "." + nameof(Environment.OSVersion.ServicePack), Environment.OSVersion.ServicePack);
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.OSName), HabitatInfo.OSName);
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.ClrImplementation), HabitatInfo.ClrImplementation);
if (HabitatInfo.ClrImplementation == JetClrImplementation.Mono)
+ {
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.MonoVersion), HabitatInfo.MonoVersion?.ToString() ?? "");
+
+ if (HabitatInfo.MonoVersion != null)
+ {
+ Assert.AreNotEqual(0, HabitatInfo.MonoVersion.Build);
+ Assert.AreEqual(-1, HabitatInfo.MonoVersion.Revision);
+ }
+ }
else
Assert.IsNull(HabitatInfo.MonoVersion);
@@ -197,6 +209,8 @@ public void CurrentTest()
if (HabitatInfo.Platform == JetPlatform.Windows)
{
+ Assert.AreEqual(PlatformID.Win32NT, Environment.OSVersion.Platform);
+
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.WindowsBuildNumber), HabitatInfo.WindowsBuildNumber?.ToString() ?? "");
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.WindowsInstallationType), HabitatInfo.WindowsInstallationType?.ToString() ?? "");
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.WindowsIsUserAdministrator), HabitatInfo.WindowsIsUserAdministrator?.ToString() ?? "");
@@ -207,15 +221,36 @@ public void CurrentTest()
Assert.IsNotNull(HabitatInfo.WindowsIsUserAdministrator);
Assert.IsNotNull(HabitatInfo.WindowsIsElevated);
Assert.IsNotNull(HabitatInfo.WindowsElevationType);
+
+ Assert.AreEqual(Environment.OSVersion.Version.Build, checked((int)HabitatInfo.WindowsBuildNumber!));
}
else
{
+ Assert.AreNotEqual(PlatformID.Win32NT, Environment.OSVersion.Platform);
+
Assert.IsNull(HabitatInfo.WindowsInstallationType);
Assert.IsNull(HabitatInfo.WindowsIsUserAdministrator);
Assert.IsNull(HabitatInfo.WindowsIsElevated);
Assert.IsNull(HabitatInfo.WindowsElevationType);
}
+ if (HabitatInfo.Platform == JetPlatform.MacOsX)
+ {
+ Console.WriteLine("{0}: {1}", nameof(HabitatInfo.MacOSVersion), HabitatInfo.MacOSVersion?.ToString() ?? "");
+
+ if (HabitatInfo.MacOSVersion != null)
+ {
+ Assert.AreNotEqual(0, HabitatInfo.MacOSVersion.Build);
+ Assert.AreEqual(-1, HabitatInfo.MacOSVersion.Revision);
+ }
+ else
+ Assert.Fail();
+ }
+ else
+ {
+ Assert.IsNull(HabitatInfo.MacOSVersion);
+ }
+
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.ProcessRuntimeIdString), HabitatInfo.ProcessRuntimeIdString);
Console.WriteLine("{0}: {1}", nameof(HabitatInfo.OSRuntimeIdString), HabitatInfo.OSRuntimeIdString);
diff --git a/JetBrains.HabitatDetector/tests/UnitHelperTest.cs b/JetBrains.HabitatDetector/tests/UnitHelperTest.cs
index 409498f..b5fe294 100644
--- a/JetBrains.HabitatDetector/tests/UnitHelperTest.cs
+++ b/JetBrains.HabitatDetector/tests/UnitHelperTest.cs
@@ -1,4 +1,6 @@
-using JetBrains.HabitatDetector.Impl.Unix;
+using System;
+using JetBrains.HabitatDetector.Impl;
+using JetBrains.HabitatDetector.Impl.Unix;
using NUnit.Framework;
namespace JetBrains.HabitatDetector.Tests
@@ -30,5 +32,15 @@ public void PlatformTest(string sysname, JetPlatform expectedPlatform, int expec
[TestCase(JetPlatform.MacOsX, "x86_64", JetArchitecture.X64)]
[Test]
public void ConvertToArchitecture(JetPlatform platform, string machine, JetArchitecture expectedArchitecture) => Assert.AreEqual(expectedArchitecture, UnixHelper.ConvertToArchitecture(platform, machine));
+
+ [Test]
+ public void NormalizeTest()
+ {
+ Assert.AreEqual(new Version(11, 222), Helper.NormalizeVersion(new Version(11, 222)));
+ Assert.AreEqual(new Version(11, 222), Helper.NormalizeVersion(new Version(11, 222, 0)));
+ Assert.AreEqual(new Version(11, 222, 3333), Helper.NormalizeVersion(new Version(11, 222, 3333)));
+ Assert.AreEqual(new Version(11, 222, 3333), Helper.NormalizeVersion(new Version(11, 222, 3333, 0)));
+ Assert.AreEqual(new Version(11, 222, 3333), Helper.NormalizeVersion(new Version(11, 222, 3333, 44444)));
+ }
}
}
\ No newline at end of file