(
name: string,
onProgress?: MarketplaceProgressCallback,
options?: { disableCredentialHelper?: boolean },
)
| 2363 | * @throws If marketplace not found or refresh fails |
| 2364 | */ |
| 2365 | export async function refreshMarketplace( |
| 2366 | name: string, |
| 2367 | onProgress?: MarketplaceProgressCallback, |
| 2368 | options?: { disableCredentialHelper?: boolean }, |
| 2369 | ): Promise<void> { |
| 2370 | const config = await loadKnownMarketplacesConfig() |
| 2371 | const entry = config[name] |
| 2372 | |
| 2373 | if (!entry) { |
| 2374 | throw new Error( |
| 2375 | `Marketplace '${name}' not found. Available marketplaces: ${Object.keys(config).join(', ')}`, |
| 2376 | ) |
| 2377 | } |
| 2378 | |
| 2379 | // Clear the memoization cache for this specific marketplace |
| 2380 | getMarketplace.cache?.delete?.(name) |
| 2381 | |
| 2382 | // settings-sourced marketplaces have no upstream to pull. Edits to the |
| 2383 | // inline plugins array surface as sourceChanged in the reconciler, which |
| 2384 | // re-materializes via addMarketplaceSource — refresh is not the vehicle. |
| 2385 | if (entry.source.source === 'settings') { |
| 2386 | logForDebugging( |
| 2387 | `Skipping refresh for settings-sourced marketplace '${name}' — no upstream`, |
| 2388 | ) |
| 2389 | return |
| 2390 | } |
| 2391 | |
| 2392 | try { |
| 2393 | // For updates, use the existing installLocation directly (in-place update) |
| 2394 | const installLocation = entry.installLocation |
| 2395 | const source = entry.source |
| 2396 | |
| 2397 | // Seed-managed marketplaces are controlled by the seed image. Refreshing |
| 2398 | // would be pointless — registerSeedMarketplaces() overwrites installLocation |
| 2399 | // back to seed on next startup. Error with guidance instead. |
| 2400 | const seedDir = seedDirFor(installLocation) |
| 2401 | if (seedDir) { |
| 2402 | throw new Error( |
| 2403 | `Marketplace '${name}' is seed-managed (${seedDir}) and its content is ` + |
| 2404 | `controlled by the seed image. To update: ask your admin to update the seed.`, |
| 2405 | ) |
| 2406 | } |
| 2407 | |
| 2408 | // For remote sources (github/git/url), installLocation must be inside the |
| 2409 | // marketplaces cache dir. A corrupted value (gh-32793, gh-32661 — e.g. |
| 2410 | // Windows path read on WSL, literal tilde, manual edit) can point at the |
| 2411 | // user's project. cacheMarketplaceFromGit would then run git ops with that |
| 2412 | // cwd (git walks up to the user's .git) and fs.rm it on pull failure. |
| 2413 | // Refuse instead of auto-fixing so the user knows their state is corrupted. |
| 2414 | if (!isLocalMarketplaceSource(source)) { |
| 2415 | const cacheDir = resolve(getMarketplacesCacheDir()) |
| 2416 | const resolvedLoc = resolve(installLocation) |
| 2417 | if (resolvedLoc !== cacheDir && !resolvedLoc.startsWith(cacheDir + sep)) { |
| 2418 | throw new Error( |
| 2419 | `Marketplace '${name}' has a corrupted installLocation ` + |
| 2420 | `(${installLocation}) — expected a path inside ${cacheDir}. ` + |
| 2421 | `This can happen after cross-platform path writes or manual edits ` + |
| 2422 | `to known_marketplaces.json. ` + |
no test coverage detected