(skipPrompt = false)
| 362 | } |
| 363 | |
| 364 | async function cleanup(skipPrompt = false) { |
| 365 | const spinner = p.spinner() |
| 366 | let hasChanges = false |
| 367 | |
| 368 | // 1. Find and remove extra submodules |
| 369 | const allProjects: Project[] = [ |
| 370 | ...Object.entries(submodules).map(([name, url]) => ({ |
| 371 | name, |
| 372 | url, |
| 373 | type: 'source' as const, |
| 374 | path: `sources/${name}`, |
| 375 | })), |
| 376 | ...Object.entries(vendors).map(([name, config]) => ({ |
| 377 | name, |
| 378 | url: (config as VendorConfig).source, |
| 379 | type: 'vendor' as const, |
| 380 | path: `vendor/${name}`, |
| 381 | })), |
| 382 | ] |
| 383 | |
| 384 | const existingSubmodulePaths = getExistingSubmodulePaths() |
| 385 | const expectedSubmodulePaths = new Set(allProjects.map(p => p.path)) |
| 386 | const extraSubmodules = existingSubmodulePaths.filter(path => !expectedSubmodulePaths.has(path)) |
| 387 | |
| 388 | if (extraSubmodules.length > 0) { |
| 389 | p.log.warn(`Found ${extraSubmodules.length} submodule(s) not in meta.ts:`) |
| 390 | for (const path of extraSubmodules) { |
| 391 | p.log.message(` - ${path}`) |
| 392 | } |
| 393 | |
| 394 | const shouldRemove = skipPrompt |
| 395 | ? true |
| 396 | : await p.confirm({ |
| 397 | message: 'Remove these extra submodules?', |
| 398 | initialValue: true, |
| 399 | }) |
| 400 | |
| 401 | if (p.isCancel(shouldRemove)) { |
| 402 | p.cancel('Cancelled') |
| 403 | return |
| 404 | } |
| 405 | |
| 406 | if (shouldRemove) { |
| 407 | hasChanges = true |
| 408 | for (const submodulePath of extraSubmodules) { |
| 409 | spinner.start(`Removing submodule: ${submodulePath}`) |
| 410 | try { |
| 411 | removeSubmodule(submodulePath) |
| 412 | spinner.stop(`Removed: ${submodulePath}`) |
| 413 | } |
| 414 | catch (e) { |
| 415 | spinner.stop(`Failed to remove ${submodulePath}: ${e}`) |
| 416 | } |
| 417 | } |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | // 2. Find and remove extra skills |
no test coverage detected