mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
fix: use stable cache key for SSH remote workspaces
- Generate cache key using workspace name and relative path from home - This ensures cache persistence across SSH sessions where absolute paths may change - Add comprehensive tests for the new cache key generation logic Fixes #6066
This commit is contained in:
parent
984d368f7a
commit
a9b70e4e76
2 changed files with 86 additions and 6 deletions
|
|
@ -3,6 +3,8 @@ import * as vscode from "vscode"
|
|||
import { createHash } from "crypto"
|
||||
import debounce from "lodash.debounce"
|
||||
import { CacheManager } from "../cache-manager"
|
||||
import * as path from "path"
|
||||
import * as os from "os"
|
||||
|
||||
// Mock safeWriteJson utility
|
||||
vitest.mock("../../../utils/safeWriteJson", () => ({
|
||||
|
|
@ -38,6 +40,11 @@ vitest.mock("@roo-code/telemetry", () => ({
|
|||
},
|
||||
}))
|
||||
|
||||
// Mock os module
|
||||
vitest.mock("os", () => ({
|
||||
homedir: vitest.fn(() => "/home/user"),
|
||||
}))
|
||||
|
||||
describe("CacheManager", () => {
|
||||
let mockContext: vscode.ExtensionContext
|
||||
let mockWorkspacePath: string
|
||||
|
|
@ -63,8 +70,18 @@ describe("CacheManager", () => {
|
|||
})
|
||||
|
||||
describe("constructor", () => {
|
||||
it("should correctly set up cachePath using Uri.joinPath and crypto.createHash", () => {
|
||||
const expectedHash = createHash("sha256").update(mockWorkspacePath).digest("hex")
|
||||
it("should correctly set up cachePath using Uri.joinPath with stable cache key", () => {
|
||||
// The cache key should be based on workspace name and relative path
|
||||
const workspaceName = path.basename(mockWorkspacePath)
|
||||
const homedir = os.homedir()
|
||||
let relativePath = mockWorkspacePath
|
||||
|
||||
if (mockWorkspacePath.startsWith(homedir)) {
|
||||
relativePath = path.relative(homedir, mockWorkspacePath)
|
||||
}
|
||||
|
||||
const compositeKey = `${workspaceName}::${relativePath}`
|
||||
const expectedHash = createHash("sha256").update(compositeKey).digest("hex")
|
||||
|
||||
expect(vscode.Uri.joinPath).toHaveBeenCalledWith(
|
||||
mockContext.globalStorageUri,
|
||||
|
|
@ -75,6 +92,36 @@ describe("CacheManager", () => {
|
|||
it("should set up debounced save function", () => {
|
||||
expect(debounce).toHaveBeenCalledWith(expect.any(Function), 1500)
|
||||
})
|
||||
|
||||
it("should generate stable cache key for workspace under home directory", () => {
|
||||
// os.homedir is already mocked to return '/home/user'
|
||||
const workspaceUnderHome = "/home/user/projects/myproject"
|
||||
const cacheManagerHome = new CacheManager(mockContext, workspaceUnderHome)
|
||||
|
||||
// Expected key should use relative path from home
|
||||
const expectedKey = `myproject::projects/myproject`
|
||||
const expectedHash = createHash("sha256").update(expectedKey).digest("hex")
|
||||
|
||||
expect(vscode.Uri.joinPath).toHaveBeenCalledWith(
|
||||
mockContext.globalStorageUri,
|
||||
`roo-index-cache-${expectedHash}.json`,
|
||||
)
|
||||
})
|
||||
|
||||
it("should generate stable cache key for workspace outside home directory", () => {
|
||||
// os.homedir is already mocked to return '/home/user'
|
||||
const workspaceOutsideHome = "/opt/projects/myproject"
|
||||
const cacheManagerOutside = new CacheManager(mockContext, workspaceOutsideHome)
|
||||
|
||||
// Expected key should use full path since it's outside home
|
||||
const expectedKey = `myproject::/opt/projects/myproject`
|
||||
const expectedHash = createHash("sha256").update(expectedKey).digest("hex")
|
||||
|
||||
expect(vscode.Uri.joinPath).toHaveBeenCalledWith(
|
||||
mockContext.globalStorageUri,
|
||||
`roo-index-cache-${expectedHash}.json`,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("initialize", () => {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import debounce from "lodash.debounce"
|
|||
import { safeWriteJson } from "../../utils/safeWriteJson"
|
||||
import { TelemetryService } from "@roo-code/telemetry"
|
||||
import { TelemetryEventName } from "@roo-code/types"
|
||||
import * as path from "path"
|
||||
import * as os from "os"
|
||||
|
||||
/**
|
||||
* Manages the cache for code indexing
|
||||
|
|
@ -23,15 +25,46 @@ export class CacheManager implements ICacheManager {
|
|||
private context: vscode.ExtensionContext,
|
||||
private workspacePath: string,
|
||||
) {
|
||||
this.cachePath = vscode.Uri.joinPath(
|
||||
context.globalStorageUri,
|
||||
`roo-index-cache-${createHash("sha256").update(workspacePath).digest("hex")}.json`,
|
||||
)
|
||||
// Generate a stable cache key that persists across SSH sessions
|
||||
const cacheKey = this.generateStableCacheKey(workspacePath)
|
||||
this.cachePath = vscode.Uri.joinPath(context.globalStorageUri, `roo-index-cache-${cacheKey}.json`)
|
||||
this._debouncedSaveCache = debounce(async () => {
|
||||
await this._performSave()
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a stable cache key for the workspace that persists across SSH sessions
|
||||
* @param workspacePath The workspace path
|
||||
* @returns A stable hash key
|
||||
*/
|
||||
private generateStableCacheKey(workspacePath: string): string {
|
||||
// Get the workspace folder name
|
||||
const workspaceName = path.basename(workspacePath)
|
||||
|
||||
// Try to get a relative path from home directory for additional stability
|
||||
const homedir = os.homedir()
|
||||
let relativePath = workspacePath
|
||||
|
||||
try {
|
||||
// If the workspace is under the home directory, use the relative path
|
||||
if (workspacePath.startsWith(homedir)) {
|
||||
relativePath = path.relative(homedir, workspacePath)
|
||||
}
|
||||
} catch (error) {
|
||||
// If we can't get relative path, just use the full path
|
||||
console.warn("Failed to get relative path from home directory:", error)
|
||||
}
|
||||
|
||||
// Create a composite key using workspace name and relative path
|
||||
// This should be more stable across SSH sessions where the absolute path might change
|
||||
// but the relative structure remains the same
|
||||
const compositeKey = `${workspaceName}::${relativePath}`
|
||||
|
||||
// Generate hash from the composite key
|
||||
return createHash("sha256").update(compositeKey).digest("hex")
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the cache manager by loading the cache file
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue