import * as NodeServices from "@effect/platform-node/NodeServices"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Path from "effect/Path"; import * as PlatformError from "effect/PlatformError"; import { ChildProcessSpawner } from "effect/unstable/process"; import { assert, it } from "@effect/vitest"; import { GitCommandError } from "@t3tools/contracts"; import * as ServerConfig from "../config.ts"; import * as GitVcsDriver from "./GitVcsDriver.ts"; import * as VcsProcess from "./VcsProcess.ts"; import { runVcsDriverContractSuite } from "./testing/VcsDriverContractHarness.ts"; const ServerConfigLayer = ServerConfig.layerTest(process.cwd(), { prefix: "t3-git-vcs-contract-", }); const GitContractLayer = Layer.mergeAll(GitVcsDriver.vcsLayer, GitVcsDriver.layer).pipe( Layer.provide(ServerConfigLayer), Layer.provideMerge(VcsProcess.layer), Layer.provideMerge(NodeServices.layer), ); const runGit = (cwd: string, args: ReadonlyArray) => Effect.gen(function* () { const driver = yield* GitVcsDriver.GitVcsDriver; yield* driver.execute({ operation: "GitVcsDriver.contract.git", cwd, args, timeoutMs: 10_000, }); }); type GitContractError = GitCommandError | PlatformError.PlatformError; runVcsDriverContractSuite({ name: "Git", kind: "git", layer: GitContractLayer, fixture: { createRepo: (cwd) => Effect.gen(function* () { yield* runGit(cwd, ["init"]); yield* runGit(cwd, ["config", "user.email", "test@test.com"]); yield* runGit(cwd, ["config", "user.name", "Test"]); }), writeFile: (cwd, relativePath, contents) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const absolutePath = path.join(cwd, relativePath); yield* fileSystem.makeDirectory(path.dirname(absolutePath), { recursive: true }); yield* fileSystem.writeFileString(absolutePath, contents); }), trackFile: (cwd, relativePath) => runGit(cwd, ["add", relativePath]), commit: (cwd, message) => runGit(cwd, ["commit", "-m", message]), ignorePath: (cwd, pattern) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; yield* fileSystem.writeFileString(path.join(cwd, ".gitignore"), `${pattern}\n`); }), }, }); it.effect("GitVcsDriver forwards execute env to the VCS process", () => { let observedEnv: NodeJS.ProcessEnv | undefined; let observedAppendTruncationMarker: boolean | undefined; let observedOutputMode: VcsProcess.VcsProcessInput["outputMode"]; return Effect.gen(function* () { const driver = yield* GitVcsDriver.makeVcsDriverShape(); yield* driver.execute({ operation: "GitVcsDriver.test.env", cwd: "/repo", args: ["status"], env: { GIT_INDEX_FILE: "/tmp/t3-index", }, appendTruncationMarker: true, outputMode: "error", }); assert.deepStrictEqual(observedEnv, { GIT_INDEX_FILE: "/tmp/t3-index", }); assert.strictEqual(observedAppendTruncationMarker, true); assert.strictEqual(observedOutputMode, "error"); }).pipe( Effect.provide( Layer.mergeAll( NodeServices.layer, Layer.mock(VcsProcess.VcsProcess)({ run: (input) => Effect.sync(() => { observedEnv = input.env; observedAppendTruncationMarker = input.appendTruncationMarker; observedOutputMode = input.outputMode; return { exitCode: ChildProcessSpawner.ExitCode(0), stdout: "", stderr: "", stdoutTruncated: false, stderrTruncated: false, }; }), }), ), ), ); });