Bring back expose shell's environment - bash (#237844)

* bring back expose shell's environment bash

* I want to see why the test is failing the build

* Pass test, disable it until we enable for stable

---------

Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
This commit is contained in:
Anthony Kim
2025-01-14 13:15:46 -05:00
committed by GitHub
parent 2174db3d18
commit 35b2db3ed1
5 changed files with 113 additions and 1 deletions

View File

@@ -87,6 +87,23 @@ import { assertNoRpc } from '../utils';
await closeTerminalAsync(terminal);
});
if (platform() === 'darwin' || platform() === 'linux') {
// TODO: Enable when this is enabled in stable, otherwise it will break the stable product builds only
test.skip('Test if env is set', async () => {
const { shellIntegration } = await createTerminalAndWaitForShellIntegration();
await new Promise<void>(r => {
disposables.push(window.onDidChangeTerminalShellIntegration(e => {
if (e.shellIntegration.env) {
r();
}
}));
});
ok(shellIntegration.env);
ok(shellIntegration.env.PATH);
ok(shellIntegration.env.PATH.length > 0, 'env.PATH should have a length greater than 0');
});
}
test('execution events should fire in order when a command runs', async () => {
const { terminal, shellIntegration } = await createTerminalAndWaitForShellIntegration();
const events: string[] = [];

View File

@@ -155,6 +155,9 @@ export interface IShellEnvDetectionCapability {
readonly onDidChangeEnv: Event<Map<string, string>>;
get env(): Map<string, string>;
setEnvironment(envs: { [key: string]: string | undefined } | undefined, isTrusted: boolean): void;
startEnvironmentSingleVar(isTrusted: boolean): void;
setEnvironmentSingleVar(key: string, value: string | undefined, isTrusted: boolean): void;
endEnvironmentSingleVar(isTrusted: boolean): void;
}
export const enum CommandInvalidationReason {

View File

@@ -11,7 +11,8 @@ import { equals } from '../../../../base/common/objects.js';
export class ShellEnvDetectionCapability extends Disposable implements IShellEnvDetectionCapability {
readonly type = TerminalCapability.ShellEnvDetection;
private readonly _env: Map<string, string> = new Map();
private _pendingEnv: Map<string, string> | undefined;
private _env: Map<string, string> = new Map();
get env(): Map<string, string> { return this._env; }
private readonly _onDidChangeEnv = this._register(new Emitter<Map<string, string>>());
@@ -36,4 +37,30 @@ export class ShellEnvDetectionCapability extends Disposable implements IShellEnv
// Convert to event and fire event
this._onDidChangeEnv.fire(this._env);
}
startEnvironmentSingleVar(isTrusted: boolean): void {
if (!isTrusted) {
return;
}
this._pendingEnv = new Map();
}
setEnvironmentSingleVar(key: string, value: string | undefined, isTrusted: boolean): void {
if (!isTrusted) {
return;
}
if (key !== undefined && value !== undefined) {
this._pendingEnv?.set(key, value);
}
}
endEnvironmentSingleVar(isTrusted: boolean): void {
if (!isTrusted) {
return;
}
if (!this._pendingEnv) {
return;
}
this._env = this._pendingEnv;
this._pendingEnv = undefined;
this._onDidChangeEnv.fire(this._env);
}
}

View File

@@ -239,6 +239,34 @@ const enum VSCodeOscPt {
*/
EnvJson = 'EnvJson',
/**
* The start of the collecting user's environment variables individually.
* Clears any environment residuals in previous sessions.
*
* Format: `OSC 633 ; EnvSingleStart ; <Nonce>`
*
* WARNING: This sequence is unfinalized, DO NOT use this in your shell integration script.
*/
EnvSingleStart = 'EnvSingleStart',
/**
* Sets an entry of single environment variable to transactional pending map of environment variables.
*
* Format: `OSC 633 ; EnvSingleEntry ; <EnvironmentKey> ; <EnvironmentValue> ; <Nonce>`
*
* WARNING: This sequence is unfinalized, DO NOT use this in your shell integration script.
*/
EnvSingleEntry = 'EnvSingleEntry',
/**
* The end of the collecting user's environment variables individually.
* Clears any pending environment variables and fires an event that contains user's environment.
*
* Format: `OSC 633 ; EnvSingleEnd ; <Nonce>`
*
* WARNING: This sequence is unfinalized, DO NOT use this in your shell integration script.
*/
EnvSingleEnd = 'EnvSingleEnd'
}
/**
@@ -446,6 +474,24 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
}
return true;
}
case VSCodeOscPt.EnvSingleStart: {
this._createOrGetShellEnvDetection().startEnvironmentSingleVar(args[0] === this._nonce);
return true;
}
case VSCodeOscPt.EnvSingleEntry: {
const arg0 = args[0];
const arg1 = args[1];
const arg2 = args[2];
if (arg0 !== undefined && arg1 !== undefined) {
const env = deserializeMessage(arg1);
this._createOrGetShellEnvDetection().setEnvironmentSingleVar(arg0, env, arg2 === this._nonce);
}
return true;
}
case VSCodeOscPt.EnvSingleEnd: {
this._createOrGetShellEnvDetection().endEnvironmentSingleVar(args[0] === this._nonce);
return true;
}
case VSCodeOscPt.RightPromptStart: {
this._createOrGetCommandDetection(this._terminal).handleRightPromptStart();
return true;

View File

@@ -214,6 +214,17 @@ __vsc_update_cwd() {
builtin printf '\e]633;P;Cwd=%s\a' "$(__vsc_escape_value "$__vsc_cwd")"
}
__vsc_update_env() {
builtin printf '\e]633;EnvSingleStart;%s;\a' $__vsc_nonce
for var in $(compgen -v); do
if printenv "$var" >/dev/null 2>&1; then
value=$(builtin printf '%s' "${!var}")
builtin printf '\e]633;EnvSingleEntry;%s;%s;%s\a' "$var" "$(__vsc_escape_value "$value")" $__vsc_nonce
fi
done
builtin printf '\e]633;EnvSingleEnd;%s;\a' $__vsc_nonce
}
__vsc_command_output_start() {
if [[ -z "${__vsc_first_prompt-}" ]]; then
builtin return
@@ -240,6 +251,10 @@ __vsc_command_complete() {
builtin printf '\e]633;D;%s\a' "$__vsc_status"
fi
__vsc_update_cwd
if [ "$__vsc_stable" = "0" ]; then
__vsc_update_env
fi
}
__vsc_update_prompt() {
# in command execution
@@ -269,6 +284,10 @@ __vsc_precmd() {
fi
__vsc_first_prompt=1
__vsc_update_prompt
if [ "$__vsc_stable" = "0" ]; then
__vsc_update_env
fi
}
__vsc_preexec() {