53 lines
1.8 KiB
C#
53 lines
1.8 KiB
C#
using System.Text.Json;
|
|
|
|
namespace Sdt.Config;
|
|
|
|
public static class WorkspaceLoader
|
|
{
|
|
private const string FileName = "sdt-workspace.json";
|
|
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
{
|
|
PropertyNameCaseInsensitive = true,
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
AllowTrailingCommas = true,
|
|
ReadCommentHandling = JsonCommentHandling.Skip,
|
|
};
|
|
|
|
/// <summary>
|
|
/// Walks up from <paramref name="startDir"/> (or CWD) to find sdt-workspace.json.
|
|
/// Returns null if not found.
|
|
/// </summary>
|
|
public static (WorkspaceConfig Config, string WorkspaceRoot)? FindAndLoad(string? startDir = null)
|
|
{
|
|
var dir = new DirectoryInfo(startDir ?? Directory.GetCurrentDirectory());
|
|
while (dir is not null)
|
|
{
|
|
var candidate = Path.Combine(dir.FullName, FileName);
|
|
if (File.Exists(candidate))
|
|
{
|
|
try
|
|
{
|
|
var json = File.ReadAllText(candidate);
|
|
var config = JsonSerializer.Deserialize<WorkspaceConfig>(json, JsonOptions)
|
|
?? throw new InvalidOperationException($"{FileName} deserialized to null.");
|
|
return (config, dir.FullName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Failed to parse {FileName} at {candidate}: {ex.Message}", ex);
|
|
}
|
|
}
|
|
dir = dir.Parent!;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolves the absolute project root for a workspace project entry.
|
|
/// </summary>
|
|
public static string ResolveProjectRoot(string workspaceRoot, WorkspaceProject project)
|
|
=> Path.GetFullPath(Path.Combine(workspaceRoot, project.Path));
|
|
}
|