Browse Source

Use safe path comparison

Saoud Rizwan 1 year ago
parent
commit
b5ca470ebf

+ 11 - 5
src/ClaudeDev.ts

@@ -29,6 +29,7 @@ import { regexSearchFiles } from "./utils/ripgrep"
 import { parseMentions } from "./utils/context-mentions"
 import { UrlContentFetcher } from "./utils/UrlContentFetcher"
 import { diagnosticsToProblemsString, getNewDiagnostics } from "./utils/diagnostics"
+import { arePathsEqual } from "./utils/path-helpers"
 
 const SYSTEM_PROMPT = async (
 	supportsImages: boolean
@@ -786,7 +787,9 @@ export class ClaudeDev {
 
 			// if the file is already open, ensure it's not dirty before getting its contents
 			if (fileExists) {
-				const existingDocument = vscode.workspace.textDocuments.find((doc) => doc.uri.fsPath === absolutePath)
+				const existingDocument = vscode.workspace.textDocuments.find((doc) =>
+					arePathsEqual(doc.uri.fsPath, absolutePath)
+				)
 				if (existingDocument && existingDocument.isDirty) {
 					await existingDocument.save()
 				}
@@ -861,7 +864,10 @@ export class ClaudeDev {
 			const tabs = vscode.window.tabGroups.all
 				.map((tg) => tg.tabs)
 				.flat()
-				.filter((tab) => tab.input instanceof vscode.TabInputText && tab.input.uri.fsPath === absolutePath)
+				.filter(
+					(tab) =>
+						tab.input instanceof vscode.TabInputText && arePathsEqual(tab.input.uri.fsPath, absolutePath)
+				)
 			for (const tab of tabs) {
 				await vscode.window.tabGroups.close(tab)
 				// console.log(`Closed tab for ${absolutePath}`)
@@ -1291,11 +1297,11 @@ export class ClaudeDev {
 	getReadablePath(relPath: string): string {
 		// path.resolve is flexible in that it will resolve relative paths like '../../' to the cwd and even ignore the cwd if the relPath is actually an absolute path
 		const absolutePath = path.resolve(cwd, relPath)
-		if (cwd === path.join(os.homedir(), "Desktop")) {
+		if (arePathsEqual(cwd, path.join(os.homedir(), "Desktop"))) {
 			// User opened vscode without a workspace, so cwd is the Desktop. Show the full absolute path to keep the user aware of where files are being created
 			return absolutePath.toPosix()
 		}
-		if (path.normalize(absolutePath) === path.normalize(cwd)) {
+		if (arePathsEqual(path.normalize(absolutePath), path.normalize(cwd))) {
 			return path.basename(absolutePath).toPosix()
 		} else {
 			// show the relative path to the cwd
@@ -2107,7 +2113,7 @@ ${this.customInstructions.trim()}
 
 		if (includeFileDetails) {
 			details += `\n\n# Current Working Directory (${cwd.toPosix()}) Files\n`
-			const isDesktop = cwd === path.join(os.homedir(), "Desktop")
+			const isDesktop = arePathsEqual(cwd, path.join(os.homedir(), "Desktop"))
 			if (isDesktop) {
 				// don't want to immediately access desktop since it would show permission popup
 				details += "(Desktop files not shown automatically. Use list_files to explore if needed.)"

+ 2 - 1
src/integrations/TerminalManager.ts

@@ -2,6 +2,7 @@ import { EventEmitter } from "events"
 import pWaitFor from "p-wait-for"
 import stripAnsi from "strip-ansi"
 import * as vscode from "vscode"
+import { arePathsEqual } from "../utils/path-helpers"
 
 /*
 TerminalManager:
@@ -225,7 +226,7 @@ export class TerminalManager {
 			if (!terminalCwd) {
 				return false
 			}
-			return vscode.Uri.file(cwd).fsPath === terminalCwd.fsPath
+			return arePathsEqual(vscode.Uri.file(cwd).fsPath, terminalCwd.fsPath)
 		})
 		if (availableTerminal) {
 			this.terminalIds.add(availableTerminal.id)

+ 3 - 2
src/parse-source-code/index.ts

@@ -3,6 +3,7 @@ import { globby, Options } from "globby"
 import os from "os"
 import * as path from "path"
 import { LanguageParser, loadRequiredLanguageParsers } from "./languageParser"
+import { arePathsEqual } from "../utils/path-helpers"
 
 // TODO: implement caching behavior to avoid having to keep analyzing project for new tasks.
 export async function parseSourceCodeForDefinitionsTopLevel(dirPath: string): Promise<string> {
@@ -57,12 +58,12 @@ export async function listFiles(dirPath: string, recursive: boolean, limit: numb
 	const absolutePath = path.resolve(dirPath)
 	// Do not allow listing files in root or home directory, which Claude tends to want to do when the user's prompt is vague.
 	const root = process.platform === "win32" ? path.parse(absolutePath).root : "/"
-	const isRoot = absolutePath === root
+	const isRoot = arePathsEqual(absolutePath, root)
 	if (isRoot) {
 		return [[root], false]
 	}
 	const homeDir = os.homedir()
-	const isHomeDir = absolutePath === homeDir
+	const isHomeDir = arePathsEqual(absolutePath, homeDir)
 	if (isHomeDir) {
 		return [[homeDir], false]
 	}

+ 2 - 1
src/utils/open-file.ts

@@ -1,6 +1,7 @@
 import * as path from "path"
 import * as os from "os"
 import * as vscode from "vscode"
+import { arePathsEqual } from "./path-helpers"
 
 export async function openImage(dataUri: string) {
 	const matches = dataUri.match(/^data:image\/([a-zA-Z]+);base64,(.+)$/)
@@ -27,7 +28,7 @@ export async function openFile(absolutePath: string) {
 		try {
 			for (const group of vscode.window.tabGroups.all) {
 				const existingTab = group.tabs.find(
-					(tab) => tab.input instanceof vscode.TabInputText && tab.input.uri.fsPath === uri.fsPath
+					(tab) => tab.input instanceof vscode.TabInputText && arePathsEqual(tab.input.uri.fsPath, uri.fsPath)
 				)
 				if (existingTab) {
 					const activeColumn = vscode.window.activeTextEditor?.viewColumn

+ 24 - 24
src/utils/path-helpers.ts

@@ -46,30 +46,30 @@ String.prototype.toPosix = function (this: string): string {
 }
 
 // Safe path comparison that works across different platforms
-// export function arePathsEqual(path1?: string, path2?: string): boolean {
-// 	if (!path1 && !path2) {
-// 		return true
-// 	}
-// 	if (!path1 || !path2) {
-// 		return false
-// 	}
+export function arePathsEqual(path1?: string, path2?: string): boolean {
+	if (!path1 && !path2) {
+		return true
+	}
+	if (!path1 || !path2) {
+		return false
+	}
 
-// 	path1 = normalizePath(path1)
-// 	path2 = normalizePath(path2)
+	path1 = normalizePath(path1)
+	path2 = normalizePath(path2)
 
-// 	if (process.platform === "win32") {
-// 		return path1.toLowerCase() === path2.toLowerCase()
-// 	}
-// 	return path1 === path2
-// }
+	if (process.platform === "win32") {
+		return path1.toLowerCase() === path2.toLowerCase()
+	}
+	return path1 === path2
+}
 
-// function normalizePath(p: string): string {
-// 	// normalize resolve ./.. segments, removes duplicate slashes, and standardizes path separators
-// 	let normalized = path.normalize(p)
-// 	// however it doesn't remove trailing slashes
-// 	// remove trailing slash, except for root paths
-// 	if (normalized.length > 1 && (normalized.endsWith("/") || normalized.endsWith("\\"))) {
-// 		normalized = normalized.slice(0, -1)
-// 	}
-// 	return normalized
-// }
+function normalizePath(p: string): string {
+	// normalize resolve ./.. segments, removes duplicate slashes, and standardizes path separators
+	let normalized = path.normalize(p)
+	// however it doesn't remove trailing slashes
+	// remove trailing slash, except for root paths
+	if (normalized.length > 1 && (normalized.endsWith("/") || normalized.endsWith("\\"))) {
+		normalized = normalized.slice(0, -1)
+	}
+	return normalized
+}