| ... | @@ -11,6 +11,7 @@ import * as Layer from "effect/Layer"; | ... | @@ -11,6 +11,7 @@ import * as Layer from "effect/Layer"; |
| 11 | import * as Path from "effect/Path"; | 11 | import * as Path from "effect/Path"; |
| 12 | import * as PlatformError from "effect/PlatformError"; | 12 | import * as PlatformError from "effect/PlatformError"; |
| 13 | import * as Ref from "effect/Ref"; | 13 | import * as Ref from "effect/Ref"; |
| | 14 | import * as Result from "effect/Result"; |
| 14 | import * as Scope from "effect/Scope"; | 15 | import * as Scope from "effect/Scope"; |
| 15 | import * as Sink from "effect/Sink"; | 16 | import * as Sink from "effect/Sink"; |
| 16 | import * as Stream from "effect/Stream"; | 17 | import * as Stream from "effect/Stream"; |
| ... | @@ -131,6 +132,51 @@ const initRepoWithCommit = ( | ... | @@ -131,6 +132,51 @@ const initRepoWithCommit = ( |
| 131 | return { initialBranch }; | 132 | return { initialBranch }; |
| 132 | }); | 133 | }); |
| 133 | | 134 | |
| | 135 | for (const location of ["root", "nested", "worktree"] as const) { |
| | 136 | it.effect( |
| | 137 | `skips clean filters while the ${location} index is locked and resumes after unlock`, |
| | 138 | () => |
| | 139 | Effect.gen(function* () { |
| | 140 | const driver = yield* GitVcsDriver.GitVcsDriver; |
| | 141 | const fs = yield* FileSystem.FileSystem; |
| | 142 | const path = yield* Path.Path; |
| | 143 | const repository = yield* makeTmpDir(); |
| | 144 | yield* initRepoWithCommit(repository); |
| | 145 | const cwd = location === "worktree" ? yield* makeTmpDir() : repository; |
| | 146 | if (location === "worktree") { |
| | 147 | yield* git(repository, ["worktree", "add", "--detach", cwd]); |
| | 148 | } |
| | 149 | yield* git(cwd, ["config", "filter.probe.clean", "echo clean >> .filter-runs; cat"]); |
| | 150 | yield* writeTextFile(cwd, ".gitattributes", "asset.bin filter=probe\n"); |
| | 151 | yield* writeTextFile(cwd, ".gitignore", ".filter-runs\n"); |
| | 152 | yield* writeTextFile(cwd, "asset.bin", "original\n"); |
| | 153 | yield* git(cwd, ["add", "."]); |
| | 154 | yield* git(cwd, ["commit", "-m", "filtered asset"]); |
| | 155 | NodeFS.utimesSync(path.join(cwd, "asset.bin"), 1, 1); |
| | 156 | const runsPath = path.join(cwd, ".filter-runs"); |
| | 157 | yield* fs.remove(runsPath, { force: true }); |
| | 158 | const indexPath = yield* git(cwd, ["rev-parse", "--git-path", "index"]); |
| | 159 | const lockPath = `${path.resolve(cwd, indexPath)}.lock`; |
| | 160 | yield* fs.writeFileString(lockPath, ""); |
| | 161 | const statusCwd = location === "nested" ? path.join(cwd, "nested") : cwd; |
| | 162 | yield* fs.makeDirectory(statusCwd, { recursive: true }); |
| | 163 | |
| | 164 | for (let poll = 0; poll < 3; poll++) { |
| | 165 | const result = yield* driver.statusDetailsLocal(statusCwd).pipe(Effect.result); |
| | 166 | assert.isTrue(Result.isFailure(result)); |
| | 167 | if (Result.isFailure(result)) assert.include(result.failure.detail, "index is locked"); |
| | 168 | } |
| | 169 | assert.isFalse(yield* fs.exists(runsPath)); |
| | 170 | assert.isTrue(yield* fs.exists(lockPath)); |
| | 171 | |
| | 172 | yield* fs.remove(lockPath); |
| | 173 | const status = yield* driver.statusDetailsLocal(statusCwd); |
| | 174 | assert.isFalse(status.hasWorkingTreeChanges); |
| | 175 | assert.include(yield* fs.readFileString(runsPath), "clean"); |
| | 176 | }).pipe(Effect.provide(TestLayer)), |
| | 177 | ); |
| | 178 | } |
| | 179 | |
| 134 | it.effect("uses stable diagnostics for every parsed non-repository command", () => { | 180 | it.effect("uses stable diagnostics for every parsed non-repository command", () => { |
| 135 | const commands: Array<{ readonly args: ReadonlyArray<string>; readonly lcAll?: string }> = []; | 181 | const commands: Array<{ readonly args: ReadonlyArray<string>; readonly lcAll?: string }> = []; |
| 136 | const spawner = ChildProcessSpawner.make((command) => | 182 | const spawner = ChildProcessSpawner.make((command) => |
| ... | @@ -163,6 +209,7 @@ it.effect("uses stable diagnostics for every parsed non-repository command", () | ... | @@ -163,6 +209,7 @@ it.effect("uses stable diagnostics for every parsed non-repository command", () |
| 163 | yield* driver.listRefs({ cwd }); | 209 | yield* driver.listRefs({ cwd }); |
| 164 | | 210 | |
| 165 | assert.deepStrictEqual(commands, [ | 211 | assert.deepStrictEqual(commands, [ |
| | 212 | { args: ["rev-parse", "--git-path", "index"], lcAll: "C" }, |
| 166 | { args: ["status", "--porcelain=2", "--branch"], lcAll: "C" }, | 213 | { args: ["status", "--porcelain=2", "--branch"], lcAll: "C" }, |
| 167 | { args: ["rev-parse", "--abbrev-ref", "HEAD"], lcAll: "C" }, | 214 | { args: ["rev-parse", "--abbrev-ref", "HEAD"], lcAll: "C" }, |
| 168 | { args: ["rev-parse", "--git-common-dir"], lcAll: "C" }, | 215 | { args: ["rev-parse", "--git-common-dir"], lcAll: "C" }, |