TeamCity.CSharpInteractive/Environment.cs (105 lines of code) (raw):
// ReSharper disable ClassNeverInstantiated.Global
namespace TeamCity.CSharpInteractive;
using System.Diagnostics.CodeAnalysis;
using Microsoft.DotNet.PlatformAbstractions;
internal class Environment:
IEnvironment,
ITraceSource,
IScriptContext,
IErrorContext
{
private readonly LinkedList<ICodeSource> _sources = new();
public Platform OperatingSystemPlatform => RuntimeEnvironment.OperatingSystemPlatform;
public string ProcessArchitecture => RuntimeEnvironment.RuntimeArchitecture;
public IEnumerable<string> GetCommandLineArgs() => System.Environment.GetCommandLineArgs();
public string GetPath(SpecialFolder specialFolder)
{
switch (OperatingSystemPlatform)
{
case Platform.Windows:
return specialFolder switch
{
SpecialFolder.Bin => GetBinDirectory(),
SpecialFolder.Temp => Path.GetFullPath(System.Environment.GetEnvironmentVariable("TMP") ?? Path.GetTempPath()),
SpecialFolder.ProgramFiles => System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles),
SpecialFolder.Script => GetScriptDirectory(),
SpecialFolder.Working => GetWorkingDirectory(),
_ => throw new ArgumentOutOfRangeException(nameof(specialFolder), specialFolder, null)
};
case Platform.Unknown:
case Platform.Linux:
case Platform.Darwin:
case Platform.FreeBSD:
return specialFolder switch
{
SpecialFolder.Bin => GetBinDirectory(),
SpecialFolder.Temp => Path.GetFullPath(System.Environment.GetEnvironmentVariable("TMPDIR") ?? Path.GetTempPath()),
SpecialFolder.ProgramFiles => "usr/local/share",
SpecialFolder.Script => GetScriptDirectory(),
SpecialFolder.Working => GetWorkingDirectory(),
_ => throw new ArgumentOutOfRangeException(nameof(specialFolder), specialFolder, null)
};
default:
throw new ArgumentOutOfRangeException(nameof(specialFolder));
}
}
public void Exit(int exitCode) => System.Environment.Exit(exitCode);
public IEnumerable<Text> Trace
{
get
{
yield return new Text($"OperatingSystemPlatform: {OperatingSystemPlatform}");
yield return Text.NewLine;
yield return new Text($"ProcessArchitecture: {ProcessArchitecture}");
yield return Text.NewLine;
foreach (var specialFolder in Enum.GetValues(typeof(SpecialFolder)).OfType<SpecialFolder>())
{
yield return new Text($"Path({specialFolder}): {GetPath(specialFolder)}");
yield return Text.NewLine;
}
yield return new Text("Command line arguments:");
yield return Text.NewLine;
foreach (var arg in System.Environment.GetCommandLineArgs())
{
yield return Text.Tab;
yield return new Text(arg);
yield return Text.NewLine;
}
}
}
public IDisposable CreateScope(ICodeSource source)
{
_sources.AddLast(source);
return Disposable.Create(() => _sources.Remove(source));
}
public bool TryGetSourceName([NotNullWhen(true)] out string? name)
{
if (TryGetCurrentSource(out var source))
{
name = Path.GetFileName(source.Name);
return !string.IsNullOrWhiteSpace(name);
}
name = default;
return false;
}
private bool TryGetCurrentSource([NotNullWhen(true)] out ICodeSource? source)
{
source = _sources.LastOrDefault();
return source != default;
}
private static string GetWorkingDirectory() => Directory.GetCurrentDirectory();
private string GetBinDirectory() => Path.GetDirectoryName(typeof(Environment).Assembly.Location) ?? GetScriptDirectory();
private string GetScriptDirectory()
{
var script = string.Empty;
if (TryGetCurrentSource(out var source))
{
script = source.Name;
}
if (string.IsNullOrWhiteSpace(script))
{
return GetWorkingDirectory();
}
var scriptDirectory = Path.GetDirectoryName(script);
return !string.IsNullOrWhiteSpace(scriptDirectory) ? scriptDirectory : script;
}
}