|
1 | 1 | import { inject, injectable } from 'inversify'; |
2 | | -import { workspace, CancellationToken } from 'vscode'; |
| 2 | +import { workspace, CancellationToken, window } from 'vscode'; |
3 | 3 | import * as fs from 'fs'; |
4 | 4 | import * as path from '../../platform/vscode-path/path'; |
5 | 5 | import type { DeepnoteProject } from './deepnoteTypes'; |
6 | 6 | import { ILogger } from '../../platform/logging/types'; |
| 7 | +import { IPersistentStateFactory } from '../../platform/common/types'; |
| 8 | + |
| 9 | +const DONT_ASK_OVERWRITE_REQUIREMENTS_KEY = 'DEEPNOTE_DONT_ASK_OVERWRITE_REQUIREMENTS'; |
7 | 10 |
|
8 | 11 | /** |
9 | 12 | * Helper class for creating requirements.txt files from Deepnote project settings. |
10 | 13 | */ |
11 | 14 | @injectable() |
12 | 15 | export class DeepnoteRequirementsHelper { |
13 | | - constructor(@inject(ILogger) private readonly logger: ILogger) {} |
| 16 | + constructor( |
| 17 | + @inject(ILogger) private readonly logger: ILogger, |
| 18 | + @inject(IPersistentStateFactory) private readonly persistentStateFactory: IPersistentStateFactory |
| 19 | + ) {} |
14 | 20 |
|
15 | 21 | /** |
16 | 22 | * Extracts requirements from project settings and creates a local requirements.txt file. |
@@ -45,9 +51,76 @@ export class DeepnoteRequirementsHelper { |
45 | 51 | const workspaceRoot = workspaceFolders[0].uri.fsPath; |
46 | 52 | const requirementsPath = path.join(workspaceRoot, 'requirements.txt'); |
47 | 53 |
|
48 | | - // Convert requirements array to text format |
| 54 | + // Convert requirements array to text format first |
49 | 55 | const requirementsText = requirements.join('\n') + '\n'; |
50 | 56 |
|
| 57 | + // Check if requirements.txt already exists |
| 58 | + const fileExists = await fs.promises |
| 59 | + .access(requirementsPath) |
| 60 | + .then(() => true) |
| 61 | + .catch(() => false); |
| 62 | + |
| 63 | + if (fileExists) { |
| 64 | + // Read existing file contents and compare |
| 65 | + const existingContent = await fs.promises.readFile(requirementsPath, 'utf8'); |
| 66 | + |
| 67 | + if (existingContent === requirementsText) { |
| 68 | + this.logger.info('requirements.txt already has the correct content, skipping update'); |
| 69 | + return; |
| 70 | + } |
| 71 | + |
| 72 | + // File exists but content is different, check if we should prompt user |
| 73 | + const dontAskState = this.persistentStateFactory.createGlobalPersistentState<boolean>( |
| 74 | + DONT_ASK_OVERWRITE_REQUIREMENTS_KEY, |
| 75 | + false // default: ask user |
| 76 | + ); |
| 77 | + |
| 78 | + if (!dontAskState.value) { |
| 79 | + // User hasn't chosen "Don't Ask Again", so prompt them |
| 80 | + const yes = 'Yes'; |
| 81 | + const no = 'No'; |
| 82 | + const dontAskAgain = "Don't Ask Again"; |
| 83 | + |
| 84 | + const response = await window.showWarningMessage( |
| 85 | + `A requirements.txt file already exists in this workspace. Do you want to override it with requirements from your Deepnote project?`, |
| 86 | + { modal: true }, |
| 87 | + yes, |
| 88 | + no, |
| 89 | + dontAskAgain |
| 90 | + ); |
| 91 | + |
| 92 | + // Check cancellation after showing the prompt |
| 93 | + if (token.isCancellationRequested) { |
| 94 | + return; |
| 95 | + } |
| 96 | + |
| 97 | + switch (response) { |
| 98 | + case yes: |
| 99 | + // User wants to override, continue with writing |
| 100 | + this.logger.info('User chose to override requirements.txt'); |
| 101 | + break; |
| 102 | + case no: |
| 103 | + // User doesn't want to override |
| 104 | + this.logger.info('User chose not to override requirements.txt'); |
| 105 | + return; |
| 106 | + case dontAskAgain: |
| 107 | + // User chose "Don't Ask Again", save preference and override this time |
| 108 | + await dontAskState.updateValue(true); |
| 109 | + this.logger.info('User chose "Don\'t Ask Again" for requirements.txt override'); |
| 110 | + break; |
| 111 | + default: |
| 112 | + // User dismissed the prompt (clicked X) |
| 113 | + this.logger.info('User dismissed requirements.txt override prompt'); |
| 114 | + return; |
| 115 | + } |
| 116 | + } else { |
| 117 | + // User previously selected "Don't Ask Again", automatically override |
| 118 | + this.logger.info( |
| 119 | + 'Automatically overriding requirements.txt (user previously selected "Don\'t Ask Again")' |
| 120 | + ); |
| 121 | + } |
| 122 | + } |
| 123 | + |
51 | 124 | // Write the requirements.txt file |
52 | 125 | await fs.promises.writeFile(requirementsPath, requirementsText, 'utf8'); |
53 | 126 |
|
|
0 commit comments