From 01ff26c52deb5f513b279ee63598352040343ec5 Mon Sep 17 00:00:00 2001 From: Jeff MAURY Date: Wed, 28 Feb 2024 16:48:01 +0100 Subject: [PATCH] fix: report error and reset state if checkout fails Fixes #428 Signed-off-by: Jeff MAURY --- .../src/managers/applicationManager.spec.ts | 43 +++++++++++++++++++ .../src/managers/applicationManager.ts | 41 ++++++++++-------- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/packages/backend/src/managers/applicationManager.spec.ts b/packages/backend/src/managers/applicationManager.spec.ts index a6c4c8fdb..4995ffc8a 100644 --- a/packages/backend/src/managers/applicationManager.spec.ts +++ b/packages/backend/src/managers/applicationManager.spec.ts @@ -437,6 +437,49 @@ describe('doCheckout', () => { }, }); }); + test('doCheckout report an error if clone is errored', async () => { + vi.spyOn(fs, 'existsSync').mockReturnValue(false); + vi.spyOn(fs, 'mkdirSync'); + const cloneRepositoryMock = vi.fn().mockRejectedValue(new Error('Unknown Git reference')); + const manager = new ApplicationManager( + '/home/user/aistudio', + { + cloneRepository: cloneRepositoryMock, + } as unknown as GitManager, + taskRegistry, + {} as Webview, + {} as PodmanConnection, + {} as CatalogManager, + {} as unknown as ModelsManager, + telemetryLogger, + localRepositoryRegistry, + ); + const gitCloneOptions = { + repository: 'repo', + ref: '000000', + targetDirectory: 'folder', + }; + let expectedError: unknown; + + try { + await manager.doCheckout(gitCloneOptions); + } catch (err: unknown) { + expectedError = err; + } + + expect(cloneRepositoryMock).toBeCalledWith(gitCloneOptions); + expect(mocks.updateTaskMock).toHaveBeenLastCalledWith({ + id: expect.any(String), + name: 'Checkout repository', + state: 'error', + labels: { + git: 'checkout', + }, + error: 'Error: Unknown Git reference', + }); + expect(expectedError).to.be.a('Error'); + expect((expectedError as Error).message).equal('Unknown Git reference'); + }); test('do not clone repo if already present locally', async () => { vi.spyOn(fs, 'existsSync').mockReturnValue(true); const stats = { diff --git a/packages/backend/src/managers/applicationManager.ts b/packages/backend/src/managers/applicationManager.ts index 17bd5fbe9..9ae962d05 100644 --- a/packages/backend/src/managers/applicationManager.ts +++ b/packages/backend/src/managers/applicationManager.ts @@ -548,24 +548,31 @@ export class ApplicationManager { git: 'checkout', }); - // We might already have the repository cloned - if (fs.existsSync(gitCloneInfo.targetDirectory) && fs.statSync(gitCloneInfo.targetDirectory).isDirectory()) { - // Update checkout state - checkoutTask.name = 'Checkout repository (cached).'; - checkoutTask.state = 'success'; - } else { - // Create folder - fs.mkdirSync(gitCloneInfo.targetDirectory, { recursive: true }); - - // Clone the repository - console.log(`Cloning repository ${gitCloneInfo.repository} in ${gitCloneInfo.targetDirectory}.`); - await this.git.cloneRepository(gitCloneInfo); - - // Update checkout state - checkoutTask.state = 'success'; + try { + // We might already have the repository cloned + if (fs.existsSync(gitCloneInfo.targetDirectory) && fs.statSync(gitCloneInfo.targetDirectory).isDirectory()) { + // Update checkout state + checkoutTask.name = 'Checkout repository (cached).'; + checkoutTask.state = 'success'; + } else { + // Create folder + fs.mkdirSync(gitCloneInfo.targetDirectory, { recursive: true }); + + // Clone the repository + console.log(`Cloning repository ${gitCloneInfo.repository} in ${gitCloneInfo.targetDirectory}.`); + await this.git.cloneRepository(gitCloneInfo); + + // Update checkout state + checkoutTask.state = 'success'; + } + } catch (err: unknown) { + checkoutTask.state = 'error'; + checkoutTask.error = String(err); + throw err; + } finally { + // Update task registry + this.taskRegistry.updateTask(checkoutTask); } - // Update task registry - this.taskRegistry.updateTask(checkoutTask); } adoptRunningEnvironments() {