History

fix(mcp): close project operation races

Julius Marminge committed 2 months ago

Commit e3f2cda1 parent 93b21576 files · +257 −29Browse files

Showing the changes to apps/server/src/sourceControl/SourceControlRepositoryService.test.ts (1 of 6 files). Show all

Unified · Split

apps/server/src/sourceControl/SourceControlRepositoryService.test.ts+65−0
@@ -365,10 +365,75 @@ it.effect("recovers a real completed clone after a lost result and rejects unsaf · 364 unmodified lines
365365
366366 yield* initializeRepository(sourcePath, "source");
367367 yield* initializeRepository(otherSourcePath, "other source");
368+ yield* fs.writeFileString(`${sourcePath}/CHANGELOG.md`, "second source commit");
369+ yield* git.execute({ operation: "test.add.second", cwd: sourcePath, args: ["add", "."] });
370+ yield* git.execute({
371+ operation: "test.commit.second",
372+ cwd: sourcePath,
373+ args: ["commit", "-m", "second"],
374+ });
368375
369376 const cloned = yield* service.cloneRepository({ remoteUrl: sourcePath, destinationPath });
370377 assert.strictEqual(cloned.cwd, destinationPath);
371378
379+ const headCommit = (yield* git.execute({
380+ operation: "test.read.head",
381+ cwd: destinationPath,
382+ args: ["rev-parse", "HEAD"],
383+ })).stdout.trim();
384+ const previousCommit = (yield* git.execute({
385+ operation: "test.read.previous",
386+ cwd: destinationPath,
387+ args: ["rev-parse", "HEAD^"],
388+ })).stdout.trim();
389+ yield* git
390+ .execute({
391+ operation: "test.remove.remote.head",
392+ cwd: destinationPath,
393+ args: ["symbolic-ref", "-d", "refs/remotes/origin/HEAD"],
394+ })
395+ .pipe(Effect.ignore);
396+ const existingRemoteRefs = (yield* git.execute({
397+ operation: "test.list.remote.refs",
398+ cwd: destinationPath,
399+ args: ["for-each-ref", "--format=%(refname)", "refs/remotes/origin"],
400+ })).stdout
401+ .split("\n")
402+ .map((line) => line.trim())
403+ .filter((line) => line.length > 0);
404+ yield* Effect.forEach(
405+ existingRemoteRefs,
406+ (refName) =>
407+ git.execute({
408+ operation: "test.remove.remote.ref",
409+ cwd: destinationPath,
410+ args: ["update-ref", "-d", refName],
411+ }),
412+ { discard: true },
413+ );
414+ const noiseRefCommands = Array.from(
415+ { length: 1_700 },
416+ (_, index) =>
417+ `create refs/remotes/origin/noise-${index.toString().padStart(4, "0")} ${previousCommit}`,
418+ );
419+ yield* git.execute({
420+ operation: "test.create.many.remote.refs",
421+ cwd: destinationPath,
422+ args: ["update-ref", "--stdin"],
423+ stdin: [...noiseRefCommands, `create refs/remotes/origin/zzzz-match ${headCommit}`, ""].join(
424+ "\n",
425+ ),
426+ });
427+ const oversizedInventory = yield* git
428+ .execute({
429+ operation: "test.verify.old.remote-ref-boundary",
430+ cwd: destinationPath,
431+ args: ["for-each-ref", "--format=%(objectname)", "refs/remotes/origin"],
432+ maxOutputBytes: 64 * 1024,
433+ })
434+ .pipe(Effect.flip);
435+ assert.instanceOf(oversizedInventory, GitCommandError);
436+
372437 // Simulate the caller losing the successful clone result before project registration.
373438 const recovered = yield* service.cloneRepository({ remoteUrl: sourcePath, destinationPath });
374439 assert.strictEqual(recovered.cwd, destinationPath);