History

Split git VCS driver from core service

- Introduce a dedicated `GitVcsDriver` service and `vcsLayer` - Update server, orchestration, and workspace wiring to use the new layer - Adjust tests and mocks for the new git-specific dependency

Julius Marminge committed 6 months ago

Commit 82a83941 parent 0ce293b15 files · +97 −87Browse files

Unified · Split

15 files
  1. apps/server/integration/OrchestrationEngineHarness.integration.ts +6 −7
  2. apps/server/src/checkpointing/Layers/CheckpointStore.test.ts +1 −1
  3. apps/server/src/git/Layers/GitManager.test.ts +12 −25
  4. apps/server/src/git/Layers/GitManager.ts +2 −2
  5. apps/server/src/orchestration/Layers/CheckpointReactor.test.ts +2 −2
  6. apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +6 −2
  7. apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +2 −2
  8. apps/server/src/server.test.ts +40 −30
  9. apps/server/src/server.ts +2 −2
  10. apps/server/src/vcs/GitVcsDriver.test.ts +3 −3
  11. apps/server/src/vcs/GitVcsDriver.ts +16 −5
  12. apps/server/src/vcs/VcsDriver.ts +1 −2
  13. apps/server/src/workspace/Layers/WorkspaceEntries.test.ts +1 −1
  14. apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts +1 −1
  15. apps/server/src/ws.ts +2 −2
apps/server/integration/OrchestrationEngineHarness.integration.ts+6−7
@@ -33,7 +33,6 @@ import { ProjectionCheckpointRepositoryLive } from "../src/persistence/Layers/Pr · 32 unmodified lines
3333 import { ProjectionPendingApprovalRepositoryLive } from "../src/persistence/Layers/ProjectionPendingApprovals.ts";
3434 import { ProviderSessionRuntimeRepositoryLive } from "../src/persistence/Layers/ProviderSessionRuntime.ts";
3535 import { makeSqlitePersistenceLive } from "../src/persistence/Layers/Sqlite.ts";
36−import { VcsDriver, type VcsDriverShape } from "../src/vcs/VcsDriver.ts";
3736 import { ProjectionCheckpointRepository } from "../src/persistence/Services/ProjectionCheckpoints.ts";
3837 import { ProjectionPendingApprovalRepository } from "../src/persistence/Services/ProjectionPendingApprovals.ts";
3938 import { makeAdapterRegistryMock } from "../src/provider/testUtils/providerAdapterRegistryMock.ts";
@@ -292,7 +291,7 @@ export const makeOrchestrationIntegrationHarness = ( · 252 unmodified lines
292291 Layer.provide(providerEventLoggersLayer),
293292 );
294293
295− const checkpointStoreLayer = CheckpointStoreLive.pipe(Layer.provide(GitVcsDriver.layer));
294+ const checkpointStoreLayer = CheckpointStoreLive.pipe(Layer.provide(GitVcsDriver.vcsLayer));
296295 const projectionSnapshotQueryLayer = OrchestrationProjectionSnapshotQueryLive;
297296 const runtimeServicesLayer = Layer.mergeAll(
298297 projectionSnapshotQueryLayer,
@@ -308,17 +307,17 @@ export const makeOrchestrationIntegrationHarness = ( · 9 unmodified lines
308307 Layer.provideMerge(runtimeServicesLayer),
309308 Layer.provideMerge(serverSettingsLayer),
310309 );
311− const vcsDriverLayer = Layer.succeed(VcsDriver, {
312− renameBranch: (input: Parameters<VcsDriverShape["renameBranch"]>[0]) =>
310+ const gitVcsDriverLayer = Layer.succeed(GitVcsDriver.GitVcsDriver, {
311+ renameBranch: (input: Parameters<GitVcsDriver.GitVcsDriverShape["renameBranch"]>[0]) =>
313312 Effect.succeed({ branch: input.newBranch }),
314− } as unknown as VcsDriverShape);
313+ } as unknown as GitVcsDriver.GitVcsDriverShape);
315314 const textGenerationLayer = Layer.succeed(TextGeneration, {
316315 generateBranchName: () => Effect.succeed({ branch: "update" }),
317316 generateThreadTitle: () => Effect.succeed({ title: "New thread" }),
318317 } as unknown as TextGenerationShape);
319318 const providerCommandReactorLayer = ProviderCommandReactorLive.pipe(
320319 Layer.provideMerge(runtimeServicesLayer),
321− Layer.provideMerge(vcsDriverLayer),
320+ Layer.provideMerge(gitVcsDriverLayer),
322321 Layer.provideMerge(textGenerationLayer),
323322 Layer.provideMerge(serverSettingsLayer),
324323 );
@@ -343,7 +342,7 @@ export const makeOrchestrationIntegrationHarness = ( · 18 unmodified lines
343342 Layer.provideMerge(
344343 WorkspaceEntriesLive.pipe(
345344 Layer.provide(WorkspacePathsLive),
346− Layer.provideMerge(GitVcsDriver.layer),
345+ Layer.provideMerge(GitVcsDriver.vcsLayer),
347346 Layer.provide(NodeServices.layer),
348347 ),
349348 ),
apps/server/src/checkpointing/Layers/CheckpointStore.test.ts+1−1
@@ -18,7 +18,7 @@ const ServerConfigLayer = ServerConfig.layerTest(process.cwd(), { · 17 unmodified lines
1818 prefix: "t3-checkpoint-store-test-",
1919 });
2020 const VcsProcessTestLayer = VcsProcess.layer.pipe(Layer.provide(NodeServices.layer));
21−const VcsDriverTestLayer = GitVcsDriver.layer.pipe(Layer.provide(VcsProcessTestLayer));
21+const VcsDriverTestLayer = GitVcsDriver.vcsLayer.pipe(Layer.provide(VcsProcessTestLayer));
2222 const CheckpointStoreTestLayer = CheckpointStoreLive.pipe(
2323 Layer.provideMerge(VcsDriverTestLayer),
2424 Layer.provideMerge(NodeServices.layer),
apps/server/src/git/Layers/GitManager.test.ts+12−25
@@ -23,7 +23,6 @@ import { · 22 unmodified lines
2323 import { type TextGenerationShape, TextGeneration } from "../Services/TextGeneration.ts";
2424 import * as GitVcsDriver from "../../vcs/GitVcsDriver.ts";
2525 import * as VcsProcess from "../../vcs/VcsProcess.ts";
26−import { VcsDriver } from "../../vcs/VcsDriver.ts";
2726 import { makeGitManager } from "./GitManager.ts";
2827 import { ServerConfig } from "../../config.ts";
2928 import { ServerSettingsService } from "../../serverSettings.ts";
@@ -212,30 +211,18 @@ function runGit( · 182 unmodified lines
212211 ): Effect.Effect<
213212 { readonly code: number; readonly stdout: string; readonly stderr: string },
214213 GitCommandError,
215− VcsDriver
214+ GitVcsDriver.GitVcsDriver
216215 > {
217216 return Effect.gen(function* () {
218− const vcs = yield* VcsDriver;
219− const result = yield* vcs
220− .execute({
221− operation: "GitManager.test.runGit",
222− cwd,
223− args,
224− allowNonZeroExit,
225− })
226− .pipe(
227− Effect.mapError(
228− (error) =>
229− new GitCommandError({
230− operation: "GitManager.test.runGit",
231− command: `git ${args.join(" ")}`,
232− cwd,
233− detail: error.message,
234− }),
235− ),
236− );
217+ const git = yield* GitVcsDriver.GitVcsDriver;
218+ const result = yield* git.execute({
219+ operation: "GitManager.test.runGit",
220+ cwd,
221+ args,
222+ allowNonZeroExit,
223+ });
237224 return {
238− code: result.exitCode,
225+ code: result.code,
239226 stdout: result.stdout,
240227 stderr: result.stderr,
241228 };
@@ -247,7 +234,7 @@ function initRepo( · 5 unmodified lines
247234 ): Effect.Effect<
248235 void,
249236 PlatformError.PlatformError | GitCommandError,
250− FileSystem.FileSystem | Scope.Scope | VcsDriver
237+ FileSystem.FileSystem | Scope.Scope | GitVcsDriver.GitVcsDriver
251238 > {
252239 return Effect.gen(function* () {
253240 const fs = yield* FileSystem.FileSystem;
@@ -263,7 +250,7 @@ function initRepo( · 9 unmodified lines
263250 function createBareRemote(): Effect.Effect<
264251 string,
265252 PlatformError.PlatformError | GitCommandError,
266− FileSystem.FileSystem | Scope.Scope | VcsDriver
253+ FileSystem.FileSystem | Scope.Scope | GitVcsDriver.GitVcsDriver
267254 > {
268255 return Effect.gen(function* () {
269256 const remoteDir = yield* makeTempDir("t3code-git-remote-");
@@ -277,7 +264,7 @@ function configureRemote( · 7 unmodified lines
277264 remoteName: string,
278265 remotePath: string,
279266 fetchNamespace: string,
280−): Effect.Effect<void, GitCommandError, VcsDriver> {
267+): Effect.Effect<void, GitCommandError, GitVcsDriver.GitVcsDriver> {
281268 return Effect.gen(function* () {
282269 yield* runGit(cwd, ["config", `remote.${remoteName}.url`, remotePath]);
283270 yield* runGit(cwd, [
apps/server/src/git/Layers/GitManager.ts+2−2
@@ -49,7 +49,7 @@ import { · 48 unmodified lines
4949 decodeGitHubPullRequestListJson,
5050 formatGitHubJsonDecodeError,
5151 } from "../githubPullRequests.ts";
52−import { VcsDriver } from "../../vcs/VcsDriver.ts";
52+import { GitVcsDriver } from "../../vcs/GitVcsDriver.ts";
5353
5454 const COMMIT_TIMEOUT_MS = 10 * 60_000;
5555 const MAX_PROGRESS_TEXT_LENGTH = 500;
@@ -491,7 +491,7 @@ function toPullRequestHeadRemoteInfo(pr: { · 435 unmodified lines
491491 }
492492
493493 export const makeGitManager = Effect.fn("makeGitManager")(function* () {
494− const gitCore = yield* VcsDriver;
494+ const gitCore = yield* GitVcsDriver;
495495 const gitHubCli = yield* GitHubCli;
496496 const textGeneration = yield* TextGeneration;
497497 const projectSetupScriptRunner = yield* ProjectSetupScriptRunner;
apps/server/src/orchestration/Layers/CheckpointReactor.test.ts+2−2
@@ -307,11 +307,11 @@ describe("CheckpointReactor", () => { · 306 unmodified lines
307307 Layer.provideMerge(RuntimeReceiptBusLive),
308308 Layer.provideMerge(Layer.succeed(ProviderService, provider.service)),
309309 Layer.provideMerge(gitStatusBroadcasterLayer),
310− Layer.provideMerge(CheckpointStoreLive.pipe(Layer.provide(GitVcsDriver.layer))),
310+ Layer.provideMerge(CheckpointStoreLive.pipe(Layer.provide(GitVcsDriver.vcsLayer))),
311311 Layer.provideMerge(
312312 WorkspaceEntriesLive.pipe(
313313 Layer.provide(WorkspacePathsLive),
314− Layer.provideMerge(GitVcsDriver.layer),
314+ Layer.provideMerge(GitVcsDriver.vcsLayer),
315315 ),
316316 ),
317317 Layer.provideMerge(WorkspacePathsLive),
apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts+6−2
@@ -51,7 +51,7 @@ import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; · 50 unmodified lines
5151 import { ProviderCommandReactor } from "../Services/ProviderCommandReactor.ts";
5252 import * as NodeServices from "@effect/platform-node/NodeServices";
5353 import { ServerSettingsService } from "../../serverSettings.ts";
54−import { VcsDriver, type VcsDriverShape } from "../../vcs/VcsDriver.ts";
54+import * as GitVcsDriver from "../../vcs/GitVcsDriver.ts";
5555
5656 const asProjectId = (value: string): ProjectId => ProjectId.make(value);
5757 const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value);
@@ -324,7 +324,11 @@ describe("ProviderCommandReactor", () => { · 266 unmodified lines
324324 const layer = ProviderCommandReactorLive.pipe(
325325 Layer.provideMerge(orchestrationLayer),
326326 Layer.provideMerge(Layer.succeed(ProviderService, service)),
327− Layer.provideMerge(Layer.succeed(VcsDriver, { renameBranch } as unknown as VcsDriverShape)),
327+ Layer.provideMerge(
328+ Layer.succeed(GitVcsDriver.GitVcsDriver, {
329+ renameBranch,
330+ } as unknown as GitVcsDriver.GitVcsDriverShape),
331+ ),
328332 Layer.provideMerge(
329333 Layer.succeed(GitStatusBroadcaster, {
330334 getStatus: () => Effect.die("getStatus should not be called in this test"),
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+2−2
@@ -28,7 +28,7 @@ import { · 27 unmodified lines
2828 type ProviderCommandReactorShape,
2929 } from "../Services/ProviderCommandReactor.ts";
3030 import { ServerSettingsService } from "../../serverSettings.ts";
31−import { VcsDriver } from "../../vcs/VcsDriver.ts";
31+import { GitVcsDriver } from "../../vcs/GitVcsDriver.ts";
3232
3333 type ProviderIntentEvent = Extract<
3434 OrchestrationEvent,
@@ -168,7 +168,7 @@ function buildGeneratedWorktreeBranchName(raw: string): string { · 133 unmodified lines
168168 const make = Effect.gen(function* () {
169169 const orchestrationEngine = yield* OrchestrationEngineService;
170170 const providerService = yield* ProviderService;
171− const git = yield* VcsDriver;
171+ const git = yield* GitVcsDriver;
172172 const gitStatusBroadcaster = yield* GitStatusBroadcaster;
173173 const textGeneration = yield* TextGeneration;
174174 const serverSettingsService = yield* ServerSettingsService;
apps/server/src/server.test.ts+40−30
@@ -104,6 +104,7 @@ import { · 103 unmodified lines
104104 import { WorkspaceEntriesLive } from "./workspace/Layers/WorkspaceEntries.ts";
105105 import { WorkspaceFileSystemLive } from "./workspace/Layers/WorkspaceFileSystem.ts";
106106 import { WorkspacePathsLive } from "./workspace/Layers/WorkspacePaths.ts";
107+import * as GitVcsDriver from "./vcs/GitVcsDriver.ts";
107108 import { VcsDriver, type VcsDriverShape } from "./vcs/VcsDriver.ts";
108109 import { ServerSecretStoreLive } from "./auth/Layers/ServerSecretStore.ts";
109110 import { ServerAuthLive } from "./auth/Layers/ServerAuth.ts";
@@ -315,6 +316,7 @@ const buildAppUnderTest = (options?: { · 205 unmodified lines
315316 serverSettings?: Partial<ServerSettingsShape>;
316317 open?: Partial<OpenShape>;
317318 vcsDriver?: Partial<VcsDriverShape>;
319+ gitVcsDriver?: Partial<GitVcsDriver.GitVcsDriverShape>;
318320 gitManager?: Partial<GitManagerShape>;
319321 gitStatusBroadcaster?: Partial<GitStatusBroadcasterShape>;
320322 projectSetupScriptRunner?: Partial<ProjectSetupScriptRunnerShape>;
@@ -384,6 +386,9 @@ const buildAppUnderTest = (options?: { · 63 unmodified lines
384386 filterIgnoredPaths: (_cwd, relativePaths) => Effect.succeed(relativePaths),
385387 ...options?.layers?.vcsDriver,
386388 });
389+ const gitVcsDriverLayer = Layer.mock(GitVcsDriver.GitVcsDriver)({
390+ ...options?.layers?.gitVcsDriver,
391+ });
387392 const gitManagerLayer = Layer.mock(GitManager)({
388393 ...options?.layers?.gitManager,
389394 });
@@ -444,6 +449,7 @@ const buildAppUnderTest = (options?: { · 54 unmodified lines
444449 }),
445450 ),
446451 Layer.provide(gitManagerLayer),
452+ Layer.provide(gitVcsDriverLayer),
447453 Layer.provideMerge(gitStatusBroadcasterLayer),
448454 Layer.provide(
449455 Layer.mock(ProjectSetupScriptRunner)({
@@ -2377,7 +2383,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 1927 unmodified lines
23772383 worktreePath: null,
23782384 }),
23792385 },
2380− vcsDriver: {
2386+ gitVcsDriver: {
23812387 pullCurrentBranch: () =>
23822388 Effect.succeed({
23832389 status: "pulled",
@@ -2531,7 +2537,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 147 unmodified lines
25312537 let statusCalls = 0;
25322538 yield* buildAppUnderTest({
25332539 layers: {
2534− vcsDriver: {
2540+ gitVcsDriver: {
25352541 pullCurrentBranch: () => Effect.fail(gitError),
25362542 },
25372543 gitManager: {
@@ -2685,7 +2691,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 147 unmodified lines
26852691 Effect.gen(function* () {
26862692 yield* buildAppUnderTest({
26872693 layers: {
2688− vcsDriver: {
2694+ gitVcsDriver: {
26892695 pullCurrentBranch: () =>
26902696 Effect.succeed({
26912697 status: "pulled" as const,
@@ -3499,13 +3505,14 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 807 unmodified lines
34993505 pr: null,
35003506 }),
35013507 );
3502− const createWorktree = vi.fn((_: Parameters<VcsDriverShape["createWorktree"]>[0]) =>
3503− Effect.succeed({
3504− worktree: {
3505− branch: "t3code/bootstrap-branch",
3506− path: "/tmp/bootstrap-worktree",
3507− },
3508− }),
3508+ const createWorktree = vi.fn(
3509+ (_: Parameters<GitVcsDriver.GitVcsDriverShape["createWorktree"]>[0]) =>
3510+ Effect.succeed({
3511+ worktree: {
3512+ branch: "t3code/bootstrap-branch",
3513+ path: "/tmp/bootstrap-worktree",
3514+ },
3515+ }),
35093516 );
35103517 const runForThread = vi.fn(
35113518 (_: Parameters<ProjectSetupScriptRunnerShape["runForThread"]>[0]) =>
@@ -3520,7 +3527,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 8 unmodified lines
35203527
35213528 yield* buildAppUnderTest({
35223529 layers: {
3523− vcsDriver: {
3530+ gitVcsDriver: {
35243531 createWorktree,
35253532 },
35263533 gitStatusBroadcaster: {
@@ -3624,13 +3631,14 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 97 unmodified lines
36243631 it.effect("records setup-script failures without aborting bootstrap turn start", () =>
36253632 Effect.gen(function* () {
36263633 const dispatchedCommands: Array<OrchestrationCommand> = [];
3627− const createWorktree = vi.fn((_: Parameters<VcsDriverShape["createWorktree"]>[0]) =>
3628− Effect.succeed({
3629− worktree: {
3630− branch: "t3code/bootstrap-branch",
3631− path: "/tmp/bootstrap-worktree",
3632− },
3633− }),
3634+ const createWorktree = vi.fn(
3635+ (_: Parameters<GitVcsDriver.GitVcsDriverShape["createWorktree"]>[0]) =>
3636+ Effect.succeed({
3637+ worktree: {
3638+ branch: "t3code/bootstrap-branch",
3639+ path: "/tmp/bootstrap-worktree",
3640+ },
3641+ }),
36343642 );
36353643 const runForThread = vi.fn(
36363644 (_: Parameters<ProjectSetupScriptRunnerShape["runForThread"]>[0]) =>
@@ -3639,7 +3647,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 2 unmodified lines
36393647
36403648 yield* buildAppUnderTest({
36413649 layers: {
3642− vcsDriver: {
3650+ gitVcsDriver: {
36433651 createWorktree,
36443652 },
36453653 orchestrationEngine: {
@@ -3717,13 +3725,14 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 71 unmodified lines
37173725 it.effect("does not misattribute setup activity dispatch failures as setup launch failures", () =>
37183726 Effect.gen(function* () {
37193727 const dispatchedCommands: Array<OrchestrationCommand> = [];
3720− const createWorktree = vi.fn((_: Parameters<VcsDriverShape["createWorktree"]>[0]) =>
3721− Effect.succeed({
3722− worktree: {
3723− branch: "t3code/bootstrap-branch",
3724− path: "/tmp/bootstrap-worktree",
3725− },
3726− }),
3728+ const createWorktree = vi.fn(
3729+ (_: Parameters<GitVcsDriver.GitVcsDriverShape["createWorktree"]>[0]) =>
3730+ Effect.succeed({
3731+ worktree: {
3732+ branch: "t3code/bootstrap-branch",
3733+ path: "/tmp/bootstrap-worktree",
3734+ },
3735+ }),
37273736 );
37283737 const runForThread = vi.fn(
37293738 (_: Parameters<ProjectSetupScriptRunnerShape["runForThread"]>[0]) =>
@@ -3739,7 +3748,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 9 unmodified lines
37393748
37403749 yield* buildAppUnderTest({
37413750 layers: {
3742− vcsDriver: {
3751+ gitVcsDriver: {
37433752 createWorktree,
37443753 },
37453754 orchestrationEngine: {
@@ -3835,13 +3844,14 @@ it.layer(NodeServices.layer)("server router seam", (it) => { · 89 unmodified lines
38353844 it.effect("cleans up created bootstrap threads when worktree creation defects", () =>
38363845 Effect.gen(function* () {
38373846 const dispatchedCommands: Array<OrchestrationCommand> = [];
3838− const createWorktree = vi.fn((_: Parameters<VcsDriverShape["createWorktree"]>[0]) =>
3839− Effect.die(new Error("worktree exploded")),
3847+ const createWorktree = vi.fn(
3848+ (_: Parameters<GitVcsDriver.GitVcsDriverShape["createWorktree"]>[0]) =>
3849+ Effect.die(new Error("worktree exploded")),
38403850 );
38413851
38423852 yield* buildAppUnderTest({
38433853 layers: {
3844− vcsDriver: {
3854+ gitVcsDriver: {
38453855 createWorktree,
38463856 },
38473857 orchestrationEngine: {
apps/server/src/server.ts+2−2
@@ -136,7 +136,7 @@ const ReactorLayerLive = Layer.empty.pipe( · 135 unmodified lines
136136
137137 const CheckpointingLayerLive = Layer.empty.pipe(
138138 Layer.provideMerge(CheckpointDiffQueryLive),
139− Layer.provideMerge(CheckpointStoreLive.pipe(Layer.provide(GitVcsDriver.layer))),
139+ Layer.provideMerge(CheckpointStoreLive.pipe(Layer.provide(GitVcsDriver.vcsLayer))),
140140 );
141141
142142 const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(
@@ -173,7 +173,7 @@ const TerminalLayerLive = TerminalManagerLive.pipe(Layer.provide(PtyAdapterLive) · 30 unmodified lines
173173
174174 const WorkspaceEntriesLayerLive = WorkspaceEntriesLive.pipe(
175175 Layer.provide(WorkspacePathsLive),
176− Layer.provideMerge(GitVcsDriver.layer),
176+ Layer.provideMerge(GitVcsDriver.vcsLayer),
177177 );
178178
179179 const WorkspaceFileSystemLayerLive = WorkspaceFileSystemLive.pipe(
apps/server/src/vcs/GitVcsDriver.test.ts+3−3
@@ -18,7 +18,7 @@ const GitVcsDriverTestDependencies = ServerConfig.layerTest(process.cwd(), { · 17 unmodified lines
1818 prefix: "t3-git-vcs-driver-test-",
1919 }).pipe(Layer.provide(NodeServices.layer));
2020
21−it.layer(Layer.empty)("GitVcsDriver.layer", (it) => {
21+it.layer(Layer.empty)("GitVcsDriver.vcsLayer", (it) => {
2222 describe("workspace helpers", () => {
2323 it.effect("filterIgnoredPaths chunks large path lists and preserves kept paths", () =>
2424 Effect.gen(function* () {
@@ -32,7 +32,7 @@ it.layer(Layer.empty)("GitVcsDriver.layer", (it) => { · 7 unmodified lines
3232 );
3333
3434 const seenChunks: string[][] = [];
35− const layer = GitVcsDriver.layer.pipe(
35+ const layer = GitVcsDriver.vcsLayer.pipe(
3636 Layer.provideMerge(GitVcsDriverTestDependencies),
3737 Layer.provideMerge(NodeServices.layer),
3838 Layer.provide(
@@ -81,7 +81,7 @@ it.layer(Layer.empty)("GitVcsDriver.layer", (it) => { · 42 unmodified lines
8181
8282 it.effect("listWorkspaceFiles disables fsmonitor and untracked cache helpers", () =>
8383 Effect.gen(function* () {
84− const layer = GitVcsDriver.layer.pipe(
84+ const layer = GitVcsDriver.vcsLayer.pipe(
8585 Layer.provideMerge(GitVcsDriverTestDependencies),
8686 Layer.provideMerge(NodeServices.layer),
8787 Layer.provide(
apps/server/src/vcs/GitVcsDriver.ts+16−5
@@ -1,10 +1,17 @@
1−import { DateTime, Effect, Layer } from "effect";
1+import { Context, DateTime, Effect, Layer } from "effect";
22
33 import { VcsProcessExitError } from "@t3tools/contracts";
44 import { makeGitCore } from "../git/Layers/GitCore.ts";
5+import type { GitCoreShape } from "../git/Services/GitCore.ts";
56 import { VcsDriver, type VcsDriverShape } from "./VcsDriver.ts";
67 import { VcsProcess, type VcsProcessShape } from "./VcsProcess.ts";
78
9+export interface GitVcsDriverShape extends GitCoreShape {}
10+
11+export class GitVcsDriver extends Context.Service<GitVcsDriver, GitVcsDriverShape>()(
12+ "t3/vcs/GitVcsDriver",
13+) {}
14+
815 const WORKSPACE_FILES_MAX_OUTPUT_BYTES = 16 * 1024 * 1024;
916 const GIT_CHECK_IGNORE_MAX_STDIN_BYTES = 256 * 1024;
1017 const WORKSPACE_GIT_HARDENED_CONFIG_ARGS = [
@@ -92,9 +99,8 @@ const gitCommand = ( · 81 unmodified lines
9299 : {}),
93100 });
94101
95−export const make = Effect.fn("makeGitVcsDriver")(function* () {
102+export const makeVcsDriver = Effect.fn("makeGitVcsDriver")(function* () {
96103 const process = yield* VcsProcess;
97− const legacyGit = yield* makeGitCore();
98104 const capabilities = {
99105 kind: "git" as const,
100106 supportsWorktrees: true,
@@ -243,7 +249,6 @@ export const make = Effect.fn("makeGitVcsDriver")(function* () { · 142 unmodified lines
243249 );
244250
245251 return VcsDriver.of({
246− ...legacyGit,
247252 capabilities,
248253 execute,
249254 detectRepository,
@@ -253,4 +258,10 @@ export const make = Effect.fn("makeGitVcsDriver")(function* () { · 3 unmodified lines
253258 });
254259 });
255260
256−export const layer = Layer.effect(VcsDriver, make());
261+export const make = Effect.fn("makeGitVcsDriverService")(function* () {
262+ const legacyGit = yield* makeGitCore();
263+ return GitVcsDriver.of(legacyGit);
264+});
265+
266+export const vcsLayer = Layer.effect(VcsDriver, makeVcsDriver());
267+export const layer = Layer.effect(GitVcsDriver, make());
apps/server/src/vcs/VcsDriver.ts+1−2
@@ -6,10 +6,9 @@ import type { · 5 unmodified lines
66 VcsListWorkspaceFilesResult,
77 VcsRepositoryIdentity,
88 } from "@t3tools/contracts";
9−import type { GitCoreShape } from "../git/Services/GitCore.ts";
109 import type { VcsProcessInput, VcsProcessOutput } from "./VcsProcess.ts";
1110
12−export interface VcsDriverShape extends Omit<GitCoreShape, "execute"> {
11+export interface VcsDriverShape {
1312 readonly capabilities: VcsDriverCapabilities;
1413 readonly execute: (
1514 input: Omit<VcsProcessInput, "command">,
apps/server/src/workspace/Layers/WorkspaceEntries.test.ts+1−1
@@ -15,7 +15,7 @@ const TestLayer = Layer.empty.pipe( · 14 unmodified lines
1515 Layer.provideMerge(WorkspaceEntriesLive.pipe(Layer.provide(WorkspacePathsLive))),
1616 Layer.provideMerge(WorkspacePathsLive),
1717 Layer.provideMerge(VcsProcess.layer),
18− Layer.provideMerge(GitVcsDriver.layer.pipe(Layer.provide(VcsProcess.layer))),
18+ Layer.provideMerge(GitVcsDriver.vcsLayer.pipe(Layer.provide(VcsProcess.layer))),
1919 Layer.provide(
2020 ServerConfig.layerTest(process.cwd(), {
2121 prefix: "t3-workspace-entries-test-",
apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts+1−1
@@ -20,7 +20,7 @@ const TestLayer = Layer.empty.pipe( · 19 unmodified lines
2020 Layer.provideMerge(ProjectLayer),
2121 Layer.provideMerge(WorkspaceEntriesLive.pipe(Layer.provide(WorkspacePathsLive))),
2222 Layer.provideMerge(WorkspacePathsLive),
23− Layer.provideMerge(GitVcsDriver.layer.pipe(Layer.provide(VcsProcess.layer))),
23+ Layer.provideMerge(GitVcsDriver.vcsLayer.pipe(Layer.provide(VcsProcess.layer))),
2424 Layer.provide(
2525 ServerConfig.layerTest(process.cwd(), {
2626 prefix: "t3-workspace-files-test-",
apps/server/src/ws.ts+2−2
@@ -49,7 +49,7 @@ import { TerminalManager } from "./terminal/Services/Manager.ts"; · 48 unmodified lines
4949 import { WorkspaceEntries } from "./workspace/Services/WorkspaceEntries.ts";
5050 import { WorkspaceFileSystem } from "./workspace/Services/WorkspaceFileSystem.ts";
5151 import { WorkspacePathOutsideRootError } from "./workspace/Services/WorkspacePaths.ts";
52−import { VcsDriver } from "./vcs/VcsDriver.ts";
52+import { GitVcsDriver } from "./vcs/GitVcsDriver.ts";
5353 import { ProjectSetupScriptRunner } from "./project/Services/ProjectSetupScriptRunner.ts";
5454 import { RepositoryIdentityResolver } from "./project/Services/RepositoryIdentityResolver.ts";
5555 import { ServerEnvironment } from "./environment/Services/ServerEnvironment.ts";
@@ -137,7 +137,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => · 81 unmodified lines
137137 const keybindings = yield* Keybindings;
138138 const open = yield* Open;
139139 const gitManager = yield* GitManager;
140− const git = yield* VcsDriver;
140+ const git = yield* GitVcsDriver;
141141 const gitStatusBroadcaster = yield* GitStatusBroadcaster;
142142 const terminalManager = yield* TerminalManager;
143143 const providerRegistry = yield* ProviderRegistry;