From a61acec08a7f5797092b4b659d97d2e4cb9494f6 Mon Sep 17 00:00:00 2001 From: Sam Therapy Date: Sat, 16 Sep 2023 17:40:16 +0200 Subject: [PATCH] refactor: Rewrite everything Rewrite the library from almost scratch to vastly improve performance and slightly improve any maintainability Signed-off-by: Sam Therapy --- .github/workflows/build-test.yaml | 32 +++- README.md | 2 +- Xdg.Net.sln | 1 - src/Xdg.Benchmarks/Program.fs | 19 +- src/Xdg.Benchmarks/Xdg.Benchmarks.fsproj | 39 ++-- src/Xdg.Directories.FFI/BaseDirectory.cs | 3 +- src/Xdg.Directories.FFI/GNUmakefile | 2 +- src/Xdg.Directories.FFI/Helpers.cs | 13 +- src/Xdg.Directories.FFI/Other.cs | 4 +- src/Xdg.Directories.FFI/UserDirectory.cs | 4 +- src/Xdg.Directories.FFI/xdg.pc | 2 +- src/Xdg.Directories/BaseDirectory.cs | 168 ++++++++++-------- src/Xdg.Directories/Helpers.cs | 78 +++----- src/Xdg.Directories/Other.cs | 113 ++++++------ src/Xdg.Directories/UserDirectory.cs | 115 +++++++----- src/Xdg.Directories/Usings.cs | 2 +- src/Xdg.Directories/Xdg.Directories.csproj | 4 +- src/Xdg.Directories/docs/BaseDirectory.xml | 4 +- .../Directories/BaseDirectory_test.cs | 50 ++++-- src/Xdg.Testing/Directories/HelperMethods.cs | 1 + src/Xdg.Testing/Directories/Other_test.cs | 59 +++++- .../Directories/UserDirectory_test.cs | 4 +- src/Xdg.Testing/Usings.cs | 2 +- 23 files changed, 435 insertions(+), 286 deletions(-) diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index 897a5cf..80a43ef 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -31,7 +31,7 @@ jobs: - name: Test run: dotnet test --no-restore --verbosity normal - publish: + publish-preview: needs: build if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} runs-on: ubuntu-latest @@ -58,3 +58,33 @@ jobs: run: dotnet build --configuration Release --no-restore -p:SymbolPackageFormat=symbols.nupkg - name: Publish the package run: dotnet nuget push src/Xdg.Directories/bin/Release/*.symbols.nupkg -s https://nuget.pkg.github.com/xdg-net/index.json -k ${{ secrets.GITHUB_TOKEN }} + + publish-release: + needs: build + if: ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/') }} + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup .NET Core SDK + uses: actions/setup-dotnet@v3 + - uses: actions/cache@v3 + with: + path: ~/.nuget/packages + # Look to see if there is a cache hit for the corresponding requirements file + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget + - name: Install dependencies + run: dotnet restore + - name: Build the package + run: dotnet build --configuration Release --no-restore -p:SymbolPackageFormat=snupkg + - name: Publish the package + run: dotnet nuget push src/Xdg.Directories/bin/Release/*.snupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_KEY }} + env: + NUGET_API_KEY: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index c2a1580..c2a29c3 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Inspiration is taken from the [Go implementation](https://github.com/adrg/xdg) f
User Directory -User directories on Windows use [Known Folders](https://learn.microsoft.com/en-us/windows/win32/shell/known-folders) as a fallback. +User directories on Windows use [Known Folders](https://learn.microsoft.com/en-us/windows/win32/shell/known-folders). | Environment Variable | Windows | macOS | Linux/FreeBSD | | --- | --- | --- | --- | | `XDG_DESKTOP_DIR` | `Desktop` | `$HOME/Desktop` | `$HOME/Desktop` | diff --git a/Xdg.Net.sln b/Xdg.Net.sln index 626058b..e5dbb66 100644 --- a/Xdg.Net.sln +++ b/Xdg.Net.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33627.172 diff --git a/src/Xdg.Benchmarks/Program.fs b/src/Xdg.Benchmarks/Program.fs index 77c578b..e19c5d4 100644 --- a/src/Xdg.Benchmarks/Program.fs +++ b/src/Xdg.Benchmarks/Program.fs @@ -1,16 +1,18 @@ open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open BenchmarkDotNet.Jobs -open Xdg.Directories; +open BenchmarkDotNet.Configs +open Xdg.Directories [] -//[] -[] -[] -[] +#if WINDOWS +[] +#endif +[] +// [] type Benchmarks() = // Base Directory - [] + [] member _.DataHome () = BaseDirectory.DataHome [] member _.ConfigHome () = BaseDirectory.ConfigHome @@ -18,7 +20,7 @@ type Benchmarks() = member _.StateHome () = BaseDirectory.StateHome [] member _.BinHome () = BaseDirectory.BinHome - [] + [] member _.DataDirs () = BaseDirectory.DataDirs [] member _.ConfigDirs () = BaseDirectory.ConfigDirs @@ -53,4 +55,5 @@ type Benchmarks() = [] member _.Fonts () = Other.Fonts -BenchmarkRunner.Run() |> ignore \ No newline at end of file +let config = DefaultConfig.Instance.WithOptions(ConfigOptions.DisableOptimizationsValidator) +BenchmarkRunner.Run(config) |> ignore \ No newline at end of file diff --git a/src/Xdg.Benchmarks/Xdg.Benchmarks.fsproj b/src/Xdg.Benchmarks/Xdg.Benchmarks.fsproj index 5843e57..007e01e 100644 --- a/src/Xdg.Benchmarks/Xdg.Benchmarks.fsproj +++ b/src/Xdg.Benchmarks/Xdg.Benchmarks.fsproj @@ -2,29 +2,42 @@ Exe - net7.0;net48 - false - false - True - True - True - True - latest-all + net7.0;net462 + false + false + True + True + True + True + latest-all + + + true + - + + Windows + + + 5 - + 5 - + 5 - + 5 @@ -40,4 +53,4 @@ - + \ No newline at end of file diff --git a/src/Xdg.Directories.FFI/BaseDirectory.cs b/src/Xdg.Directories.FFI/BaseDirectory.cs index 90b1bac..56f9a2d 100644 --- a/src/Xdg.Directories.FFI/BaseDirectory.cs +++ b/src/Xdg.Directories.FFI/BaseDirectory.cs @@ -1,5 +1,4 @@ #if NET7_0_OR_GREATER -#pragma warning disable CA1031 // General exceptions needed for handling errors using System.Runtime.InteropServices; namespace Xdg.Directories.FFI; @@ -87,4 +86,4 @@ internal static partial class Exports } } } -#endif \ No newline at end of file +#endif diff --git a/src/Xdg.Directories.FFI/GNUmakefile b/src/Xdg.Directories.FFI/GNUmakefile index 0b9bbeb..74ea950 100644 --- a/src/Xdg.Directories.FFI/GNUmakefile +++ b/src/Xdg.Directories.FFI/GNUmakefile @@ -2,7 +2,7 @@ PREFIX ?= /usr/local LIB ?= lib64 DOTNET ?= dotnet NETVERSION ?= net7.0 -PUBFLAGS ?= --framework $(NETVERSION) -c Release -p PublishAot=true +PUBFLAGS ?= --framework $(NETVERSION) -c Release ifeq ($(OS),Windows_NT) OSFLAG += win diff --git a/src/Xdg.Directories.FFI/Helpers.cs b/src/Xdg.Directories.FFI/Helpers.cs index e9f5a9b..4acf74c 100644 --- a/src/Xdg.Directories.FFI/Helpers.cs +++ b/src/Xdg.Directories.FFI/Helpers.cs @@ -14,10 +14,13 @@ internal static partial class Exports /// /// The .NET Pointer to free [UnmanagedCallersOnly(EntryPoint = "xdg_free")] - public static void Free(IntPtr p) - => Marshal.FreeCoTaskMem(p); + public static void Free(IntPtr p) => Marshal.FreeCoTaskMem(p); - internal static IntPtr StringToPtr(string? str) - => Marshal.StringToCoTaskMemUTF8(str); + /// + /// Converts a .NET string to a C string + /// + /// The .NET string + /// A pointer to a C string + internal static IntPtr StringToPtr(string? str) => Marshal.StringToCoTaskMemUTF8(str); } -#endif \ No newline at end of file +#endif diff --git a/src/Xdg.Directories.FFI/Other.cs b/src/Xdg.Directories.FFI/Other.cs index adca544..f3b100c 100644 --- a/src/Xdg.Directories.FFI/Other.cs +++ b/src/Xdg.Directories.FFI/Other.cs @@ -1,8 +1,8 @@ #if NET7_0_OR_GREATER -#pragma warning disable CA1031 // General exceptions needed for handling errors using System.Runtime.InteropServices; namespace Xdg.Directories.FFI; + internal static partial class Exports { [UnmanagedCallersOnly(EntryPoint = "xdg_user_home")] @@ -18,4 +18,4 @@ internal static partial class Exports } } } -#endif \ No newline at end of file +#endif diff --git a/src/Xdg.Directories.FFI/UserDirectory.cs b/src/Xdg.Directories.FFI/UserDirectory.cs index eb2108c..7d309d7 100644 --- a/src/Xdg.Directories.FFI/UserDirectory.cs +++ b/src/Xdg.Directories.FFI/UserDirectory.cs @@ -1,8 +1,8 @@ #if NET7_0_OR_GREATER -#pragma warning disable CA1031 // General exceptions needed for handling errors using System.Runtime.InteropServices; namespace Xdg.Directories.FFI; + internal static partial class Exports { [UnmanagedCallersOnly(EntryPoint = "xdg_desktop_dir")] @@ -109,4 +109,4 @@ internal static partial class Exports } } } -#endif \ No newline at end of file +#endif diff --git a/src/Xdg.Directories.FFI/xdg.pc b/src/Xdg.Directories.FFI/xdg.pc index bc96c56..39ee0dc 100644 --- a/src/Xdg.Directories.FFI/xdg.pc +++ b/src/Xdg.Directories.FFI/xdg.pc @@ -4,7 +4,7 @@ includedir=${prefix}/include libdir=${exec_prefix}/lib Name: xdg -Description: xdg directory library +Description: a dotnet-ffi xdg directory library Version: 1.0.0 Libs: -L${libdir} -lxdg Cflags: -I${includedir} \ No newline at end of file diff --git a/src/Xdg.Directories/BaseDirectory.cs b/src/Xdg.Directories/BaseDirectory.cs index f08a5ab..7456ae9 100644 --- a/src/Xdg.Directories/BaseDirectory.cs +++ b/src/Xdg.Directories/BaseDirectory.cs @@ -7,116 +7,142 @@ public static class BaseDirectory public static string DataHome { get => - Helpers.OS( - "XDG_DATA_HOME", - GetEnvironmentVariable("LOCALAPPDATA") - ?? GetFolderPath(SpecialFolder.LocalApplicationData), - $"{Other.Home}/Library/Application Support", - $"{Other.Home}/.local/share" - )!; + GetEnvironmentVariable("XDG_DATA_HOME") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => GetEnvironmentVariable("LOCALAPPDATA") + ?? GetFolderPath(SpecialFolder.LocalApplicationData), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Library", "Application Support"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, ".local", "share"), + _ => string.Empty + }; } /// public static string ConfigHome { get => - Helpers.OS( - "XDG_CONFIG_HOME", - GetEnvironmentVariable("LOCALAPPDATA") - ?? GetFolderPath(SpecialFolder.LocalApplicationData), - $"{Other.Home}/Library/Application Support", - $"{Other.Home}/.config" - )!; + GetEnvironmentVariable("XDG_CONFIG_HOME") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => GetEnvironmentVariable("LOCALAPPDATA") + ?? GetFolderPath(SpecialFolder.LocalApplicationData), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Library", "Application Support"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, ".config"), + _ => string.Empty + }; } /// public static string StateHome { get => - Helpers.OS( - "XDG_STATE_HOME", - GetEnvironmentVariable("LOCALAPPDATA") - ?? GetFolderPath(SpecialFolder.LocalApplicationData), - $"{Other.Home}/Library/Application Support", - $"{Other.Home}/.local/state" - )!; + GetEnvironmentVariable("XDG_STATE_HOME") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => GetEnvironmentVariable("LOCALAPPDATA") + ?? GetFolderPath(SpecialFolder.LocalApplicationData), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Library", "Application Support"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, ".local", "state"), + _ => string.Empty + }; } /// - public static string? BinHome + public static string BinHome { - get => Helpers.OS("XDG_BIN_HOME", null, null, $"{Other.Home}/.local/bin")!; + get => + GetEnvironmentVariable("XDG_BIN_HOME") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => string.Empty, + Helpers.OS.MacOS => string.Empty, + Helpers.OS.UnixLike => Path.Combine(Other.Home, ".local", "bin"), + _ => string.Empty + }; } /// public static IList DataDirs { get => - Helpers.OS( - "XDG_DATA_DIRS", - new string[] - { - Helpers.AorB( - GetFolderPath(SpecialFolder.ApplicationData), - GetEnvironmentVariable("APPDATA")! - ), - GetEnvironmentVariable("PROGRAMDATA") - ?? GetFolderPath(SpecialFolder.CommonApplicationData) - }, - new string[] { "/Library/Application Support" }, - new string[] { "/usr/local/share", "/usr/share" } - )!; + GetEnvironmentVariable("XDG_DATA_DIRS")?.Split(':') + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => new string[] + { + GetEnvironmentVariable("APPDATA") + ?? GetFolderPath(SpecialFolder.ApplicationData), + GetEnvironmentVariable("PROGRAMDATA") + ?? GetFolderPath(SpecialFolder.CommonApplicationData) + }, + Helpers.OS.MacOS => new string[] { "/Library/Application Support" }, + Helpers.OS.UnixLike => new string[] {"/usr/local/share", "/usr/share"}, + _ => Array.Empty() + }; } /// public static IList ConfigDirs { get => - Helpers.OS( - "XDG_CONFIG_DIRS", - new string[] - { - GetEnvironmentVariable("PROGRAMDATA") - ?? GetFolderPath(SpecialFolder.CommonApplicationData), - Helpers.AorB( - GetFolderPath(SpecialFolder.ApplicationData), - GetEnvironmentVariable("APPDATA")! - ) - }, - new string[] - { - $"{Other.Home}/Library/Preferences", - "/Library/Application Support", - "/Library/Preferences" - }, - new string[] { "/etc/xdg" } - )!; + GetEnvironmentVariable("XDG_CONFIG_DIRS")?.Split(':') + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => new string[] + { + GetEnvironmentVariable("ProgramData") + ?? GetFolderPath(SpecialFolder.CommonApplicationData), + GetEnvironmentVariable("APPDATA") + ?? GetFolderPath(SpecialFolder.ApplicationData) + }, + Helpers.OS.MacOS + => new string[] + { + Path.Combine(Other.Home, "Library", "Preferences"), + "/Library/Application Support", + "/Library/Preferences" + }, + Helpers.OS.UnixLike => new string[] { "/etc/xdg" }, + _ => Array.Empty() + }; } /// public static string CacheHome { get => - Helpers.OS( - "XDG_CACHE_HOME", - GetEnvironmentVariable("LOCALAPPDATA") is not null - ? $"{GetEnvironmentVariable("LOCALAPPDATA")}\\cache" - : $"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\cache", - $"{Other.Home}/Library/Caches", - $"{Other.Home}/.cache" - )!; + GetEnvironmentVariable("XDG_CACHE_HOME") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => GetEnvironmentVariable("LOCALAPPDATA") is not null + ? Path.Combine(GetEnvironmentVariable("LOCALAPPDATA")!, "cache") + : Path.Combine(GetFolderPath(SpecialFolder.LocalApplicationData), "cache"), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Library", "Caches"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, ".cache"), + _ => string.Empty + }; } /// public static string RuntimeDir { get => - Helpers.OS( - "XDG_RUNTIME_DIR", - GetEnvironmentVariable("LOCALAPPDATA") - ?? GetFolderPath(SpecialFolder.LocalApplicationData), - $"{Other.Home}/Library/Application Support", - $"/run/user/{GetEnvironmentVariable("UID")}" - )!; + GetEnvironmentVariable("XDG_RUNTIME_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => GetEnvironmentVariable("LOCALAPPDATA") + ?? GetFolderPath(SpecialFolder.LocalApplicationData), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Library", "Application Support"), + Helpers.OS.UnixLike => Path.Combine("/run", "user", GetEnvironmentVariable("UID") ?? "0"), + _ => string.Empty + }; } } diff --git a/src/Xdg.Directories/Helpers.cs b/src/Xdg.Directories/Helpers.cs index b6c277e..bc92bc6 100644 --- a/src/Xdg.Directories/Helpers.cs +++ b/src/Xdg.Directories/Helpers.cs @@ -4,67 +4,45 @@ namespace Xdg.Directories; static internal class Helpers { /// - /// Return a specified value depending on the running operating system + /// The current operating system /// - /// Environment variable to test initially - /// Windows directory - /// macOS Directory - /// Linux/BSD Directory - /// Env if set, otherwise variable depending on operating system - /// If running on another operating system - internal static string? OS(string Env, string? Windows, string? MacOS, string? Unix) + internal enum OS : byte { - string? env = GetEnvironmentVariable(Env); - if (env is not null) - return env; - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return Windows; - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - return MacOS; -#if NETSTANDARD - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) -#elif NET - else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD()) -#endif - return Unix; - else - throw new NotSupportedException("Platforms not supported by .NET Standard are not supported."); + Windows, + MacOS, + /// + /// Linux, FreeBSD, etc. + /// + UnixLike, + /// + /// Anything not supported by .NET + /// + Other } /// - /// Return a specified value depending on the running operating system - /// - /// Environment variable to test initially - /// Windows directories - /// macOS Directories - /// Linux/BSD Directories - /// Env if set, otherwise variable depending on operating system - /// If running on another operating system - internal static IList? OS(string Env, IList? Windows, IList? MacOS, IList? Unix) + /// Get the current operating system + /// + /// The current operating system + internal static OS GetCurrentOperatingSystem() { - string? env = GetEnvironmentVariable(Env); - if (env is not null) - return env.Split(':')!; - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return Windows; - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - return MacOS; + // OperatingSystem.Is is faster but not supported by .NET Standard #if NETSTANDARD + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return OS.Windows; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + return OS.MacOS; else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return OS.UnixLike; #elif NET + if (OperatingSystem.IsWindows()) + return OS.Windows; + else if (OperatingSystem.IsMacOS()) + return OS.MacOS; else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD()) + return OS.UnixLike; #endif - return Unix; else - throw new NotSupportedException("Platforms not supported by .NET Standard are not supported."); + return OS.Other; } - - /// - /// Returns B if and only if A is empty. - /// - /// Value to test - /// Alternative if A is null or empty - /// B if A is null or empty, A if not - internal static string AorB(string A, string B) - => A is { Length: 0 } ? B : A; } diff --git a/src/Xdg.Directories/Other.cs b/src/Xdg.Directories/Other.cs index 64201d2..cb43193 100644 --- a/src/Xdg.Directories/Other.cs +++ b/src/Xdg.Directories/Other.cs @@ -8,14 +8,14 @@ public static class Other { get { - // Unix ?? Windows - string? home = - GetEnvironmentVariable("HOME") - ?? GetEnvironmentVariable("USERPROFILE"); - if (home is not null) - return home; - else - return GetFolderPath(SpecialFolder.UserProfile); + string? homeEnv = Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetEnvironmentVariable("USERPROFILE"), + Helpers.OS.MacOS => GetEnvironmentVariable("HOME"), + Helpers.OS.UnixLike => GetEnvironmentVariable("HOME"), + _ => null + }; + return homeEnv ?? GetFolderPath(SpecialFolder.UserProfile); } } @@ -23,56 +23,63 @@ public static class Other public static IList Applications { get => - Helpers.OS( - "", - new string[] - { - GetFolderPath(SpecialFolder.Programs), - GetFolderPath(SpecialFolder.CommonPrograms) - }, - new string[] { "/Applications" }, - new string[] - { - $"{BaseDirectory.DataHome}/applications", - $"{Home}/.local/share/applications", - "/usr/local/share/applications", - "/usr/share/applications", - // TODO: Add $XDG_DATA_DIRS/applications - } - )!; + Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => new string[] + { + GetFolderPath(SpecialFolder.Programs), + GetFolderPath(SpecialFolder.CommonPrograms) + }, + Helpers.OS.MacOS => new string[] { "/Applications" }, + Helpers.OS.UnixLike + => new string[] + { + $"{BaseDirectory.DataHome}/applications", + $"{Home}/.local/share/applications", + "/usr/local/share/applications", + "/usr/share/applications", + // TODO: Add $XDG_DATA_DIRS/applications + }, + _ => Array.Empty() + }; } /// public static IList Fonts { get => - Helpers.OS( - "", - new string[] - { - GetEnvironmentVariable("SystemRoot") is not null - ? $"{GetEnvironmentVariable("SystemRoot")}\\Fonts" - : GetFolderPath(SpecialFolder.Fonts), - GetEnvironmentVariable("LOCALAPPDATA") is not null - ? $"{GetEnvironmentVariable("LOCALAPPDATA")}\\Microsoft\\Windows\\Fonts" - : $"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\Microsoft\\Windows\\Fonts" - }, - new string[] - { - $"{Home}/Library/Fonts", - "/Library/Fonts", - "/System/Library/Fonts", - "/Network/Library/Fonts" - }, - new string[] - { - $"{BaseDirectory.DataHome}/fonts", - $"{Home}/.fonts", - $"{Home}/.local/share/fonts", - "/usr/local/share/fonts", - "/usr/share/fonts", - // TODO: Add $XDG_DATA_DIRS/fonts - } - )!; + Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows + => new string[] + { + GetEnvironmentVariable("SystemRoot") is not null + ? $"{GetEnvironmentVariable("SystemRoot")}\\Fonts" + : GetFolderPath(SpecialFolder.Fonts), + GetEnvironmentVariable("LOCALAPPDATA") is not null + ? $"{GetEnvironmentVariable("LOCALAPPDATA")}\\Microsoft\\Windows\\Fonts" + : $"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\Microsoft\\Windows\\Fonts" + }, + Helpers.OS.MacOS + => new string[] + { + $"{Home}/Library/Fonts", + "/Library/Fonts", + "/System/Library/Fonts", + "/Network/Library/Fonts" + }, + Helpers.OS.UnixLike + => new string[] + { + Path.Combine(BaseDirectory.DataHome, "fonts"), + Path.Combine(Home, ".fonts"), + Path.Combine(Home, ".local", "share", "fonts"), + "/usr/local/share/fonts", + "/usr/share/fonts", + // TODO: Add $XDG_DATA_DIRS/fonts + }, + _ => Array.Empty() + }; } } diff --git a/src/Xdg.Directories/UserDirectory.cs b/src/Xdg.Directories/UserDirectory.cs index e368e6c..8db722e 100644 --- a/src/Xdg.Directories/UserDirectory.cs +++ b/src/Xdg.Directories/UserDirectory.cs @@ -7,95 +7,112 @@ public static class UserDirectory public static string DesktopDir { get => - Helpers.OS( - "XDG_DESKTOP_DIR", - GetFolderPath(SpecialFolder.Desktop), - $"{Other.Home}/Desktop", - $"{Other.Home}/Desktop" - )!; + GetEnvironmentVariable("XDG_DESKTOP_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetFolderPath(SpecialFolder.Desktop), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Desktop"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Desktop"), + _ => string.Empty + }; } /// - public static string? DownloadDir + public static string DownloadDir { get => - Helpers.OS( - "XDG_DOWNLOAD_DIR", - null, // TODO: Actually Implement? - $"{Other.Home}/Downloads", - $"{Other.Home}/Downloads" - )!; + GetEnvironmentVariable("XDG_DOWNLOAD_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + // TODO: Implement this ourselves because Microsoft doesn't. + Helpers.OS.Windows => string.Empty, + Helpers.OS.MacOS => Path.Combine(Other.Home, "Downloads"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Downloads"), + _ => string.Empty + }; } /// public static string DocumentsDir { get => - Helpers.OS( - "XDG_DOCUMENTS_DIR", - GetFolderPath(SpecialFolder.MyDocuments), - $"{Other.Home}/Documents", - $"{Other.Home}/Documents" - )!; + GetEnvironmentVariable("XDG_DOCUMENTS_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetFolderPath(SpecialFolder.MyDocuments), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Documents"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Documents"), + _ => string.Empty + }; } /// public static string MusicDir { get => - Helpers.OS( - "XDG_MUSIC_DIR", - GetFolderPath(SpecialFolder.MyMusic), - $"{Other.Home}/Music", - $"{Other.Home}/Music" - )!; + GetEnvironmentVariable("XDG_MUSIC_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetFolderPath(SpecialFolder.MyMusic), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Music"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Music"), + _ => string.Empty + }; } /// public static string PicturesDir { get => - Helpers.OS( - "XDG_PICTURES_DIR", - GetFolderPath(SpecialFolder.MyPictures), - $"{Other.Home}/Pictures", - $"{Other.Home}/Pictures" - )!; + GetEnvironmentVariable("XDG_PICTURES_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetFolderPath(SpecialFolder.MyPictures), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Pictures"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Pictures"), + _ => string.Empty + }; } /// public static string VideosDir { get => - Helpers.OS( - "XDG_VIDEOS_DIR", - GetFolderPath(SpecialFolder.MyVideos), - $"{Other.Home}/Movies", - $"{Other.Home}/Videos" - )!; + GetEnvironmentVariable("XDG_VIDEOS_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetFolderPath(SpecialFolder.MyVideos), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Movies"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Videos"), + _ => string.Empty + }; } /// public static string TemplatesDir { get => - Helpers.OS( - "XDG_TEMPLATES_DIR", - GetFolderPath(SpecialFolder.Templates), - $"{Other.Home}/Templates", - $"{Other.Home}/Templates" - )!; + GetEnvironmentVariable("XDG_TEMPLATES_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetFolderPath(SpecialFolder.Templates), + Helpers.OS.MacOS => Path.Combine(Other.Home, "Templates"), + Helpers.OS.UnixLike => Path.Combine(Other.Home, "Templates"), + _ => string.Empty + }; } /// public static string PublicDir { get => - Helpers.OS( - "XDG_PUBLICSHARE_DIR", - GetEnvironmentVariable("PUBLIC"), - $"{Other.Home}/Public", - $"{Other.Home}/Public" - )!; + GetEnvironmentVariable("XDG_PUBLICSHARE_DIR") + ?? Helpers.GetCurrentOperatingSystem() switch + { + Helpers.OS.Windows => GetEnvironmentVariable("PUBLIC") ?? string.Empty, + Helpers.OS.MacOS => Path.Combine(Other.Home, "Public"), + Helpers.OS.UnixLike => $"{Other.Home}/Public", + _ => string.Empty + }; } } diff --git a/src/Xdg.Directories/Usings.cs b/src/Xdg.Directories/Usings.cs index 16e5d50..b6bfab4 100644 --- a/src/Xdg.Directories/Usings.cs +++ b/src/Xdg.Directories/Usings.cs @@ -1 +1 @@ -global using static System.Environment; \ No newline at end of file +global using static System.Environment; diff --git a/src/Xdg.Directories/Xdg.Directories.csproj b/src/Xdg.Directories/Xdg.Directories.csproj index ee08fd8..af3d1b8 100644 --- a/src/Xdg.Directories/Xdg.Directories.csproj +++ b/src/Xdg.Directories/Xdg.Directories.csproj @@ -24,7 +24,7 @@ True README.md - LICENSE + MIT True snupkg xdg;base-directories;base-directory;xdg-base-directory;directory;freedesktop;cross-platform @@ -74,4 +74,4 @@ - \ No newline at end of file + diff --git a/src/Xdg.Directories/docs/BaseDirectory.xml b/src/Xdg.Directories/docs/BaseDirectory.xml index a5ef53f..9fdb899 100644 --- a/src/Xdg.Directories/docs/BaseDirectory.xml +++ b/src/Xdg.Directories/docs/BaseDirectory.xml @@ -155,7 +155,7 @@ Windows - null + ""
Windows does not support this by default.
@@ -163,7 +163,7 @@ macOS - null + ""
macOS does not support this by default.
diff --git a/src/Xdg.Testing/Directories/BaseDirectory_test.cs b/src/Xdg.Testing/Directories/BaseDirectory_test.cs index c652ec8..d19f3ba 100644 --- a/src/Xdg.Testing/Directories/BaseDirectory_test.cs +++ b/src/Xdg.Testing/Directories/BaseDirectory_test.cs @@ -12,42 +12,57 @@ public class BaseDirectory_Test public void DataHome_Windows_Default() { Helper.Prepare("XDG_DATA_HOME", null, "Windows"); - Assert.AreEqual(BaseDirectory.DataHome, GetFolderPath(SpecialFolder.LocalApplicationData)); + Assert.AreEqual( + BaseDirectory.DataHome, + GetFolderPath(SpecialFolder.LocalApplicationData) + ); } [TestMethod, TestCategory("ConfigHome")] public void ConfigHome_Windows_Default() { Helper.Prepare("XDG_CONFIG_HOME", null, "Windows"); - Assert.AreEqual(BaseDirectory.ConfigHome, GetFolderPath(SpecialFolder.LocalApplicationData)); + Assert.AreEqual( + BaseDirectory.ConfigHome, + GetFolderPath(SpecialFolder.LocalApplicationData) + ); } [TestMethod, TestCategory("StateHome")] public void StateHome_Windows_Default() { Helper.Prepare("XDG_STATE_HOME", null, "Windows"); - Assert.AreEqual(GetFolderPath(SpecialFolder.LocalApplicationData), BaseDirectory.StateHome); + Assert.AreEqual( + GetFolderPath(SpecialFolder.LocalApplicationData), + BaseDirectory.StateHome + ); } [TestMethod, TestCategory("BinHome")] public void BinHome_Windows_Default() { Helper.Prepare("XDG_BIN_HOME", null, "Windows"); - Assert.IsNull(BaseDirectory.BinHome); + Assert.AreEqual(string.Empty, BaseDirectory.BinHome); } [TestMethod, TestCategory("CacheHome")] public void CacheHome_Windows_Default() { Helper.Prepare("XDG_CACHE_HOME", null, "Windows"); - Assert.AreEqual($"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\cache", BaseDirectory.CacheHome); + Assert.AreEqual( + $"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\cache", + BaseDirectory.CacheHome + ); } [TestMethod, TestCategory("RuntimeDir")] public void RuntimeDir_Windows_Default() { Helper.Prepare("XDG_RUNTIME_DIR", null, "Windows"); - Assert.AreEqual(GetFolderPath(SpecialFolder.LocalApplicationData), BaseDirectory.RuntimeDir); + Assert.AreEqual( + GetFolderPath(SpecialFolder.LocalApplicationData), + BaseDirectory.RuntimeDir + ); } [TestMethod, TestCategory("DataDirs")] @@ -55,7 +70,11 @@ public class BaseDirectory_Test { Helper.Prepare("XDG_DATA_DIRS", null, "Windows"); CollectionAssert.AreEqual( - new string[] { GetEnvironmentVariable("APPDATA")!, GetEnvironmentVariable("PROGRAMDATA")! }, + new string[] + { + GetEnvironmentVariable("APPDATA")!, + GetEnvironmentVariable("PROGRAMDATA")! + }, (System.Collections.ICollection)BaseDirectory.DataDirs ); } @@ -65,7 +84,11 @@ public class BaseDirectory_Test { Helper.Prepare("XDG_CONFIG_DIRS", null, "Windows"); CollectionAssert.AreEqual( - new string[] { GetEnvironmentVariable("PROGRAMDATA")!, GetEnvironmentVariable("APPDATA")! }, + new string[] + { + GetEnvironmentVariable("PROGRAMDATA")!, + GetEnvironmentVariable("APPDATA")! + }, (System.Collections.ICollection)BaseDirectory.ConfigDirs ); } @@ -131,7 +154,12 @@ public class BaseDirectory_Test { Helper.Prepare("XDG_CONFIG_DIRS", null, "MacOS"); CollectionAssert.AreEqual( - new string[] { $"{Other.Home}/Library/Preferences", "/Library/Application Support", "/Library/Preferences" }, + new string[] + { + $"{Other.Home}/Library/Preferences", + "/Library/Application Support", + "/Library/Preferences" + }, (System.Collections.ICollection)BaseDirectory.ConfigDirs ); } @@ -179,7 +207,7 @@ public class BaseDirectory_Test public void RuntimeDir_Linux_Default() { Helper.Prepare("XDG_RUNTIME_DIR", null, "Linux"); - Assert.AreEqual($"/run/user/{GetEnvironmentVariable("UID")}", BaseDirectory.RuntimeDir); + Assert.AreEqual($"/run/user/{GetEnvironmentVariable("UID") ?? "0"}", BaseDirectory.RuntimeDir); } [TestMethod, TestCategory("DataDirs")] @@ -268,4 +296,4 @@ public class BaseDirectory_Test ); } } -} \ No newline at end of file +} diff --git a/src/Xdg.Testing/Directories/HelperMethods.cs b/src/Xdg.Testing/Directories/HelperMethods.cs index 7c16ac5..e805184 100644 --- a/src/Xdg.Testing/Directories/HelperMethods.cs +++ b/src/Xdg.Testing/Directories/HelperMethods.cs @@ -1,6 +1,7 @@ using System.Runtime.InteropServices; namespace Xdg.Testing.Directories; + internal static class Helper { public static void Prepare(string Env, string? EnvValue, string OS) diff --git a/src/Xdg.Testing/Directories/Other_test.cs b/src/Xdg.Testing/Directories/Other_test.cs index 569eefd..3cafc74 100644 --- a/src/Xdg.Testing/Directories/Other_test.cs +++ b/src/Xdg.Testing/Directories/Other_test.cs @@ -26,14 +26,28 @@ public class Other_Test public void Applications_Windows_Default() { Helper.Prepare("DISCARD", null, "Windows"); - CollectionAssert.AreEquivalent(new string[] { GetFolderPath(SpecialFolder.Programs), GetFolderPath(SpecialFolder.CommonPrograms) }, (System.Collections.ICollection)Other.Applications); + CollectionAssert.AreEquivalent( + new string[] + { + GetFolderPath(SpecialFolder.Programs), + GetFolderPath(SpecialFolder.CommonPrograms) + }, + (System.Collections.ICollection)Other.Applications + ); } [TestMethod, TestCategory("Fonts")] public void Fonts_Windows_Default() { Helper.Prepare("DISCARD", null, "Windows"); - CollectionAssert.AreEquivalent(new string[] { GetFolderPath(SpecialFolder.Fonts), $"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\Microsoft\\Windows\\Fonts" }, (System.Collections.ICollection)Other.Fonts); + CollectionAssert.AreEquivalent( + new string[] + { + GetFolderPath(SpecialFolder.Fonts), + $"{GetFolderPath(SpecialFolder.LocalApplicationData)}\\Microsoft\\Windows\\Fonts" + }, + (System.Collections.ICollection)Other.Fonts + ); } } @@ -58,14 +72,26 @@ public class Other_Test public void Applications_MacOS_Default() { Helper.Prepare("DISCARD", null, "macOS"); - CollectionAssert.AreEquivalent(new string[] { "/Applications" }, (System.Collections.ICollection)Other.Applications); + CollectionAssert.AreEquivalent( + new string[] { "/Applications" }, + (System.Collections.ICollection)Other.Applications + ); } [TestMethod, TestCategory("Fonts")] public void Fonts_MacOS_Default() { Helper.Prepare("DISCARD", null, "macOS"); - CollectionAssert.AreEquivalent(new string[] { $"{Other.Home}/Library/Fonts", "/Library/Fonts", "/System/Library/Fonts", "/Network/Library/Fonts" }, (System.Collections.ICollection)Other.Fonts); + CollectionAssert.AreEquivalent( + new string[] + { + $"{Other.Home}/Library/Fonts", + "/Library/Fonts", + "/System/Library/Fonts", + "/Network/Library/Fonts" + }, + (System.Collections.ICollection)Other.Fonts + ); } } @@ -76,7 +102,7 @@ public class Other_Test public void Home_Linux_Default() { Helper.Prepare("DISCARD", null, "Linux"); - Assert.AreEqual(GetEnvironmentVariable("HOME"), Other.Home); + Assert.AreEqual(GetFolderPath(SpecialFolder.UserProfile), Other.Home); } [TestMethod, TestCategory("Home")] @@ -90,14 +116,33 @@ public class Other_Test public void Applications_Linux_Default() { Helper.Prepare("DISCARD", null, "Linux"); - CollectionAssert.AreEquivalent(new string[] { $"{BaseDirectory.DataHome}/applications", $"{Other.Home}/.local/share/applications", "/usr/local/share/applications", "/usr/share/applications", }, (System.Collections.ICollection)Other.Applications); + CollectionAssert.AreEquivalent( + new string[] + { + $"{BaseDirectory.DataHome}/applications", + $"{Other.Home}/.local/share/applications", + "/usr/local/share/applications", + "/usr/share/applications", + }, + (System.Collections.ICollection)Other.Applications + ); } [TestMethod, TestCategory("Fonts")] public void Fonts_Linux_Default() { Helper.Prepare("DISCARD", null, "Linux"); - CollectionAssert.AreEquivalent(new string[] { $"{BaseDirectory.DataHome}/fonts", $"{Other.Home}/.fonts", $"{Other.Home}/.local/share/fonts", "/usr/local/share/fonts", "/usr/share/fonts", }, (System.Collections.ICollection)Other.Fonts); + CollectionAssert.AreEquivalent( + new string[] + { + $"{BaseDirectory.DataHome}/fonts", + $"{Other.Home}/.fonts", + $"{Other.Home}/.local/share/fonts", + "/usr/local/share/fonts", + "/usr/share/fonts", + }, + (System.Collections.ICollection)Other.Fonts + ); } } } diff --git a/src/Xdg.Testing/Directories/UserDirectory_test.cs b/src/Xdg.Testing/Directories/UserDirectory_test.cs index 09eaf6d..bf64857 100644 --- a/src/Xdg.Testing/Directories/UserDirectory_test.cs +++ b/src/Xdg.Testing/Directories/UserDirectory_test.cs @@ -19,7 +19,7 @@ public class UserDirectory_Test public void DownloadDir_Windows_Default() { Helper.Prepare("XDG_DOWNLOAD_DIR", null, "Windows"); - Assert.IsNull(UserDirectory.DownloadDir); + Assert.AreEqual(string.Empty, UserDirectory.DownloadDir); } [TestMethod, TestCategory("DocumentsDir")] @@ -244,4 +244,4 @@ public class UserDirectory_Test Assert.AreEqual("/", UserDirectory.PublicDir); } } -} \ No newline at end of file +} diff --git a/src/Xdg.Testing/Usings.cs b/src/Xdg.Testing/Usings.cs index 99b2ca9..7ba5fc5 100644 --- a/src/Xdg.Testing/Usings.cs +++ b/src/Xdg.Testing/Usings.cs @@ -1,2 +1,2 @@ global using Microsoft.VisualStudio.TestTools.UnitTesting; -global using static System.Environment; \ No newline at end of file +global using static System.Environment;