fix: replace Unix path assumptions with cross-platform isAbsolutePath
Windows daemon paths like C:\Users\... don't start with "/", breaking the explorer sidebar, checkout status, terminals, and file attachments when connected to a Windows daemon. Consolidate three private isAbsolutePath implementations into a shared utility and use it everywhere, with correct file URI conversion for Windows and UNC paths.
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
import { isAbsolutePath } from "./path";
|
||||
|
||||
interface BuildAbsoluteExplorerPathInput {
|
||||
workspaceRoot: string;
|
||||
entryPath: string;
|
||||
}
|
||||
|
||||
function isAbsolutePath(pathValue: string): boolean {
|
||||
return (
|
||||
pathValue.startsWith("/") || pathValue.startsWith("\\\\") || /^[A-Za-z]:[\\/]/.test(pathValue)
|
||||
);
|
||||
}
|
||||
|
||||
export function buildAbsoluteExplorerPath({
|
||||
workspaceRoot,
|
||||
entryPath,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { isAbsolutePath } from "./path";
|
||||
|
||||
export interface InlinePathTarget {
|
||||
raw: string;
|
||||
path: string;
|
||||
@@ -183,7 +185,7 @@ export function parseAssistantFileLink(
|
||||
};
|
||||
}
|
||||
|
||||
if (!trimmed.startsWith("/")) {
|
||||
if (!isAbsolutePath(trimmed)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -195,7 +197,7 @@ export function parseAssistantFileLink(
|
||||
}
|
||||
|
||||
const normalizedPath = normalizePathToken(decodeURIComponent(parsedUrl.pathname));
|
||||
if (!normalizedPath || !normalizedPath.startsWith("/")) {
|
||||
if (!normalizedPath || !isAbsolutePath(normalizedPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -334,7 +336,3 @@ function resolvePathAgainstCwd(pathValue: string, cwd?: string): string | null {
|
||||
function normalizePathForCompare(value: string): string {
|
||||
return /^[A-Za-z]:/.test(value) ? value.toLowerCase() : value;
|
||||
}
|
||||
|
||||
function isAbsolutePath(value: string): boolean {
|
||||
return value.startsWith("/") || /^[A-Za-z]:\//.test(value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isAbsolutePath } from "./path";
|
||||
|
||||
describe("isAbsolutePath", () => {
|
||||
it("returns true for Unix absolute paths", () => {
|
||||
expect(isAbsolutePath("/")).toBe(true);
|
||||
expect(isAbsolutePath("/home/user")).toBe(true);
|
||||
expect(isAbsolutePath("/tmp/file.txt")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true for Windows drive letter paths", () => {
|
||||
expect(isAbsolutePath("C:\\Users")).toBe(true);
|
||||
expect(isAbsolutePath("C:/Users")).toBe(true);
|
||||
expect(isAbsolutePath("d:\\projects")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true for UNC paths", () => {
|
||||
expect(isAbsolutePath("\\\\server\\share")).toBe(true);
|
||||
expect(isAbsolutePath("\\\\\\\\host\\path")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false for relative paths", () => {
|
||||
expect(isAbsolutePath("foo/bar")).toBe(false);
|
||||
expect(isAbsolutePath("./relative")).toBe(false);
|
||||
expect(isAbsolutePath("../parent")).toBe(false);
|
||||
expect(isAbsolutePath("")).toBe(false);
|
||||
expect(isAbsolutePath("file.txt")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false for edge cases that are not absolute paths", () => {
|
||||
expect(isAbsolutePath("")).toBe(false);
|
||||
expect(isAbsolutePath("C:")).toBe(false);
|
||||
});
|
||||
|
||||
it("handles mixed separators in absolute paths", () => {
|
||||
expect(isAbsolutePath("C:/Users\\mixed/path")).toBe(true);
|
||||
expect(isAbsolutePath("/tmp\\mixed/path")).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
export function isAbsolutePath(value: string): boolean {
|
||||
return (
|
||||
value.startsWith("/") || value.startsWith("\\\\") || /^[A-Za-z]:[\\/]/.test(value)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user