Forge
csharpdeeb25a2
1using System.Text.Json;
2
3namespace CascadeIDE.Services;
4
5/// <summary>
6/// Сохранение выбранного стартового проекта для отладки; канон — <c>LaunchProfilesStore</c> / <c>launch-profiles.toml</c> (ADR 0090),
7/// <c>startup-project.json</c> — зеркалирование для совместимости.
8/// </summary>
9public static class StartupProjectStore
10{
11 private const string FileName = "startup-project.json";
12
13 public static string GetStorePath(string solutionPath)
14 {
15 var root = BreakpointsFileService.GetWorkspaceRoot(solutionPath);
16 if (string.IsNullOrEmpty(root))
17 return "";
18 return Path.Combine(root, ".cascade-ide", FileName);
19 }
20
21 public static bool TryLoad(string solutionPath, out string? projectPathRelative)
22 {
23 if (LaunchProfilesStore.TryGetActiveProjectRelativePath(solutionPath, out var fromToml, out _) &&
24 !string.IsNullOrEmpty(fromToml))
25 {
26 projectPathRelative = fromToml;
27 return true;
28 }
29
30 return TryLoadLegacyJsonOnly(solutionPath, out projectPathRelative);
31 }
32
33 /// <summary>Только <c>startup-project.json</c>, без чтения TOML (миграция / fallback).</summary>
34 internal static bool TryLoadLegacyJsonOnly(string solutionPath, out string? projectPathRelative)
35 {
36 projectPathRelative = null;
37 var storePath = GetStorePath(solutionPath);
38 if (string.IsNullOrEmpty(storePath) || !File.Exists(storePath))
39 return false;
40
41 try
42 {
43 var json = File.ReadAllText(storePath);
44 var dto = JsonSerializer.Deserialize<Dto>(json);
45 var rel = dto?.StartupProjectRelativePath?.Trim().Replace('/', Path.DirectorySeparatorChar);
46 if (string.IsNullOrEmpty(rel))
47 return false;
48 projectPathRelative = rel;
49 return true;
50 }
51 catch
52 {
53 return false;
54 }
55 }
56
57 public static void Save(string solutionPath, string projectPathRelativeToSolution)
58 {
59 LaunchProfilesStore.UpsertActiveProject(solutionPath, projectPathRelativeToSolution);
60 var storePath = GetStorePath(solutionPath);
61 if (string.IsNullOrEmpty(storePath))
62 return;
63 var rel = projectPathRelativeToSolution.Trim().Replace('/', Path.DirectorySeparatorChar);
64 var dir = Path.GetDirectoryName(storePath);
65 if (!string.IsNullOrEmpty(dir))
66 Directory.CreateDirectory(dir);
67 var dto = new Dto { StartupProjectRelativePath = rel };
68 var json = JsonSerializer.Serialize(dto, new JsonSerializerOptions { WriteIndented = true });
69 File.WriteAllText(storePath, json);
70 }
71
72 public static void Clear(string solutionPath)
73 {
74 LaunchProfilesStore.Delete(solutionPath);
75 var storePath = GetStorePath(solutionPath);
76 if (!string.IsNullOrEmpty(storePath) && File.Exists(storePath))
77 {
78 try { File.Delete(storePath); }
79 catch { /* ignore */ }
80 }
81 }
82
83 private sealed class Dto
84 {
85 public string? StartupProjectRelativePath { get; set; }
86 }
87}
88
View only · write via MCP/CIDE