Forge
csharp3407750f
1using System.Data;
2using Microsoft.EntityFrameworkCore;
3using Microsoft.EntityFrameworkCore.Infrastructure;
4
5namespace AgentForge.Data;
6
7internal static class ForgeDatabaseBootstrap
8{
9 internal const string InitialMigrationId = "20260612034124_Initial";
10
11 internal static void ApplyKernel(ForgeDbContext db)
12 {
13 if (!ForgeSchemaProbe.TableExists(db, "repos"))
14 {
15 db.Database.Migrate();
16 return;
17 }
18
19 if (!MigrationHistory.IsApplied(db, InitialMigrationId))
20 {
21 ForgeLegacyKernelSchemaPatcher.Apply(db);
22 MigrationHistory.Stamp(db, InitialMigrationId);
23 return;
24 }
25
26 db.Database.Migrate();
27 }
28}
29
30internal static class MigrationHistory
31{
32 internal static bool IsApplied(ForgeDbContext db, string migrationId)
33 {
34 if (!ForgeSchemaProbe.TableExists(db, "__EFMigrationsHistory"))
35 return false;
36
37 var connection = db.Database.GetDbConnection();
38 var openedHere = connection.State != ConnectionState.Open;
39 if (openedHere)
40 connection.Open();
41
42 try
43 {
44 using var command = connection.CreateCommand();
45 var escaped = migrationId.Replace("'", "''", StringComparison.Ordinal);
46 command.CommandText =
47 $"SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '{escaped}'";
48 return Convert.ToInt64(command.ExecuteScalar()) > 0;
49 }
50 finally
51 {
52 if (openedHere)
53 connection.Close();
54 }
55 }
56
57 internal static void Stamp(ForgeDbContext db, string migrationId)
58 {
59 db.Database.ExecuteSqlRaw(
60 """
61 CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
62 "MigrationId" TEXT PRIMARY KEY,
63 "ProductVersion" TEXT NOT NULL);
64 """);
65 db.Database.ExecuteSqlRaw(
66 """
67 INSERT OR IGNORE INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
68 VALUES ({0}, {1});
69 """,
70 migrationId,
71 ProductInfo.GetVersion());
72 }
73}
74
75internal static class ForgeLegacyKernelSchemaPatcher
76{
77 internal static void Apply(ForgeDbContext db) => EnsureCommitProvenanceTable(db);
78
79 private static void EnsureCommitProvenanceTable(ForgeDbContext db)
80 {
81 if (ForgeSchemaProbe.TableExists(db, "commit_provenance"))
82 return;
83
84 db.Database.ExecuteSqlRaw(
85 """
86 CREATE TABLE IF NOT EXISTS "commit_provenance" (
87 "Id" TEXT PRIMARY KEY,
88 "Actor" TEXT NOT NULL,
89 "Anchors" TEXT NOT NULL,
90 "Branch" TEXT NOT NULL,
91 "DriveMode" TEXT,
92 "IssueNumbers" TEXT NOT NULL,
93 "LogicalLineId" TEXT,
94 "MrNumber" INT,
95 "RecordedAt" TEXT NOT NULL,
96 "RepoId" TEXT NOT NULL,
97 "RunId" TEXT,
98 "Sha" TEXT NOT NULL,
99 CONSTRAINT "FK_commit_provenance_repos_RepoId" FOREIGN KEY ("RepoId") REFERENCES "repos" ("Id") ON DELETE CASCADE);
100 """);
101 db.Database.ExecuteSqlRaw(
102 """
103 CREATE INDEX IF NOT EXISTS "IX_commit_provenance_RepoId" ON "commit_provenance" ("RepoId");
104 """);
105 db.Database.ExecuteSqlRaw(
106 """
107 CREATE UNIQUE INDEX IF NOT EXISTS "IX_commit_provenance_RepoId_Sha" ON "commit_provenance" ("RepoId", "Sha");
108 """);
109 }
110}
111
View only · write via MCP/CIDE