mirror of https://github.com/garrytan/gstack.git
fix(gbrain-sync): sourceLocalPath handles wrapped {sources:[...]} shape from gbrain v0.20+
gbrain v0.20+ changed `gbrain sources list --json` to return
{sources: [...]} instead of a flat array. sourceLocalPath crashed
upstream with `list.find is not a function` on every /sync-gbrain
invocation against modern gbrain. Accept both shapes for
forward/backward compat, matching probeSource/sourcePageCount in
lib/gbrain-sources.ts.
Contributed by @jakehann11 via #1571. Closes #1567. Supersedes #1564
(@tonyjzhou, same fix, different shape — credit retained).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0c7ef235ed
commit
59a9b841af
|
|
@ -287,13 +287,20 @@ function gbrainSupportsSourcesRename(env?: NodeJS.ProcessEnv): boolean {
|
|||
* `env` is the environment passed to the spawned `gbrain` process; defaults
|
||||
* to `process.env`. Tests inject a PATH that points at a gbrain shim so the
|
||||
* helper can be exercised without a real gbrain CLI.
|
||||
*
|
||||
* Shape note: `gbrain sources list --json` returns `{sources: [...]}` (v0.20+);
|
||||
* older versions returned a flat array. Accept both for forward/backward compat
|
||||
* (mirrors `probeSource`/`sourcePageCount` in lib/gbrain-sources.ts).
|
||||
*/
|
||||
export function sourceLocalPath(sourceId: string, env?: NodeJS.ProcessEnv): string | null {
|
||||
const list = execGbrainJson<Array<{ id: string; local_path?: string }>>(
|
||||
const raw = execGbrainJson<unknown>(
|
||||
["sources", "list", "--json"],
|
||||
{ baseEnv: env },
|
||||
);
|
||||
if (!list) return null;
|
||||
if (!raw) return null;
|
||||
const list: Array<{ id?: string; local_path?: string }> = Array.isArray(raw)
|
||||
? (raw as Array<{ id?: string; local_path?: string }>)
|
||||
: ((raw as { sources?: Array<{ id?: string; local_path?: string }> }).sources ?? []);
|
||||
const found = list.find((s) => s.id === sourceId);
|
||||
return found?.local_path ?? null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -837,4 +837,29 @@ describe("sourceLocalPath", () => {
|
|||
});
|
||||
expect(sourceLocalPath("any-id", envWithBindir(bindir))).toBeNull();
|
||||
});
|
||||
|
||||
// gbrain v0.20+ wraps the response as `{sources: [...]}`. Older versions
|
||||
// returned a flat array. sourceLocalPath was returning null (or crashing
|
||||
// with `list.find is not a function` upstream) because it only handled
|
||||
// the flat-array shape. Pin both shapes here.
|
||||
it("handles {sources: [...]} wrapped shape (gbrain v0.20+)", () => {
|
||||
makeShim(bindir, {
|
||||
"sources list --json": {
|
||||
stdout: JSON.stringify({
|
||||
sources: [
|
||||
{ id: "other-source", local_path: "/x" },
|
||||
{ id: "target-id", local_path: "/repo/match" },
|
||||
],
|
||||
}),
|
||||
},
|
||||
});
|
||||
expect(sourceLocalPath("target-id", envWithBindir(bindir))).toBe("/repo/match");
|
||||
});
|
||||
|
||||
it("returns null when the source is missing in the wrapped shape", () => {
|
||||
makeShim(bindir, {
|
||||
"sources list --json": { stdout: JSON.stringify({ sources: [] }) },
|
||||
});
|
||||
expect(sourceLocalPath("missing-id", envWithBindir(bindir))).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue