Базовая работа на Linux
This commit is contained in:
172
src/Sms.Environment.Linux/LinuxEnvironmentVariableStore.cs
Normal file
172
src/Sms.Environment.Linux/LinuxEnvironmentVariableStore.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using Sms.Environment;
|
||||
|
||||
namespace Sms.Environment.Linux;
|
||||
|
||||
public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
|
||||
{
|
||||
private const string ManagedFileName = "99-sms-task-two.conf";
|
||||
|
||||
private readonly string _managedFilePath;
|
||||
private readonly string _environmentDirectory;
|
||||
|
||||
public LinuxEnvironmentVariableStore()
|
||||
: this(
|
||||
Path.Combine(
|
||||
System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile),
|
||||
".config",
|
||||
"environment.d"),
|
||||
ManagedFileName)
|
||||
{
|
||||
}
|
||||
|
||||
internal LinuxEnvironmentVariableStore(string environmentDirectory, string managedFileName)
|
||||
{
|
||||
_environmentDirectory = environmentDirectory;
|
||||
_managedFilePath = Path.Combine(environmentDirectory, managedFileName);
|
||||
}
|
||||
|
||||
public string? Get(string name)
|
||||
{
|
||||
var fromFiles = LoadMergedFromDirectory();
|
||||
if (fromFiles.TryGetValue(name, out var fileValue))
|
||||
{
|
||||
return fileValue;
|
||||
}
|
||||
|
||||
return System.Environment.GetEnvironmentVariable(name);
|
||||
}
|
||||
|
||||
public void Set(string name, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(_environmentDirectory);
|
||||
var managed = LoadManagedFile();
|
||||
managed[name] = value;
|
||||
WriteManagedFileAtomic(managed);
|
||||
System.Environment.SetEnvironmentVariable(name, value);
|
||||
}
|
||||
catch (Exception ex) when (ex is UnauthorizedAccessException or IOException)
|
||||
{
|
||||
throw new EnvironmentVariableStoreException(
|
||||
$"Failed to write environment variable '{name}' to '{_managedFilePath}'.",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists(string name) => Get(name) is not null;
|
||||
|
||||
public IReadOnlyDictionary<string, string> GetAll(IEnumerable<string> names)
|
||||
{
|
||||
var merged = LoadMergedFromDirectory();
|
||||
var result = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
foreach (var name in names)
|
||||
{
|
||||
if (merged.TryGetValue(name, out var value))
|
||||
{
|
||||
result[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var processValue = System.Environment.GetEnvironmentVariable(name);
|
||||
if (processValue is not null)
|
||||
{
|
||||
result[name] = processValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, string> GetProcessEnvironment() =>
|
||||
ToDictionary(System.Environment.GetEnvironmentVariables());
|
||||
|
||||
public IReadOnlyDictionary<string, string> GetUserPersistedEnvironment() =>
|
||||
LoadMergedFromDirectory();
|
||||
|
||||
public bool IsPersistedInUserStore(string name) =>
|
||||
LoadMergedFromDirectory().ContainsKey(name);
|
||||
|
||||
public void RemoveFromUserStore(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(_environmentDirectory))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(_environmentDirectory, "*.conf"))
|
||||
{
|
||||
var variables = SystemdEnvironmentFileParser.Parse(File.ReadAllText(file));
|
||||
if (!variables.Remove(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
WriteConfFileAtomic(file, variables);
|
||||
}
|
||||
|
||||
System.Environment.SetEnvironmentVariable(name, null);
|
||||
}
|
||||
catch (Exception ex) when (ex is UnauthorizedAccessException or IOException)
|
||||
{
|
||||
throw new EnvironmentVariableStoreException(
|
||||
$"Failed to remove environment variable '{name}' from '{_environmentDirectory}'.",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> LoadManagedFile()
|
||||
{
|
||||
if (!File.Exists(_managedFilePath))
|
||||
{
|
||||
return new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
return SystemdEnvironmentFileParser.Parse(File.ReadAllText(_managedFilePath));
|
||||
}
|
||||
|
||||
private Dictionary<string, string> LoadMergedFromDirectory()
|
||||
{
|
||||
var merged = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
if (!Directory.Exists(_environmentDirectory))
|
||||
{
|
||||
return merged;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(_environmentDirectory, "*.conf").Order(StringComparer.Ordinal))
|
||||
{
|
||||
var parsed = SystemdEnvironmentFileParser.Parse(File.ReadAllText(file));
|
||||
foreach (var pair in parsed)
|
||||
{
|
||||
merged[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
private void WriteManagedFileAtomic(Dictionary<string, string> variables) =>
|
||||
WriteConfFileAtomic(_managedFilePath, variables);
|
||||
|
||||
private static void WriteConfFileAtomic(string path, Dictionary<string, string> variables)
|
||||
{
|
||||
var content = SystemdEnvironmentFileParser.Serialize(variables);
|
||||
var tempPath = path + ".tmp";
|
||||
File.WriteAllText(tempPath, content);
|
||||
File.Move(tempPath, path, overwrite: true);
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> ToDictionary(System.Collections.IDictionary source)
|
||||
{
|
||||
var result = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
foreach (string key in source.Keys)
|
||||
{
|
||||
result[key] = source[key]?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user