* Clean up legacy non-versioned cache directories. * * Legacy cache structure: ~/.claude/plugins/cache/{plugin-name}/ * Versioned cache structure: ~/.claude/plugins/cache/{marketplace}/{plugin}/{version}/ * * This function removes legacy directories that are not referenced by any installation.
(v2Data: InstalledPluginsFileV2)
| 190 | * This function removes legacy directories that are not referenced by any installation. |
| 191 | */ |
| 192 | function cleanupLegacyCache(v2Data: InstalledPluginsFileV2): void { |
| 193 | const fs = getFsImplementation() |
| 194 | const cachePath = getPluginCachePath() |
| 195 | try { |
| 196 | // Collect all install paths that are referenced |
| 197 | const referencedPaths = new Set<string>() |
| 198 | for (const installations of Object.values(v2Data.plugins)) { |
| 199 | for (const entry of installations) { |
| 200 | referencedPaths.add(entry.installPath) |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | // List top-level directories in cache |
| 205 | const entries = fs.readdirSync(cachePath) |
| 206 | |
| 207 | for (const dirent of entries) { |
| 208 | if (!dirent.isDirectory()) { |
| 209 | continue |
| 210 | } |
| 211 | |
| 212 | const entry = dirent.name |
| 213 | const entryPath = join(cachePath, entry) |
| 214 | |
| 215 | // Check if this is a versioned cache (marketplace dir with plugin/version subdirs) |
| 216 | // or a legacy cache (flat plugin directory) |
| 217 | const subEntries = fs.readdirSync(entryPath) |
| 218 | const hasVersionedStructure = subEntries.some(subDirent => { |
| 219 | if (!subDirent.isDirectory()) return false |
| 220 | const subPath = join(entryPath, subDirent.name) |
| 221 | // Check if subdir contains version directories (semver-like or hash) |
| 222 | const versionEntries = fs.readdirSync(subPath) |
| 223 | return versionEntries.some(vDirent => vDirent.isDirectory()) |
| 224 | }) |
| 225 | |
| 226 | if (hasVersionedStructure) { |
| 227 | // This is a marketplace directory with versioned structure - skip |
| 228 | continue |
| 229 | } |
| 230 | |
| 231 | // This is a legacy flat cache directory |
| 232 | // Check if it's referenced by any installation |
| 233 | if (!referencedPaths.has(entryPath)) { |
| 234 | // Not referenced - safe to delete |
| 235 | fs.rmSync(entryPath, { recursive: true, force: true }) |
| 236 | logForDebugging(`Cleaned up legacy cache directory: ${entry}`) |
| 237 | } |
| 238 | } |
| 239 | } catch (error) { |
| 240 | const errorMsg = errorMessage(error) |
| 241 | logForDebugging(`Failed to clean up legacy cache: ${errorMsg}`, { |
| 242 | level: 'warn', |
| 243 | }) |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | /** |
| 248 | * Reset migration state (for testing) |
no test coverage detected