authorgravatar for 71498452+StiensWout@users.noreply.github.comWout Stiens <71498452+StiensWout@users.noreply.github.com> 2026-07-29 17:48:57+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-07-29 11:48:57-04:00
logd19039aeef6942e6eb204856c43b5354c0333e2d
treed63996ac50b965b241cf88fe60de4390515fb8d3
parent49c0d96edf280f1fe6750a83161a3a2cff0f25ef
signature Signed by PGP key B5690EEEBB952194

fix(server): detect repositories after initialization (#4848)


2 files changed, 49 insertions(+), 1 deletions(-)

apps/server/src/vcs/VcsDriverRegistry.test.ts+45
...@@ -92,4 +92,49 @@ describe("VcsDriverRegistry", () => {...@@ -92,4 +92,49 @@ describe("VcsDriverRegistry", () => {
92 );92 );
93 }).pipe(Effect.provide(layer));93 }).pipe(Effect.provide(layer));
94 });94 });
95
96 it.effect("detects a repository created after a negative lookup", () => {
97 let insideWorkTreeChecks = 0;
98 const layer = Layer.effect(VcsDriverRegistry.VcsDriverRegistry, VcsDriverRegistry.make).pipe(
99 Layer.provide(NodeServices.layer),
100 Layer.provide(
101 Layer.mock(VcsProjectConfig.VcsProjectConfig)({
102 resolveKind: (input) => Effect.succeed(input.requestedKind ?? "auto"),
103 }),
104 ),
105 Layer.provide(
106 Layer.mock(VcsProcess.VcsProcess)({
107 run: (input) =>
108 Effect.sync(() => {
109 const command = normalizeGitArgs(input.args).join(" ");
110 if (command === "rev-parse --is-inside-work-tree") {
111 insideWorkTreeChecks += 1;
112 return insideWorkTreeChecks === 1
113 ? {
114 ...processOutput(""),
115 exitCode: ChildProcessSpawner.ExitCode(128),
116 stderr: "fatal: not a git repository",
117 }
118 : processOutput("true\n");
119 }
120 if (command === "rev-parse --show-toplevel") {
121 return processOutput("/repo\n");
122 }
123 if (command === "rev-parse --git-common-dir") {
124 return processOutput("/repo/.git\n");
125 }
126 return processOutput("");
127 }),
128 }),
129 ),
130 );
131
132 return Effect.gen(function* () {
133 const registry = yield* VcsDriverRegistry.VcsDriverRegistry;
134
135 assert.equal(yield* registry.detect({ cwd: "/repo" }), null);
136 assert.equal((yield* registry.detect({ cwd: "/repo" }))?.repository.rootPath, "/repo");
137 assert.equal(insideWorkTreeChecks, 2);
138 }).pipe(Effect.provide(layer));
139 });
95});140});
apps/server/src/vcs/VcsDriverRegistry.ts+4-1
...@@ -115,7 +115,10 @@ export const make = Effect.gen(function* () {...@@ -115,7 +115,10 @@ export const make = Effect.gen(function* () {
115 (key) => detectResolvedKind(parseDetectionCacheKey(key)),115 (key) => detectResolvedKind(parseDetectionCacheKey(key)),
116 {116 {
117 capacity: DETECTION_CACHE_CAPACITY,117 capacity: DETECTION_CACHE_CAPACITY,
118 timeToLive: (exit) => (Exit.isSuccess(exit) ? DETECTION_CACHE_TTL : Duration.zero),118 timeToLive: Exit.match({
119 onSuccess: (detected) => (detected === null ? Duration.zero : DETECTION_CACHE_TTL),
120 onFailure: () => Duration.zero,
121 }),
119 },122 },
120 );123 );
121124