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