Skip to content

Commit

Permalink
Merge pull request #32 from Nexus-Mods/xdg-base-directories
Browse files Browse the repository at this point in the history
Add XDG Base Directories
  • Loading branch information
Al12rs authored Nov 27, 2023
2 parents 9aff411 + 96e00e0 commit 538048f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/NexusMods.Paths/FileSystemAbstraction/BaseFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ public bool HasKnownPath(KnownPath knownPath)
KnownPath.LocalApplicationDataDirectory => true,
KnownPath.MyDocumentsDirectory => true,
KnownPath.MyGamesDirectory => true,

KnownPath.XDG_CONFIG_HOME => OS.IsLinux,
KnownPath.XDG_CACHE_HOME => OS.IsLinux,
KnownPath.XDG_DATA_HOME => OS.IsLinux,
KnownPath.XDG_STATE_HOME => OS.IsLinux,
KnownPath.XDG_RUNTIME_DIR => OS.IsLinux,
};

bool IsWindowsOrMapped()
Expand Down Expand Up @@ -180,11 +186,25 @@ public virtual AbsolutePath GetKnownPath(KnownPath knownPath)
KnownPath.LocalApplicationDataDirectory => FromUnsanitizedFullPath(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)),
KnownPath.MyDocumentsDirectory => FromUnsanitizedFullPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)),
KnownPath.MyGamesDirectory => FromUnsanitizedDirectoryAndFileName(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "My Games"),

KnownPath.XDG_CONFIG_HOME => GetXDGBaseDirectory($"{nameof(KnownPath.XDG_CONFIG_HOME)}", static fs => fs.GetKnownPath(KnownPath.HomeDirectory).Combine(".config")),
KnownPath.XDG_CACHE_HOME => GetXDGBaseDirectory($"{nameof(KnownPath.XDG_CACHE_HOME)}", static fs => fs.GetKnownPath(KnownPath.HomeDirectory).Combine(".cache")),
KnownPath.XDG_DATA_HOME => GetXDGBaseDirectory($"{nameof(KnownPath.XDG_DATA_HOME)}", static fs => fs.GetKnownPath(KnownPath.HomeDirectory).Combine(".local").Combine("share")),
KnownPath.XDG_STATE_HOME => GetXDGBaseDirectory($"{nameof(KnownPath.XDG_STATE_HOME)}", static fs => fs.GetKnownPath(KnownPath.HomeDirectory).Combine(".local").Combine("state")),
KnownPath.XDG_RUNTIME_DIR => GetXDGBaseDirectory($"{nameof(KnownPath.XDG_RUNTIME_DIR)}", static fs => fs.GetKnownPath(KnownPath.TempDirectory)),
};

Debug.Assert(path != default, $"{nameof(GetKnownPath)} returns 'default' for {nameof(KnownPath)} '{knownPath}'. You forgot to add a mapping for this {nameof(KnownPath)}!");
return path;

AbsolutePath GetXDGBaseDirectory(string environmentVariable, Func<IFileSystem, AbsolutePath> defaultFunc)
{
if (!OS.IsLinux) throw OS.CreatePlatformNotSupportedException();

var value = Environment.GetEnvironmentVariable(environmentVariable, EnvironmentVariableTarget.Process);
return value is null ? defaultFunc(this) : FromUnsanitizedFullPath(value);
}

AbsolutePath ThisOrDefault(string fullPath)
{
return string.IsNullOrWhiteSpace(fullPath) ? default : FromUnsanitizedFullPath(fullPath);
Expand Down Expand Up @@ -233,8 +253,11 @@ public static (Dictionary<AbsolutePath, AbsolutePath> pathMappings, Dictionary<K
KnownPath.LocalApplicationDataDirectory => newHomeDirectory.Combine("AppData/Local"),
KnownPath.ApplicationDataDirectory => newHomeDirectory.Combine("AppData/Roaming"),
KnownPath.TempDirectory => newHomeDirectory.Combine("AppData/Local/Temp"),

_ => default
};

if (newPath == default) continue;
knownPathMappings[knownPath] = newPath;
}

Expand Down
36 changes: 36 additions & 0 deletions src/NexusMods.Paths/FileSystemAbstraction/KnownPath.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using JetBrains.Annotations;

Expand Down Expand Up @@ -295,4 +296,39 @@ public enum KnownPath
/// <see cref="MyDocumentsDirectory"/> with <c>My Games</c>.
/// </remarks>
MyGamesDirectory,

/// <summary>
/// <c>$XDG_CONFIG_HOME</c> defines the base directory relative to which user-specific configuration files should be stored.
/// If <c>$XDG_CONFIG_HOME</c> is either not set or empty, a default equal to <c>$HOME/.config</c> should be used.
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
XDG_CONFIG_HOME,

/// <summary>
/// <c>$XDG_CACHE_HOME</c> defines the base directory relative to which user-specific non-essential data files should be stored.
/// If <c>$XDG_CACHE_HOME</c> is either not set or empty, a default equal to <c>$HOME/.cache</c> should be used.
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
XDG_CACHE_HOME,

/// <summary>
/// <c>$XDG_DATA_HOME</c> defines the base directory relative to which user-specific data files should be stored.
/// If <c>$XDG_DATA_HOME</c> is either not set or empty, a default equal to <c>$HOME/.local/share</c> should be used.
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
XDG_DATA_HOME,

/// <summary>
/// <c>$XDG_STATE_HOME</c> defines the base directory relative to which user-specific state files should be stored.
/// If <c>$XDG_STATE_HOME</c> is either not set or empty, a default equal to <c>$HOME/.local/state</c> should be used.
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
XDG_STATE_HOME,

/// <summary>
/// <c>$XDG_RUNTIME_DIR</c> defines the base directory relative to which user-specific non-essential runtime files and other file objects (such as sockets, named pipes, ...) should be stored.
/// The directory MUST be owned by the user, and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700.
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
XDG_RUNTIME_DIR,
}

0 comments on commit 538048f

Please sign in to comment.