Skip to content

Commit 4d02f6c

Browse files
committed
included PlatformAbstraction as source
1 parent 9571404 commit 4d02f6c

File tree

7 files changed

+501
-1
lines changed

7 files changed

+501
-1
lines changed

src/GitVersionTask.MsBuild/GitVersionTask.MsBuild.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
<PropertyGroup>
44
<TargetFrameworks>net472;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
55
<LangVersion>8.0</LangVersion>
6+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
67
</PropertyGroup>
78

89
<ItemGroup>
910
<PackageReference Include="Microsoft.Build" Version="16.4.0" />
1011
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.4.0" />
11-
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="2.1.0" />
1212
</ItemGroup>
1313

1414
<ItemGroup>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Runtime.InteropServices;
7+
8+
namespace Microsoft.DotNet.PlatformAbstractions.Native
9+
{
10+
internal static partial class NativeMethods
11+
{
12+
public static class Darwin
13+
{
14+
private const int CTL_KERN = 1;
15+
private const int KERN_OSRELEASE = 2;
16+
17+
public unsafe static string GetKernelRelease()
18+
{
19+
const uint BUFFER_LENGTH = 32;
20+
21+
var name = stackalloc int[2];
22+
name[0] = CTL_KERN;
23+
name[1] = KERN_OSRELEASE;
24+
25+
var buf = stackalloc byte[(int)BUFFER_LENGTH];
26+
var len = stackalloc uint[1];
27+
*len = BUFFER_LENGTH;
28+
29+
try
30+
{
31+
// If the buffer isn't big enough, it seems sysctl still returns 0 and just sets len to the
32+
// necessary buffer size. This appears to be contrary to the man page, but it's easy to detect
33+
// by simply checking len against the buffer length.
34+
if (sysctl(name, 2, buf, len, IntPtr.Zero, 0) == 0 && *len < BUFFER_LENGTH)
35+
{
36+
return Marshal.PtrToStringAnsi((IntPtr)buf, (int)*len);
37+
}
38+
}
39+
catch (Exception ex)
40+
{
41+
throw new PlatformNotSupportedException("Error reading Darwin Kernel Version", ex);
42+
}
43+
throw new PlatformNotSupportedException("Unknown error reading Darwin Kernel Version");
44+
}
45+
46+
[DllImport("libc")]
47+
private unsafe static extern int sysctl(
48+
int* name,
49+
uint namelen,
50+
byte* oldp,
51+
uint* oldlenp,
52+
IntPtr newp,
53+
uint newlen);
54+
}
55+
}
56+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if NET45
6+
7+
using System;
8+
using System.Runtime.InteropServices;
9+
10+
namespace Microsoft.DotNet.PlatformAbstractions.Native
11+
{
12+
internal static partial class NativeMethods
13+
{
14+
public static class Unix
15+
{
16+
public unsafe static string GetUname()
17+
{
18+
// Utsname shouldn't be larger than 2K
19+
var buf = stackalloc byte[2048];
20+
21+
try
22+
{
23+
if (uname((IntPtr)buf) == 0)
24+
{
25+
return Marshal.PtrToStringAnsi((IntPtr)buf);
26+
}
27+
}
28+
catch (Exception ex)
29+
{
30+
throw new PlatformNotSupportedException("Error reading Unix name", ex);
31+
}
32+
throw new PlatformNotSupportedException("Unknown error reading Unix name");
33+
}
34+
35+
[DllImport("libc")]
36+
private static extern int uname(IntPtr utsname);
37+
}
38+
}
39+
}
40+
#endif
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.InteropServices;
6+
7+
namespace Microsoft.DotNet.PlatformAbstractions.Native
8+
{
9+
internal static partial class NativeMethods
10+
{
11+
public static class Windows
12+
{
13+
[StructLayout(LayoutKind.Sequential)]
14+
internal struct RTL_OSVERSIONINFOEX
15+
{
16+
internal uint dwOSVersionInfoSize;
17+
internal uint dwMajorVersion;
18+
internal uint dwMinorVersion;
19+
internal uint dwBuildNumber;
20+
internal uint dwPlatformId;
21+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
22+
internal string szCSDVersion;
23+
}
24+
25+
// This call avoids the shimming Windows does to report old versions
26+
[DllImport("ntdll")]
27+
private static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation);
28+
29+
internal static string RtlGetVersion()
30+
{
31+
RTL_OSVERSIONINFOEX osvi = new RTL_OSVERSIONINFOEX();
32+
osvi.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
33+
if (RtlGetVersion(out osvi) == 0)
34+
{
35+
return $"{osvi.dwMajorVersion}.{osvi.dwMinorVersion}.{osvi.dwBuildNumber}";
36+
}
37+
else
38+
{
39+
return null;
40+
}
41+
}
42+
}
43+
}
44+
}
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.IO;
7+
using System.Runtime.InteropServices;
8+
9+
namespace Microsoft.DotNet.PlatformAbstractions.Native
10+
{
11+
internal static class PlatformApis
12+
{
13+
private class DistroInfo
14+
{
15+
public string Id;
16+
public string VersionId;
17+
}
18+
19+
private static readonly Lazy<Platform> _platform = new Lazy<Platform>(DetermineOSPlatform);
20+
private static readonly Lazy<DistroInfo> _distroInfo = new Lazy<DistroInfo>(LoadDistroInfo);
21+
22+
public static string GetOSName()
23+
{
24+
switch (GetOSPlatform())
25+
{
26+
case Platform.Windows:
27+
return "Windows";
28+
case Platform.Linux:
29+
return GetDistroId() ?? "Linux";
30+
case Platform.Darwin:
31+
return "Mac OS X";
32+
case Platform.FreeBSD:
33+
return "FreeBSD";
34+
default:
35+
return "Unknown";
36+
}
37+
}
38+
39+
public static string GetOSVersion()
40+
{
41+
switch (GetOSPlatform())
42+
{
43+
case Platform.Windows:
44+
return NativeMethods.Windows.RtlGetVersion() ?? string.Empty;
45+
case Platform.Linux:
46+
return GetDistroVersionId() ?? string.Empty;
47+
case Platform.Darwin:
48+
return GetDarwinVersion() ?? string.Empty;
49+
case Platform.FreeBSD:
50+
return GetFreeBSDVersion() ?? string.Empty;
51+
default:
52+
return string.Empty;
53+
}
54+
}
55+
56+
private static string GetDarwinVersion()
57+
{
58+
Version version;
59+
var kernelRelease = NativeMethods.Darwin.GetKernelRelease();
60+
if (!Version.TryParse(kernelRelease, out version) || version.Major < 5)
61+
{
62+
// 10.0 covers all versions prior to Darwin 5
63+
// Similarly, if the version is not a valid version number, but we have still detected that it is Darwin, we just assume
64+
// it is OS X 10.0
65+
return "10.0";
66+
}
67+
else
68+
{
69+
// Mac OS X 10.1 mapped to Darwin 5.x, and the mapping continues that way
70+
// So just subtract 4 from the Darwin version.
71+
// https://en.wikipedia.org/wiki/Darwin_%28operating_system%29
72+
return $"10.{version.Major - 4}";
73+
}
74+
}
75+
76+
private static string GetFreeBSDVersion()
77+
{
78+
// This is same as sysctl kern.version
79+
// FreeBSD 11.0-RELEASE-p1 FreeBSD 11.0-RELEASE-p1 #0 r306420: Thu Sep 29 01:43:23 UTC 2016 [email protected]:/usr/obj/usr/src/sys/GENERIC
80+
// What we want is major release as minor releases should be compatible.
81+
String version = RuntimeInformation.OSDescription;
82+
try
83+
{
84+
// second token up to first dot
85+
return RuntimeInformation.OSDescription.Split()[1].Split('.')[0];
86+
}
87+
catch
88+
{
89+
}
90+
return string.Empty;
91+
}
92+
93+
public static Platform GetOSPlatform()
94+
{
95+
return _platform.Value;
96+
}
97+
98+
private static string GetDistroId()
99+
{
100+
return _distroInfo.Value?.Id;
101+
}
102+
103+
private static string GetDistroVersionId()
104+
{
105+
return _distroInfo.Value?.VersionId;
106+
}
107+
108+
private static DistroInfo LoadDistroInfo()
109+
{
110+
DistroInfo result = null;
111+
112+
// Sample os-release file:
113+
// NAME="Ubuntu"
114+
// VERSION = "14.04.3 LTS, Trusty Tahr"
115+
// ID = ubuntu
116+
// ID_LIKE = debian
117+
// PRETTY_NAME = "Ubuntu 14.04.3 LTS"
118+
// VERSION_ID = "14.04"
119+
// HOME_URL = "http://www.ubuntu.com/"
120+
// SUPPORT_URL = "http://help.ubuntu.com/"
121+
// BUG_REPORT_URL = "http://bugs.launchpad.net/ubuntu/"
122+
// We use ID and VERSION_ID
123+
124+
if (File.Exists("/etc/os-release"))
125+
{
126+
var lines = File.ReadAllLines("/etc/os-release");
127+
result = new DistroInfo();
128+
foreach (var line in lines)
129+
{
130+
if (line.StartsWith("ID=", StringComparison.Ordinal))
131+
{
132+
result.Id = line.Substring(3).Trim('"', '\'');
133+
}
134+
else if (line.StartsWith("VERSION_ID=", StringComparison.Ordinal))
135+
{
136+
result.VersionId = line.Substring(11).Trim('"', '\'');
137+
}
138+
}
139+
}
140+
141+
if (result != null)
142+
{
143+
result = NormalizeDistroInfo(result);
144+
}
145+
146+
return result;
147+
}
148+
149+
// For some distros, we don't want to use the full version from VERSION_ID. One example is
150+
// Red Hat Enterprise Linux, which includes a minor version in their VERSION_ID but minor
151+
// versions are backwards compatable.
152+
//
153+
// In this case, we'll normalized RIDs like 'rhel.7.2' and 'rhel.7.3' to a generic
154+
// 'rhel.7'. This brings RHEL in line with other distros like CentOS or Debian which
155+
// don't put minor version numbers in their VERSION_ID fields because all minor versions
156+
// are backwards compatible.
157+
private static DistroInfo NormalizeDistroInfo(DistroInfo distroInfo)
158+
{
159+
// Handle if VersionId is null by just setting the index to -1.
160+
int lastVersionNumberSeparatorIndex = distroInfo.VersionId?.IndexOf('.') ?? -1;
161+
162+
if (lastVersionNumberSeparatorIndex != -1 && distroInfo.Id == "alpine")
163+
{
164+
// For Alpine, the version reported has three components, so we need to find the second version separator
165+
lastVersionNumberSeparatorIndex = distroInfo.VersionId.IndexOf('.', lastVersionNumberSeparatorIndex + 1);
166+
}
167+
168+
if (lastVersionNumberSeparatorIndex != -1 && (distroInfo.Id == "rhel" || distroInfo.Id == "alpine"))
169+
{
170+
distroInfo.VersionId = distroInfo.VersionId.Substring(0, lastVersionNumberSeparatorIndex);
171+
}
172+
173+
return distroInfo;
174+
}
175+
176+
// I could probably have just done one method signature and put the #if inside the body but the implementations
177+
// are just completely different so I wanted to make that clear by putting the whole thing inside the #if.
178+
#if NET45
179+
private static Platform DetermineOSPlatform()
180+
{
181+
var platform = (int)Environment.OSVersion.Platform;
182+
var isWindows = (platform != 4) && (platform != 6) && (platform != 128);
183+
184+
if (isWindows)
185+
{
186+
return Platform.Windows;
187+
}
188+
else
189+
{
190+
try
191+
{
192+
var uname = NativeMethods.Unix.GetUname();
193+
if (string.Equals(uname, "Darwin", StringComparison.OrdinalIgnoreCase))
194+
{
195+
return Platform.Darwin;
196+
}
197+
if (string.Equals(uname, "Linux", StringComparison.OrdinalIgnoreCase))
198+
{
199+
return Platform.Linux;
200+
}
201+
if (string.Equals(uname, "FreeBSD", StringComparison.OrdinalIgnoreCase))
202+
{
203+
return Platform.FreeBSD;
204+
}
205+
}
206+
catch
207+
{
208+
}
209+
return Platform.Unknown;
210+
}
211+
}
212+
#else
213+
private static Platform DetermineOSPlatform()
214+
{
215+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
216+
{
217+
return Platform.Windows;
218+
}
219+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
220+
{
221+
return Platform.Linux;
222+
}
223+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
224+
{
225+
return Platform.Darwin;
226+
}
227+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD")))
228+
{
229+
return Platform.FreeBSD;
230+
}
231+
232+
return Platform.Unknown;
233+
}
234+
#endif
235+
}
236+
}

0 commit comments

Comments
 (0)