Use partial classes instead, mirroring iOS approach (#58361)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 31 Aug 2021 19:54:36 +0000 (12:54 -0700)
committerGitHub <noreply@github.com>
Tue, 31 Aug 2021 19:54:36 +0000 (12:54 -0700)
This should give the same output as legacy Xamarin. If it doesn't, I messed up

Co-authored-by: Jo Shields <joshield@microsoft.com>
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
src/mono/System.Private.CoreLib/src/System/Environment.Android.cs [new file with mode: 0644]

index e72c543..751a074 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Environment.UnixOrBrowser.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Environment.OSVersion.OSX.cs" Condition="'$(IsOSXLike)' == 'true' AND '$(TargetsMacCatalyst)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Environment.OSVersion.MacCatalyst.cs" Condition="'$(TargetsMacCatalyst)' == 'true'" />
-    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.GetFolderPathCore.Unix.cs" Condition="'$(IsiOSLike)' != 'true'" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.GetFolderPathCore.Unix.cs" Condition="'$(IsiOSLike)' != 'true' and '$(TargetsAndroid)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureInfo.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IUnaryNegationOperators.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IUnaryPlusOperators.cs" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
index 3e032e7..9691199 100644 (file)
         <Link>Common\Interop\Unix\System.Native\Interop.GetEnviron.cs</Link>
       </Compile>
   </ItemGroup>
+  <ItemGroup Condition="'$(TargetsAndroid)' == 'true'">
+      <Compile Include="$(BclSourcesRoot)\System\Environment.Android.cs" />
+  </ItemGroup>
   <ItemGroup Condition="'$(TargetsMacCatalyst)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true'">
       <Compile Include="$(BclSourcesRoot)\System\Environment.iOS.cs" />
       <Compile Include="$(CommonPath)Interop\OSX\System.Native\Interop.SearchPath.cs">
diff --git a/src/mono/System.Private.CoreLib/src/System/Environment.Android.cs b/src/mono/System.Private.CoreLib/src/System/Environment.Android.cs
new file mode 100644 (file)
index 0000000..44c8988
--- /dev/null
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.IO;
+using System.Threading;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace System
+{
+    public static partial class Environment
+    {
+        private static Dictionary<SpecialFolder, string>? s_specialFolders;
+
+        private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option)
+        {
+            if (s_specialFolders == null)
+            {
+                Interlocked.CompareExchange(ref s_specialFolders, new Dictionary<SpecialFolder, string>(), null);
+            }
+
+            string? path;
+            lock (s_specialFolders)
+            {
+                if (!s_specialFolders.TryGetValue(folder, out path))
+                {
+                    path = GetSpecialFolder(folder) ?? string.Empty;
+                    s_specialFolders[folder] = path;
+                }
+            }
+            return path;
+        }
+
+        private static string? GetSpecialFolder(SpecialFolder folder)
+        {
+            string? home = null;
+            try
+            {
+                home = PersistedFiles.GetHomeDirectory();
+            }
+            catch (Exception exc)
+            {
+                Debug.Fail($"Unable to get home directory: {exc}");
+            }
+
+            // Fall back to '/' when we can't determine the home directory.
+            // This location isn't writable by non-root users which provides some safeguard
+            // that the application doesn't write data which is meant to be private.
+            if (string.IsNullOrEmpty(home))
+            {
+                home = "/";
+            }
+
+            switch (folder)
+            {
+                case SpecialFolder.Personal:
+                case SpecialFolder.LocalApplicationData:
+                    return home;
+
+                case SpecialFolder.ApplicationData:
+                    return Path.Combine(home, ".config");
+
+                case SpecialFolder.Desktop:
+                case SpecialFolder.DesktopDirectory:
+                    return Path.Combine(home, "Desktop");
+
+                case SpecialFolder.MyMusic:
+                    return Path.Combine(home, "Music");
+
+                case SpecialFolder.MyPictures:
+                    return Path.Combine(home, "Pictures");
+
+                case SpecialFolder.Templates:
+                    return Path.Combine(home, "Templates");
+
+                case SpecialFolder.MyVideos:
+                    return Path.Combine(home, "Videos");
+
+                case SpecialFolder.CommonTemplates:
+                    return "/usr/share/templates";
+
+                case SpecialFolder.Fonts:
+                    return Path.Combine(home, ".fonts");
+
+                case SpecialFolder.UserProfile:
+                    return GetEnvironmentVariable("HOME");
+
+                case SpecialFolder.CommonApplicationData:
+                    return "/usr/share";
+
+                default:
+                    return string.Empty;
+            }
+        }
+    }
+}