diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cc5f8ea7..a08760ea8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Silenced a false-positive `MaxListenersExceededWarning` logged on every request proxied through an external rewrite. [#1697](https://github.com/sourcebot-dev/sourcebot/pull/1697) - Upgraded `next` to `^16.3.8`. [#1709](https://github.com/sourcebot-dev/sourcebot/pull/1709) +- Fixed implicit directories in the file tree carrying the leaf file's path, which broke folder expansion and the `/api/git/tree` payload. [#1712](https://github.com/sourcebot-dev/sourcebot/pull/1712) ## [5.1.15] - 2026-09-29 diff --git a/packages/web/src/features/git/utils.test.ts b/packages/web/src/features/git/utils.test.ts index e4aa5f8e2..e52d93f3b 100644 --- a/packages/web/src/features/git/utils.test.ts +++ b/packages/web/src/features/git/utils.test.ts @@ -103,3 +103,20 @@ test('buildFileTree builds a sorted tree from a flat list', () => { }); }); +test('buildFileTree gives implicit directories their own path, not the leaf file path', () => { + const flatList: { type: string, path: string }[] = [ + { type: 'blob', path: 'src/components/buttons/PrimaryButton.tsx' }, + ]; + + const tree = buildFileTree(flatList); + + const src = tree.children[0]; + const components = src.children[0]; + const buttons = components.children[0]; + + expect(src.path).toBe('src'); + expect(components.path).toBe('src/components'); + expect(buttons.path).toBe('src/components/buttons'); + expect(buttons.children[0].path).toBe('src/components/buttons/PrimaryButton.tsx'); +}); + diff --git a/packages/web/src/features/git/utils.ts b/packages/web/src/features/git/utils.ts index f9b1a71e7..4f12f1fb6 100644 --- a/packages/web/src/features/git/utils.ts +++ b/packages/web/src/features/git/utils.ts @@ -67,7 +67,11 @@ export const buildFileTree = (flatList: { type: string, path: string }[]): FileT if (!next) { next = { name: part, - path: item.path, + // A node's path is its own location, not the leaf's: an + // implicit directory (`src` for `src/main.ts`) used to get + // the file's path, which broke folder expansion, route + // sync and the /api/git/tree payload. + path: parts.slice(0, i + 1).join('/'), type: nodeType, children: [], };