diff --git a/__tests__/commands/export-sql.js b/__tests__/commands/export-sql.js index ad46695d3..05d1db63c 100644 --- a/__tests__/commands/export-sql.js +++ b/__tests__/commands/export-sql.js @@ -187,7 +187,7 @@ describe( 'commands/ExportSQLCommand', () => { const confirmEnoughStorageSpy = jest.spyOn( exportCommand, 'confirmEnoughStorage' ); beforeAll( () => { - confirmEnoughStorageSpy.mockResolvedValue( true ); + confirmEnoughStorageSpy.mockResolvedValue( { continue: true, isPromptShown: false } ); downloadSpy.mockResolvedValue( 'test-backup.sql.gz' ); } ); diff --git a/__tests__/lib/backup-storage-availability/backup-storage-availability.ts b/__tests__/lib/backup-storage-availability/backup-storage-availability.ts index 332f4bf2e..8c30ccf42 100644 --- a/__tests__/lib/backup-storage-availability/backup-storage-availability.ts +++ b/__tests__/lib/backup-storage-availability/backup-storage-availability.ts @@ -28,7 +28,7 @@ describe( 'backup-storage-availability', () => { await expect( backupStorageAvailability.validateAndPromptDiskSpaceWarningForBackupImport() - ).resolves.toBe( true ); + ).resolves.toStrictEqual( { continue: true, isPromptShown: true } ); expect( confirmRunSpy ).toHaveBeenCalled(); } ); @@ -46,7 +46,7 @@ describe( 'backup-storage-availability', () => { await expect( backupStorageAvailability.validateAndPromptDiskSpaceWarningForBackupImport() - ).resolves.toBe( true ); + ).resolves.toStrictEqual( { continue: true, isPromptShown: false } ); expect( confirmRunSpy ).not.toHaveBeenCalled(); } ); @@ -73,7 +73,7 @@ describe( 'backup-storage-availability', () => { await expect( backupStorageAvailability.validateAndPromptDiskSpaceWarningForDevEnvBackupImport() - ).resolves.toBe( true ); + ).resolves.toStrictEqual( { continue: true, isPromptShown: true } ); expect( confirmRunSpy ).toHaveBeenCalledTimes( timesPrompted ); } @@ -92,7 +92,7 @@ describe( 'backup-storage-availability', () => { await expect( backupStorageAvailability.validateAndPromptDiskSpaceWarningForDevEnvBackupImport() - ).resolves.toBe( false ); + ).resolves.toStrictEqual( { continue: false, isPromptShown: true } ); expect( confirmRunSpy ).toHaveBeenCalledTimes( 1 ); } ); @@ -114,7 +114,7 @@ describe( 'backup-storage-availability', () => { await expect( backupStorageAvailability.validateAndPromptDiskSpaceWarningForDevEnvBackupImport() - ).resolves.toBe( true ); + ).resolves.toStrictEqual( { continue: true, isPromptShown: Boolean( timesPrompted ) } ); expect( confirmRunSpy ).toHaveBeenCalledTimes( timesPrompted ); } @@ -132,7 +132,7 @@ describe( 'backup-storage-availability', () => { await expect( backupStorageAvailability.validateAndPromptDiskSpaceWarningForDevEnvBackupImport() - ).resolves.toBe( true ); + ).resolves.toStrictEqual( { continue: true, isPromptShown: false } ); expect( confirmRunSpy ).not.toHaveBeenCalled(); } ); diff --git a/src/commands/export-sql.js b/src/commands/export-sql.js index 944ef90c2..671cc96e3 100644 --- a/src/commands/export-sql.js +++ b/src/commands/export-sql.js @@ -422,9 +422,16 @@ export class ExportSQLCommand { ); this.progressTracker.stepSuccess( this.steps.CREATE ); - const storageConfirmed = await this.progressTracker.handleContinuePrompt( async () => { - return await this.confirmEnoughStorage( await this.getExportJob() ); - }, 3 ); + const storageConfirmed = await this.progressTracker.handleContinuePrompt( + async setPromptShown => { + const status = await this.confirmEnoughStorage( await this.getExportJob() ); + if ( status.isPromptShown ) { + setPromptShown(); + } + + return status.continue; + } + ); if ( storageConfirmed ) { this.progressTracker.stepSuccess( this.steps.CONFIRM_ENOUGH_STORAGE ); diff --git a/src/lib/backup-storage-availability/backup-storage-availability.ts b/src/lib/backup-storage-availability/backup-storage-availability.ts index b6c34b2c6..8ee1d7b3a 100644 --- a/src/lib/backup-storage-availability/backup-storage-availability.ts +++ b/src/lib/backup-storage-availability/backup-storage-availability.ts @@ -11,6 +11,11 @@ import { formatMetricBytes } from '../cli/format'; const oneGiBInBytes = 1024 * 1024 * 1024; +export interface PromptStatus { + continue: boolean; + isPromptShown: boolean; +} + export class BackupStorageAvailability { archiveSize: number; @@ -86,7 +91,7 @@ export class BackupStorageAvailability { } // eslint-disable-next-line id-length - async validateAndPromptDiskSpaceWarningForBackupImport(): Promise< boolean > { + async validateAndPromptDiskSpaceWarningForBackupImport(): Promise< PromptStatus > { const isStorageAvailable = ( await this.getStorageAvailableInVipPath() ) > this.getArchiveSize(); if ( ! isStorageAvailable ) { @@ -97,16 +102,25 @@ export class BackupStorageAvailability { ) } of free space in your machine to download this database backup. Do you still want to continue with downloading the database backup?`, } ); - return await confirmPrompt.run(); + return { + continue: await confirmPrompt.run(), + isPromptShown: true, + }; } - return true; + return { + continue: true, + isPromptShown: false, + }; } // eslint-disable-next-line id-length - async validateAndPromptDiskSpaceWarningForDevEnvBackupImport(): Promise< boolean > { + async validateAndPromptDiskSpaceWarningForDevEnvBackupImport(): Promise< PromptStatus > { let storageAvailableInMainMachinePrompted = false; + // there's two prompts, so as long as one prompt is shown, we need to set isPromptShown + let isPromptShown = false; + if ( ! ( await this.isStorageAvailableInMainMachine() ) ) { const storageRequired = this.getStorageRequiredInMainMachine(); const storageAvailableInVipPath = this.bytesToHuman( @@ -121,10 +135,15 @@ Do you still want to continue with importing the database backup? `, } ); + isPromptShown = true; + storageAvailableInMainMachinePrompted = await confirmPrompt.run(); if ( ! storageAvailableInMainMachinePrompted ) { - return false; + return { + continue: false, + isPromptShown, + }; } } @@ -141,17 +160,28 @@ Do you still want to continue with importing the database backup? Do you still want to continue with importing the database backup?`, } ); - return await confirmPrompt.run(); + isPromptShown = true; + + return { + continue: await confirmPrompt.run(), + isPromptShown, + }; } } catch ( error ) { if ( error instanceof DockerMachineNotFoundError ) { // skip storage available check - return true; + return { + continue: true, + isPromptShown, + }; } throw error; } - return true; + return { + continue: true, + isPromptShown, + }; } } diff --git a/src/lib/cli/progress.ts b/src/lib/cli/progress.ts index b62db0009..309be2b5f 100644 --- a/src/lib/cli/progress.ts +++ b/src/lib/cli/progress.ts @@ -193,15 +193,24 @@ export class ProgressTracker { } async handleContinuePrompt< PromptReturn >( - prompt: () => Promise< PromptReturn > + prompt: ( setPromptShown: () => void ) => Promise< PromptReturn > ): Promise< PromptReturn > { this.print(); this.stopPrinting(); - const returnValue = await prompt(); - this.displayFromStep = [ ...this.getSteps().values() ].findIndex( - step => step.status === StepStatus.RUNNING - ); + let isPromptShown = false; + + const setPromptShown = () => { + isPromptShown = true; + }; + + const returnValue = await prompt( setPromptShown ); + + if ( isPromptShown ) { + this.displayFromStep = [ ...this.getSteps().values() ].findIndex( + step => step.status === StepStatus.RUNNING + ); + } let hasPrintedOnce = false; const printingStartedPromise = new Promise< void >( resolve => { @@ -218,7 +227,9 @@ export class ProgressTracker { linesToSkip += EOL; } - process.stdout.write( linesToSkip ); + if ( isPromptShown ) { + process.stdout.write( linesToSkip ); + } hasPrintedOnce = true;