@@ -33,6 +33,7 @@ import { defaultShells } from './service';
33
33
import { IEnvironmentActivationService } from './types' ;
34
34
import { EnvironmentType } from '../../pythonEnvironments/info' ;
35
35
import { getSearchPathEnvVarNames } from '../../common/utils/exec' ;
36
+ import { EnvironmentVariables } from '../../common/variables/types' ;
36
37
37
38
@injectable ( )
38
39
export class TerminalEnvVarCollectionService implements IExtensionActivationService {
@@ -45,7 +46,10 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ
45
46
46
47
private registeredOnce = false ;
47
48
48
- private previousEnvVars = _normCaseKeys ( process . env ) ;
49
+ /**
50
+ * Carries default environment variables for the currently selected shell.
51
+ */
52
+ private processEnvVars : EnvironmentVariables | undefined ;
49
53
50
54
constructor (
51
55
@inject ( IPlatformService ) private readonly platform : IPlatformService ,
@@ -90,6 +94,7 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ
90
94
this . applicationEnvironment . onDidChangeShell (
91
95
async ( shell : string ) => {
92
96
this . showProgress ( ) ;
97
+ this . processEnvVars = undefined ;
93
98
// Pass in the shell where known instead of relying on the application environment, because of bug
94
99
// on VSCode: https://github.com/microsoft/vscode/issues/160694
95
100
await this . _applyCollection ( undefined , shell ) . ignoreErrors ( ) ;
@@ -106,6 +111,9 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ
106
111
public async _applyCollection ( resource : Resource , shell = this . applicationEnvironment . shell ) : Promise < void > {
107
112
const workspaceFolder = this . getWorkspaceFolder ( resource ) ;
108
113
const settings = this . configurationService . getSettings ( resource ) ;
114
+ const envVarCollection = this . getEnvironmentVariableCollection ( workspaceFolder ) ;
115
+ // Clear any previously set env vars from collection.
116
+ envVarCollection . clear ( ) ;
109
117
if ( ! settings . terminal . activateEnvironment ) {
110
118
traceVerbose ( 'Activating environments in terminal is disabled for' , resource ?. fsPath ) ;
111
119
return ;
@@ -116,7 +124,6 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ
116
124
undefined ,
117
125
shell ,
118
126
) ;
119
- const envVarCollection = this . getEnvironmentVariableCollection ( workspaceFolder ) ;
120
127
if ( ! env ) {
121
128
const shellType = identifyShellFromShellPath ( shell ) ;
122
129
const defaultShell = defaultShells [ this . platform . osType ] ;
@@ -126,32 +133,38 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ
126
133
await this . _applyCollection ( resource , defaultShell ?. shell ) ;
127
134
return ;
128
135
}
129
- envVarCollection . clear ( ) ;
130
- this . previousEnvVars = _normCaseKeys ( process . env ) ;
136
+ this . processEnvVars = undefined ;
131
137
return ;
132
138
}
133
- const previousEnv = this . previousEnvVars ;
134
- this . previousEnvVars = env ;
139
+ if ( ! this . processEnvVars ) {
140
+ this . processEnvVars = await this . environmentActivationService . getProcessEnvironmentVariables (
141
+ resource ,
142
+ shell ,
143
+ ) ;
144
+ }
145
+ const processEnv = this . processEnvVars ;
135
146
Object . keys ( env ) . forEach ( ( key ) => {
147
+ if ( shouldSkip ( key ) ) {
148
+ return ;
149
+ }
136
150
const value = env [ key ] ;
137
- const prevValue = previousEnv [ key ] ;
151
+ const prevValue = processEnv [ key ] ;
138
152
if ( prevValue !== value ) {
139
153
if ( value !== undefined ) {
154
+ if ( key === 'PS1' ) {
155
+ traceVerbose ( `Prepending environment variable ${ key } in collection with ${ value } ` ) ;
156
+ envVarCollection . prepend ( key , value , {
157
+ applyAtShellIntegration : true ,
158
+ applyAtProcessCreation : false ,
159
+ } ) ;
160
+ return ;
161
+ }
140
162
traceVerbose ( `Setting environment variable ${ key } in collection to ${ value } ` ) ;
141
163
envVarCollection . replace ( key , value , { applyAtShellIntegration : true } ) ;
142
- } else {
143
- traceVerbose ( `Clearing environment variable ${ key } from collection` ) ;
144
- envVarCollection . delete ( key ) ;
145
164
}
146
165
}
147
166
} ) ;
148
- Object . keys ( previousEnv ) . forEach ( ( key ) => {
149
- // If the previous env var is not in the current env, clear it from collection.
150
- if ( ! ( key in env ) ) {
151
- traceVerbose ( `Clearing environment variable ${ key } from collection` ) ;
152
- envVarCollection . delete ( key ) ;
153
- }
154
- } ) ;
167
+
155
168
const displayPath = this . pathUtils . getDisplayName ( settings . pythonPath , workspaceFolder ?. uri . fsPath ) ;
156
169
const description = new MarkdownString ( `${ Interpreters . activateTerminalDescription } \`${ displayPath } \`` ) ;
157
170
envVarCollection . description = description ;
@@ -224,13 +237,6 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ
224
237
}
225
238
}
226
239
227
- export function _normCaseKeys ( env : NodeJS . ProcessEnv ) : NodeJS . ProcessEnv {
228
- const result : NodeJS . ProcessEnv = { } ;
229
- Object . keys ( env ) . forEach ( ( key ) => {
230
- // `os.environ` script used to get env vars normalizes keys to upper case:
231
- // https://github.com/python/cpython/issues/101754
232
- // So convert `process.env` keys to upper case to match.
233
- result [ key . toUpperCase ( ) ] = env [ key ] ;
234
- } ) ;
235
- return result ;
240
+ function shouldSkip ( env : string ) {
241
+ return [ '_' , 'SHLVL' ] . includes ( env ) ;
236
242
}
0 commit comments