From 966702b0fade3a3507b6e543f041d079badcf1a2 Mon Sep 17 00:00:00 2001 From: zinefer Date: Sat, 26 Jul 2025 23:17:29 -0600 Subject: [PATCH 1/5] Bugfix: Resolve ancestral symlinks --- src/testTree.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/testTree.ts b/src/testTree.ts index c03147b0..2ca992fc 100644 --- a/src/testTree.ts +++ b/src/testTree.ts @@ -1,6 +1,6 @@ import type { RunnerTask, RunnerTestFile } from 'vitest' import type { VitestFolderAPI } from './api' -import { lstatSync, readlinkSync } from 'node:fs' +import { lstatSync, readlinkSync, realpathSync } from 'node:fs' import { resolve } from 'node:path' import { basename, dirname, normalize } from 'pathe' import * as vscode from 'vscode' @@ -83,14 +83,12 @@ export class TestTree extends vscode.Disposable { } getSymlinkFolder(uri: vscode.Uri) { - const stats = lstatSync(uri.fsPath) - if (stats.isSymbolicLink()) { - const actualPath = readlinkSync(uri.fsPath) - const dir = dirname(uri.fsPath) - const id = resolve(dir, actualPath) - return vscode.Uri.file(id) + const realPath = realpathSync(uri.fsPath); + if (realPath === uri.fsPath) { + return uri } - return uri + + return vscode.Uri.file(realPath); } // in cases where there is only a single workspace, we don't show it as a folder @@ -191,8 +189,16 @@ export class TestTree extends vscode.Disposable { return cached } + const parent = dirname(normalizedFolder); + // If the parent is the same as the folder, we are at the root + if (dirname(normalizedFolder) === normalizedFolder) { + log.workspaceError(`Attempted to get parent for root folder: ${normalizedFolder}. Fatal error, preventing infinite loop.\nDo you have a symlink in your workspace?`); + // this should never happen, but if it does, we just return the loader item to recover + return this.loaderItem; + } + const folderUri = vscode.Uri.file(normalizedFolder) - const parentItem = this.getOrCreateFolderTestItem(api, dirname(normalizedFolder)) + const parentItem = this.getOrCreateFolderTestItem(api, parent) const folderItem = this._createFolderItem(folderUri, parentItem) folderItem.tags = [api.tag] parentItem.children.add(folderItem) From d321710fac68f89a1707b41dca63adff2e9cfe00 Mon Sep 17 00:00:00 2001 From: zinefer Date: Sat, 26 Jul 2025 23:41:23 -0600 Subject: [PATCH 2/5] Improve error message --- src/testTree.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/testTree.ts b/src/testTree.ts index 2ca992fc..896fdf5a 100644 --- a/src/testTree.ts +++ b/src/testTree.ts @@ -192,8 +192,9 @@ export class TestTree extends vscode.Disposable { const parent = dirname(normalizedFolder); // If the parent is the same as the folder, we are at the root if (dirname(normalizedFolder) === normalizedFolder) { - log.workspaceError(`Attempted to get parent for root folder: ${normalizedFolder}. Fatal error, preventing infinite loop.\nDo you have a symlink in your workspace?`); - // this should never happen, but if it does, we just return the loader item to recover + log.workspaceError( + `Fatal error: Attempted to get parent for root folder. Aborting to prevent infinite loop.` + ); return this.loaderItem; } From d33c4f1a6f8ca3a21c328c257cb653b540220fca Mon Sep 17 00:00:00 2001 From: zinefer Date: Sat, 26 Jul 2025 23:52:51 -0600 Subject: [PATCH 3/5] Stylefix --- src/testTree.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/testTree.ts b/src/testTree.ts index 896fdf5a..6bf913c6 100644 --- a/src/testTree.ts +++ b/src/testTree.ts @@ -1,6 +1,6 @@ import type { RunnerTask, RunnerTestFile } from 'vitest' import type { VitestFolderAPI } from './api' -import { lstatSync, readlinkSync, realpathSync } from 'node:fs' +import { realpathSync } from 'node:fs' import { resolve } from 'node:path' import { basename, dirname, normalize } from 'pathe' import * as vscode from 'vscode' @@ -83,12 +83,12 @@ export class TestTree extends vscode.Disposable { } getSymlinkFolder(uri: vscode.Uri) { - const realPath = realpathSync(uri.fsPath); + const realPath = realpathSync(uri.fsPath) if (realPath === uri.fsPath) { return uri } - return vscode.Uri.file(realPath); + return vscode.Uri.file(realPath) } // in cases where there is only a single workspace, we don't show it as a folder @@ -189,13 +189,13 @@ export class TestTree extends vscode.Disposable { return cached } - const parent = dirname(normalizedFolder); + const parent = dirname(normalizedFolder) // If the parent is the same as the folder, we are at the root if (dirname(normalizedFolder) === normalizedFolder) { log.workspaceError( - `Fatal error: Attempted to get parent for root folder. Aborting to prevent infinite loop.` - ); - return this.loaderItem; + `Fatal error: Attempted to get parent for root folder. Aborting to prevent infinite loop.`, + ) + return this.loaderItem } const folderUri = vscode.Uri.file(normalizedFolder) From 7180b2bb6214c37c31dd6da340740c7d1348ef5b Mon Sep 17 00:00:00 2001 From: zinefer Date: Sat, 26 Jul 2025 23:56:46 -0600 Subject: [PATCH 4/5] Reuse parent --- src/testTree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testTree.ts b/src/testTree.ts index 6bf913c6..49ceb7c2 100644 --- a/src/testTree.ts +++ b/src/testTree.ts @@ -191,7 +191,7 @@ export class TestTree extends vscode.Disposable { const parent = dirname(normalizedFolder) // If the parent is the same as the folder, we are at the root - if (dirname(normalizedFolder) === normalizedFolder) { + if (parent === normalizedFolder) { log.workspaceError( `Fatal error: Attempted to get parent for root folder. Aborting to prevent infinite loop.`, ) From 04ece93094089be3bad2a1230661502844924ad3 Mon Sep 17 00:00:00 2001 From: zinefer Date: Tue, 29 Jul 2025 12:55:19 -0600 Subject: [PATCH 5/5] Improve error handling --- src/testTree.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/testTree.ts b/src/testTree.ts index 49ceb7c2..e8f0accb 100644 --- a/src/testTree.ts +++ b/src/testTree.ts @@ -192,10 +192,7 @@ export class TestTree extends vscode.Disposable { const parent = dirname(normalizedFolder) // If the parent is the same as the folder, we are at the root if (parent === normalizedFolder) { - log.workspaceError( - `Fatal error: Attempted to get parent for root folder. Aborting to prevent infinite loop.`, - ) - return this.loaderItem + throw new Error(`Fatal Error: Attempted to get parent of root folder "${normalizedFolder}".`) } const folderUri = vscode.Uri.file(normalizedFolder)