diff --git a/index.ts b/index.ts index 69aaf7d..6f39ebc 100755 --- a/index.ts +++ b/index.ts @@ -64,8 +64,15 @@ async function main(): Promise { process.exit(0); } if (args.marketplaceTarget) { - await updateMarketplace(args.marketplaceTarget); - process.exit(0); + try { + await updateMarketplace(args.marketplaceTarget); + process.exit(0); + } catch (error) { + console.error( + `Error: ${error instanceof Error ? error.message : String(error)}`, + ); + process.exit(1); + } } console.error( 'Error: Marketplace name is required for "update" command. Use "--all" to update all marketplaces or provide a marketplace name.' diff --git a/src/marketplace.test.ts b/src/marketplace.test.ts index c5d40ce..82a5f28 100644 --- a/src/marketplace.test.ts +++ b/src/marketplace.test.ts @@ -417,7 +417,7 @@ describe("marketplace", () => { } expect(calls).toEqual([["git", "-C", alphaLocation, "pull"]]); - expect(messages).toContain("Updated 1 marketplace(s)"); + expect(messages).toContain("\nUpdate complete: 1 succeeded, 0 failed"); }); test("updateAllMarketplaces() prints message when no GitHub marketplaces found", async () => { @@ -438,4 +438,57 @@ describe("marketplace", () => { expect(messages).toContain("No marketplaces to update."); }); + + test("updateAllMarketplaces() continues updating after failure and prints summary", async () => { + const alphaLocation = createMarketplaceDir("alpha"); + const betaLocation = createMarketplaceDir("beta"); + const gammaLocation = createMarketplaceDir("gamma"); + writeKnownMarketplaces({ + alpha: { + source: { source: "github", repo: "owner/alpha" }, + installLocation: alphaLocation, + lastUpdated: "2025-01-01T00:00:00.000Z", + }, + beta: { + source: { source: "github", repo: "owner/beta" }, + installLocation: betaLocation, + lastUpdated: "2025-01-02T00:00:00.000Z", + }, + gamma: { + source: { source: "github", repo: "owner/gamma" }, + installLocation: gammaLocation, + lastUpdated: "2025-01-03T00:00:00.000Z", + }, + }); + + const calls: string[][] = []; + const restoreSpawn = mockSpawnSync((cmd) => { + calls.push(cmd); + // Make beta fail + if (cmd[2] === betaLocation) { + return { exitCode: 1, stderr: Buffer.from("git pull failed") }; + } + return { exitCode: 0 }; + }); + + const { messages: logMessages, restore: restoreLog } = captureConsole("log"); + const { messages: errorMessages, restore: restoreError } = captureConsole("error"); + try { + await updateAllMarketplaces(paths); + } finally { + restoreSpawn(); + restoreLog(); + restoreError(); + } + + expect(calls).toEqual([ + ["git", "-C", alphaLocation, "pull"], + ["git", "-C", betaLocation, "pull"], + ["git", "-C", gammaLocation, "pull"], + ]); + expect(logMessages).toContain("Updated marketplace: alpha"); + expect(errorMessages).toContain("Error updating beta: Failed to clone/update marketplace: git pull failed"); + expect(logMessages).toContain("Updated marketplace: gamma"); + expect(logMessages).toContain("\nUpdate complete: 2 succeeded, 1 failed"); + }); }); diff --git a/src/marketplace.ts b/src/marketplace.ts index a7f13de..1f2066a 100644 --- a/src/marketplace.ts +++ b/src/marketplace.ts @@ -108,10 +108,8 @@ function runGitCommand(args: string[]): void { stderr: "pipe", }); } catch (error) { - console.error( - `Error: Failed to clone/update marketplace: ${error instanceof Error ? error.message : String(error)}`, - ); - process.exit(1); + const message = error instanceof Error ? error.message : String(error); + throw new Error(`Failed to clone/update marketplace: ${message}`); } if (result.exitCode !== 0) { @@ -119,8 +117,7 @@ function runGitCommand(args: string[]): void { decodeOutput(result.stderr) || decodeOutput(result.stdout) || `exit code ${result.exitCode ?? "unknown"}`; - console.error(`Error: Failed to clone/update marketplace: ${details}`); - process.exit(1); + throw new Error(`Failed to clone/update marketplace: ${details}`); } } @@ -170,7 +167,12 @@ export async function addMarketplace( const existing = knownMarketplaces[parsed.name]; if (existing) { if (existing.source.source === "github" && existing.source.repo === parsed.repo) { - runGitCommand(["-C", existing.installLocation, "pull"]); + try { + runGitCommand(["-C", existing.installLocation, "pull"]); + } catch (error) { + console.error(`Error: ${error instanceof Error ? error.message : String(error)}`); + process.exit(1); + } knownMarketplaces[parsed.name] = { ...existing, lastUpdated: new Date().toISOString(), @@ -190,7 +192,12 @@ export async function addMarketplace( const installLocation = join(marketplacesRoot, parsed.name); const repoUrl = `https://github.com/${parsed.repo}.git`; - runGitCommand(["clone", repoUrl, installLocation]); + try { + runGitCommand(["clone", repoUrl, installLocation]); + } catch (error) { + console.error(`Error: ${error instanceof Error ? error.message : String(error)}`); + process.exit(1); + } await validateMarketplace(installLocation, target); knownMarketplaces[parsed.name] = { @@ -230,8 +237,7 @@ export async function updateMarketplace( const knownMarketplaces = await readKnownMarketplaces(paths); const marketplace = knownMarketplaces[name]; if (!marketplace) { - console.error(`Error: Marketplace "${name}" not found`); - process.exit(1); + throw new Error(`Marketplace "${name}" not found`); } if (marketplace.source.source !== "github") { @@ -261,9 +267,23 @@ export async function updateAllMarketplaces( return; } + const results: { name: string; success: boolean; error?: string }[] = []; + for (const [name] of githubMarketplaces) { - await updateMarketplace(name, paths); + try { + await updateMarketplace(name, paths); + results.push({ name, success: true }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + console.error(`Error updating ${name}: ${errorMessage}`); + results.push({ name, success: false, error: errorMessage }); + } } - console.log(`Updated ${githubMarketplaces.length} marketplace(s)`); + const successCount = results.filter((r) => r.success).length; + const failureCount = results.filter((r) => !r.success).length; + + console.log( + `\nUpdate complete: ${successCount} succeeded, ${failureCount} failed`, + ); } diff --git a/src/plugin.ts b/src/plugin.ts index 9273b9e..9c93928 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -42,7 +42,6 @@ export async function disablePlugin(pluginName: string): Promise { return; } - await saveConfig({ try { await saveConfig({ enabledPlugins: config.enabledPlugins.filter((name) => name !== pluginName),