using System;
using System.IO;
using System.Reflection;
using LANCommander.SDK.Helpers;
namespace LANCommander.SDK;
public static class AppPaths
{
private static string _configDirectory = String.Empty;
///
/// Builds a full path under the application's config directory.
///
/// Additional path segments appended to the config directory.
/// The combined path under the config directory.
public static string GetConfigPath(params string[] paths)
=> Path.Combine(GetConfigDirectory(), Path.Combine(paths));
///
/// Locates (and creates if necessary) the directory in which application data will be stored.
/// Prefers the current working directory when writable; otherwise falls back to the user's local application data.
///
/// The resolved config directory path.
public static string GetConfigDirectory()
{
if (!String.IsNullOrWhiteSpace(_configDirectory))
return _configDirectory;
var baseDirectory = Directory.GetCurrentDirectory();
if (DirectoryHelper.IsDirectoryWritable(baseDirectory))
_configDirectory = baseDirectory;
else
_configDirectory = GetAppDataPath();
_configDirectory = Path.Combine(_configDirectory, "Data");
if (!Directory.Exists(_configDirectory))
Directory.CreateDirectory(_configDirectory);
return _configDirectory;
}
///
/// Gets (and creates if necessary) the base local application data directory for the current user,
/// scoped by the entry assembly's company and product metadata.
///
/// The local application data path for this application.
public static string GetAppDataPath()
{
var (company, product) = GetCompanyAndProduct();
var userRoot = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var appDataPath = Path.Combine(userRoot, company, product);
if (!Directory.Exists(appDataPath))
Directory.CreateDirectory(appDataPath);
return appDataPath;
}
///
/// Checks if the config directory is currently mounted. This should be used in Docker containers only.
///
/// true if the config directory is a mount point; otherwise false.
public static bool ConfigDirectoryIsMounted()
{
var path = GetConfigDirectory();
var fullPath = Path.GetFullPath(path);
foreach (var line in File.ReadLines("/proc/self/mountinfo"))
{
// mountinfo format: see `man proc`
var parts = line.Split(' ');
if (parts.Length > 4)
{
var mountPoint = parts[4];
if (string.Equals(mountPoint, fullPath, StringComparison.Ordinal))
return true;
}
}
return false;
}
///
/// Reads company and product metadata from the entry assembly (or executing assembly as a fallback).
///
/// A tuple containing company and product strings (may be null if not defined).
private static (string? Company, string? Product) GetCompanyAndProduct()
{
var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
var company = assembly.GetCustomAttribute()?.Company;
var product = assembly.GetCustomAttribute()?.Product;
return (company, product);
}
}