diff --git a/src/api.ts b/src/api.ts index 53790aa1..f2258ccd 100644 --- a/src/api.ts +++ b/src/api.ts @@ -379,7 +379,7 @@ export interface EnvironmentManager { quickCreateConfig?(): QuickCreateConfig | undefined; /** - * Creates a new Python environment within the specified scope. + * Creates a new Python environment within the specified scope. Create should support adding a .gitignore file if it creates a folder within the workspace. * @param scope - The scope within which to create the environment. * @param options - Optional parameters for creating the Python environment. * @returns A promise that resolves to the created Python environment, or undefined if creation failed. diff --git a/src/managers/builtin/venvManager.ts b/src/managers/builtin/venvManager.ts index 122d5e8c..c1464d87 100644 --- a/src/managers/builtin/venvManager.ts +++ b/src/managers/builtin/venvManager.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs/promises'; import * as path from 'path'; import { EventEmitter, l10n, LogOutputChannel, MarkdownString, ProgressLocation, ThemeIcon, Uri } from 'vscode'; import { @@ -20,6 +21,7 @@ import { } from '../../api'; import { PYTHON_EXTENSION_ID } from '../../common/constants'; import { VenvManagerStrings } from '../../common/localize'; +import { traceError } from '../../common/logging'; import { createDeferred, Deferred } from '../../common/utils/deferred'; import { showErrorMessage, withProgress } from '../../common/window.apis'; import { findParentIfFile } from '../../features/envCommands'; @@ -162,6 +164,17 @@ export class VenvManager implements EnvironmentManager { } if (environment) { this.addEnvironment(environment, true); + + // Add .gitignore to the .venv folder + try { + const venvDir = environment.environmentPath.fsPath; + const gitignorePath = path.join(venvDir, '.gitignore'); + await fs.writeFile(gitignorePath, '*\n', { flag: 'w' }); + } catch (err) { + traceError( + `Failed to create .gitignore in venv: ${err instanceof Error ? err.message : String(err)}`, + ); + } } return environment; } finally { diff --git a/src/managers/conda/condaEnvManager.ts b/src/managers/conda/condaEnvManager.ts index 229ad4b1..c044afce 100644 --- a/src/managers/conda/condaEnvManager.ts +++ b/src/managers/conda/condaEnvManager.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs-extra'; import * as path from 'path'; import { Disposable, EventEmitter, l10n, LogOutputChannel, MarkdownString, ProgressLocation, Uri } from 'vscode'; import { @@ -19,6 +20,7 @@ import { SetEnvironmentScope, } from '../../api'; import { CondaStrings } from '../../common/localize'; +import { traceError } from '../../common/logging'; import { createDeferred, Deferred } from '../../common/utils/deferred'; import { showErrorMessage, withProgress } from '../../common/window.apis'; import { NativePythonFinder } from '../common/nativePythonFinder'; @@ -167,6 +169,20 @@ export class CondaEnvManager implements EnvironmentManager, Disposable { } if (result) { this.addEnvironment(result); + + // If the environment is inside the workspace, add a .gitignore file + try { + const projectUris = this.api.getPythonProjects().map((p) => p.uri.fsPath); + const envPath = result.environmentPath?.fsPath; + if (envPath && projectUris.some((root) => envPath.startsWith(root))) { + const gitignorePath = path.join(envPath, '.gitignore'); + await fs.writeFile(gitignorePath, '*\n', { flag: 'w' }); + } + } catch (err) { + traceError( + `Failed to create .gitignore in conda env: ${err instanceof Error ? err.message : String(err)}`, + ); + } } return result;