未验证 提交 e7c0af11 编写于 作者: M meganrogge

Revert "Revert "Merge pull request #122540 from microsoft/tyriar/122104""

This reverts commit 28a1bc2f.
上级 024251c2
......@@ -439,3 +439,5 @@ export interface ITerminalDimensionsOverride extends Readonly<ITerminalDimension
*/
forceExactSize?: boolean;
}
export type SafeConfigProvider = <T>(key: string) => T | undefined;
......@@ -8,6 +8,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
import { generateUuid } from 'vs/base/common/uuid';
import { getSystemShell, getSystemShellSync } from 'vs/base/node/shell';
import { ILogService } from 'vs/platform/log/common/log';
import { SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfigProvider, ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
......@@ -16,7 +17,7 @@ import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/work
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { BaseExtHostTerminalService, ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService';
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { ITerminalConfiguration, ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { detectAvailableProfiles } from 'vs/workbench/contrib/terminal/node/terminalProfiles';
import type * as vscode from 'vscode';
......@@ -75,14 +76,8 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
}
public getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string {
const fetchSetting = (key: string): string | undefined => {
return configProvider
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
.get<string>(key.substr(key.lastIndexOf('.') + 1));
};
return terminalEnvironment.getDefaultShell(
fetchSetting,
this._buildSafeConfigProvider(configProvider),
this._defaultShell ?? getSystemShellSync(platform.OS, process.env as platform.IProcessEnvironment),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir,
......@@ -93,13 +88,12 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
}
public getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string {
const fetchSetting = (key: string): string | string[] | undefined => {
return configProvider
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
.get<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
};
return terminalEnvironment.getDefaultShellArgs(fetchSetting, useAutomationShell, terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, process.env, this._variableResolver), this._logService);
return terminalEnvironment.getDefaultShellArgs(
this._buildSafeConfigProvider(configProvider),
useAutomationShell,
terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, process.env, this._variableResolver),
this._logService
);
}
private _registerListeners(): void {
......@@ -124,8 +118,8 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
}
public async $getAvailableProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]> {
const config = await (await this._extHostConfiguration.getConfigProvider()).getConfiguration().get('terminal.integrated');
return detectAvailableProfiles(configuredProfilesOnly, undefined, this._logService, config as ITerminalConfiguration, await this._variableResolverPromise, this._lastActiveWorkspace);
const safeConfigProvider = this._buildSafeConfigProvider(await this._extHostConfiguration.getConfigProvider());
return detectAvailableProfiles(configuredProfilesOnly, safeConfigProvider, undefined, this._logService, await this._variableResolverPromise, this._lastActiveWorkspace);
}
public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
......@@ -135,4 +129,17 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
args: this.getDefaultShellArgs(useAutomationShell, configProvider)
};
}
// TODO: Remove when workspace trust is enabled
private _buildSafeConfigProvider(configProvider: ExtHostConfigProvider): SafeConfigProvider {
const config = configProvider.getConfiguration();
return (key: string) => {
const isWorkspaceConfigAllowed = config.get('terminal.integrated.allowWorkspaceConfiguration');
if (isWorkspaceConfigAllowed) {
return config.get(key) as any;
}
const inspected = config.inspect(key);
return inspected?.globalValue || inspected?.defaultValue;
};
}
}
......@@ -16,7 +16,6 @@ import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IProductService } from 'vs/platform/product/common/productService';
import { IRemoteTerminalService, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { withNullAsUndefined } from 'vs/base/common/types';
......@@ -27,7 +26,7 @@ import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminal
import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder';
import { localize } from 'vs/nls';
import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/terminalStrings';
import { IProcessEnvironment, isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/platform';
import { IProcessEnvironment, OperatingSystem, OS } from 'vs/base/common/platform';
/** The amount of time to consider terminal errors to be related to the launch */
const LAUNCHING_DURATION = 500;
......@@ -117,7 +116,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
@ILogService private readonly _logService: ILogService,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IWorkbenchEnvironmentService private readonly _workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IProductService private readonly _productService: IProductService,
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
......@@ -335,8 +333,9 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
// Fetch any extension environment additions and apply them
private async _setupEnvVariableInfo(variableResolver: terminalEnvironment.VariableResolver | undefined, shellLaunchConfig: IShellLaunchConfig): Promise<IProcessEnvironment> {
const platformKey = isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux');
const envFromConfigValue = this._configurationService.getValue<ITerminalEnvironment | undefined>(`terminal.integrated.env.${platformKey}`);
// const platformKey = isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux');
// this._configurationService.getValue<ITerminalEnvironment | undefined>(`terminal.integrated.env.${platformKey}`);
const envFromConfigValue = this._terminalProfileResolverService.getSafeConfigValue('env', OS) as ITerminalEnvironment | undefined;
this._configHelper.showRecommendations(shellLaunchConfig);
const baseEnv = await (this._configHelper.config.inheritEnv
? this._terminalProfileResolverService.getShellEnvironment(this.remoteAuthority)
......
......@@ -123,7 +123,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
private _getRealDefaultProfile(sync: true, os: OperatingSystem): ITerminalProfile | undefined;
private _getRealDefaultProfile(sync: false, os: OperatingSystem): Promise<ITerminalProfile | undefined>;
private _getRealDefaultProfile(sync: boolean, os: OperatingSystem): ITerminalProfile | undefined | Promise<ITerminalProfile | undefined> {
const defaultProfileName = this._configurationService.getValue(`terminal.integrated.defaultProfile.${this._getOsKey(os)}`);
const defaultProfileName = this.getSafeConfigValue('defaultProfile', os);
if (defaultProfileName && typeof defaultProfileName === 'string') {
if (sync) {
const profiles = this._terminalService.availableProfiles;
......@@ -138,10 +138,10 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
private async _getFallbackDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise<ITerminalProfile> {
let executable: string;
let args: string | string[] | undefined;
const shellSetting = this._configurationService.getValue(`terminal.integrated.shell.${this._getOsKey(options.os)}`);
const shellSetting = this.getSafeConfigValue('shell', options.os);
if (this._isValidShell(shellSetting)) {
executable = shellSetting;
const shellArgsSetting = this._configurationService.getValue(`terminal.integrated.shellArgs.${this._getOsKey(options.os)}`);
const shellArgsSetting = this.getSafeConfigValue('shellArgs', options.os);
if (this._isValidShellArgs(shellArgsSetting, options.os)) {
args = shellArgsSetting;
}
......@@ -170,7 +170,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
}
private _getAutomationShellProfile(options: IShellLaunchConfigResolveOptions): ITerminalProfile | undefined {
const automationShell = this._configurationService.getValue(`terminal.integrated.automationShell.${this._getOsKey(options.os)}`);
const automationShell = this.getSafeConfigValue('automationShell', options.os);
if (!automationShell || typeof automationShell !== 'string') {
return undefined;
}
......@@ -274,6 +274,28 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
}
return false;
}
// TODO: Remove when workspace trust is enabled
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined {
return this.getSafeConfigValueFullKey(`terminal.integrated.${key}.${this._getOsKey(os)}`);
}
getSafeConfigValueFullKey(key: string): unknown | undefined {
const isWorkspaceConfigAllowed = this._configurationService.getValue('terminal.integrated.allowWorkspaceConfiguration');
if (isWorkspaceConfigAllowed) {
return this._configurationService.getValue(key);
} else {
const config = this._configurationService.inspect(key);
const value = config.user?.value || config.default?.value;
// Clone if needed to allow extensibility
if (Array.isArray(value)) {
return value.slice();
}
if (typeof value === 'object') {
return { ...value };
}
return value;
}
}
}
export class BrowserTerminalProfileResolverService extends BaseTerminalProfileResolverService {
......
......@@ -19,7 +19,7 @@ import { Schemas } from 'vs/base/common/network';
import { ILabelService } from 'vs/platform/label/common/label';
import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { IProcessDataEvent, IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal';
import { ITerminalConfiguration, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalConfiguration, ITerminalProfileResolverService, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform';
......@@ -125,6 +125,7 @@ export class RemoteTerminalChannelClient {
@IConfigurationResolverService private readonly _resolverService: IConfigurationResolverService,
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
@IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
@ILogService private readonly _logService: ILogService,
@IEditorService private readonly _editorService: IEditorService,
@ILabelService private readonly _labelService: ILabelService,
......@@ -140,20 +141,20 @@ export class RemoteTerminalChannelClient {
const terminalConfig = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
const configuration: ICompleteTerminalConfiguration = {
'terminal.integrated.automationShell.windows': this._configurationService.getValue('terminal.integrated.automationShell.windows'),
'terminal.integrated.automationShell.osx': this._configurationService.getValue('terminal.integrated.automationShell.osx'),
'terminal.integrated.automationShell.linux': this._configurationService.getValue('terminal.integrated.automationShell.linux'),
'terminal.integrated.shell.windows': this._configurationService.getValue('terminal.integrated.shell.windows'),
'terminal.integrated.shell.osx': this._configurationService.getValue('terminal.integrated.shell.osx'),
'terminal.integrated.shell.linux': this._configurationService.getValue('terminal.integrated.shell.linux'),
'terminal.integrated.shellArgs.windows': this._configurationService.getValue('terminal.integrated.shellArgs.windows'),
'terminal.integrated.shellArgs.osx': this._configurationService.getValue('terminal.integrated.shellArgs.osx'),
'terminal.integrated.shellArgs.linux': this._configurationService.getValue('terminal.integrated.shellArgs.linux'),
'terminal.integrated.env.windows': this._configurationService.getValue('terminal.integrated.env.windows'),
'terminal.integrated.env.osx': this._configurationService.getValue('terminal.integrated.env.osx'),
'terminal.integrated.env.linux': this._configurationService.getValue('terminal.integrated.env.linux'),
'terminal.integrated.automationShell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.automationShell.windows') as string,
'terminal.integrated.automationShell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.automationShell.osx') as string,
'terminal.integrated.automationShell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.automationShell.linux') as string,
'terminal.integrated.shell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shell.windows') as string,
'terminal.integrated.shell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shell.osx') as string,
'terminal.integrated.shell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shell.linux') as string,
'terminal.integrated.shellArgs.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shellArgs.windows') as string | string[],
'terminal.integrated.shellArgs.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shellArgs.osx') as string | string[],
'terminal.integrated.shellArgs.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.shellArgs.linux') as string | string[],
'terminal.integrated.env.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.env.windows') as ITerminalEnvironment,
'terminal.integrated.env.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.env.osx') as ITerminalEnvironment,
'terminal.integrated.env.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.env.linux') as ITerminalEnvironment,
'terminal.integrated.inheritEnv': terminalConfig.inheritEnv,
'terminal.integrated.cwd': terminalConfig.cwd,
'terminal.integrated.cwd': this._terminalProfileResolverService.getSafeConfigValueFullKey('terminal.integrated.cwd') as string,
'terminal.integrated.detectLocale': terminalConfig.detectLocale
};
......
......@@ -100,6 +100,10 @@ export interface ITerminalProfileResolverService {
getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string>;
getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]>;
getShellEnvironment(remoteAuthority: string | undefined): Promise<IProcessEnvironment>;
// TODO: Remove when workspace trust is enabled
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined;
getSafeConfigValueFullKey(key: string): unknown | undefined;
}
export interface IShellLaunchConfigResolveOptions {
......@@ -195,6 +199,7 @@ export interface ITerminalConfiguration {
focusMode: 'singleClick' | 'doubleClick';
},
bellDuration: number;
allowWorkspaceConfiguration: boolean;
}
export const DEFAULT_LOCAL_ECHO_EXCLUDE: ReadonlyArray<string> = ['vim', 'vi', 'nano', 'tmux'];
......
......@@ -60,8 +60,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.automationShell.linux': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize({
key: 'terminal.integrated.automationShell.linux',
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
......@@ -71,8 +69,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.automationShell.osx': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize({
key: 'terminal.integrated.automationShell.osx',
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
......@@ -82,8 +78,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.automationShell.windows': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize({
key: 'terminal.integrated.automationShell.windows',
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
......@@ -93,8 +87,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.shellArgs.linux': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize('terminal.integrated.shellArgs.linux', "The command line arguments to use when on the Linux terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."),
type: 'array',
items: {
......@@ -105,8 +97,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.shellArgs.osx': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize('terminal.integrated.shellArgs.osx', "The command line arguments to use when on the macOS terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."),
type: 'array',
items: {
......@@ -120,8 +110,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.shellArgs.windows': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."),
'anyOf': [
{
......@@ -141,8 +129,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.profiles.windows': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize(
{
key: 'terminal.integrated.profiles.windows',
......@@ -203,8 +189,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.profiles.osx': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize(
{
key: 'terminal.integrated.profile.osx',
......@@ -242,8 +226,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.profiles.linux': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize(
{
key: 'terminal.integrated.profile.linux',
......@@ -511,6 +493,7 @@ export const terminalConfiguration: IConfigurationNode = {
description: localize('terminal.integrated.rightClickBehavior', "Controls how terminal reacts to right click.")
},
'terminal.integrated.cwd': {
restricted: true,
description: localize('terminal.integrated.cwd', "An explicit start path where the terminal will be launched, this is used as the current working directory (cwd) for the shell process. This may be particularly useful in workspace settings if the root directory is not a convenient cwd."),
type: 'string',
default: undefined
......@@ -550,8 +533,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.env.osx': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize('terminal.integrated.env.osx', "Object with environment variables that will be added to the VS Code process to be used by the terminal on macOS. Set to `null` to delete the environment variable."),
type: 'object',
additionalProperties: {
......@@ -561,8 +542,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.env.linux': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize('terminal.integrated.env.linux', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Linux. Set to `null` to delete the environment variable."),
type: 'object',
additionalProperties: {
......@@ -572,8 +551,6 @@ export const terminalConfiguration: IConfigurationNode = {
},
'terminal.integrated.env.windows': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: localize('terminal.integrated.env.windows', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Windows. Set to `null` to delete the environment variable."),
type: 'object',
additionalProperties: {
......@@ -683,6 +660,12 @@ export const terminalConfiguration: IConfigurationNode = {
description: localize('terminal.integrated.enablePersistentSessions', "Persist terminal sessions for the workspace across window reloads."),
type: 'boolean',
default: true
},
'terminal.integrated.allowWorkspaceConfiguration': {
scope: ConfigurationScope.APPLICATION,
description: localize('terminal.integrated.allowWorkspaceConfiguration', "Allows shell and profile settings to be pick up from a workspace."),
type: 'boolean',
default: false
}
}
};
......@@ -696,8 +679,6 @@ function getTerminalShellConfigurationStub(linux: string, osx: string, windows:
properties: {
'terminal.integrated.shell.linux': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: linux,
type: ['string', 'null'],
default: null,
......@@ -705,8 +686,6 @@ function getTerminalShellConfigurationStub(linux: string, osx: string, windows:
},
'terminal.integrated.shell.osx': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: osx,
type: ['string', 'null'],
default: null,
......@@ -714,8 +693,6 @@ function getTerminalShellConfigurationStub(linux: string, osx: string, windows:
},
'terminal.integrated.shell.windows': {
restricted: true,
// TODO: Remove when workspace trust is enabled by default
scope: ConfigurationScope.APPLICATION,
markdownDescription: windows,
type: ['string', 'null'],
default: null,
......
......@@ -7,27 +7,43 @@ import * as fs from 'fs';
import { normalize, basename, delimiter } from 'vs/base/common/path';
import { enumeratePowerShellInstallations } from 'vs/base/node/powershell';
import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment';
import { ITerminalConfiguration, ITerminalProfile, ITerminalProfileObject, ProfileSource } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalProfile, ITerminalProfileObject, ProfileSource } from 'vs/workbench/contrib/terminal/common/terminal';
import * as cp from 'child_process';
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ILogService } from 'vs/platform/log/common/log';
import * as pfs from 'vs/base/node/pfs';
import { ITerminalEnvironment } from 'vs/platform/terminal/common/terminal';
import { ITerminalEnvironment, SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
import { Codicon } from 'vs/base/common/codicons';
import { isMacintosh, isWindows } from 'vs/base/common/platform';
let profileSources: Map<string, IPotentialTerminalProfile> | undefined;
export function detectAvailableProfiles(configuredProfilesOnly: boolean, fsProvider?: IFsProvider, logService?: ILogService, config?: ITerminalConfiguration, variableResolver?: ExtHostVariableResolverService, workspaceFolder?: IWorkspaceFolder, testPaths?: string[]): Promise<ITerminalProfile[]> {
export function detectAvailableProfiles(configuredProfilesOnly: boolean, safeConfigProvider: SafeConfigProvider, fsProvider?: IFsProvider, logService?: ILogService, variableResolver?: ExtHostVariableResolverService, workspaceFolder?: IWorkspaceFolder, testPaths?: string[]): Promise<ITerminalProfile[]> {
fsProvider = fsProvider || {
existsFile: pfs.SymlinkSupport.existsFile,
readFile: fs.promises.readFile
};
if (isWindows) {
return detectAvailableWindowsProfiles(configuredProfilesOnly, fsProvider, logService, config?.useWslProfiles, config?.profiles.windows, variableResolver, workspaceFolder);
return detectAvailableWindowsProfiles(
configuredProfilesOnly,
fsProvider,
logService,
safeConfigProvider('terminal.integrated.useWslProfiles') || true,
safeConfigProvider('terminal.integrated.profiles.windows'),
variableResolver,
workspaceFolder
);
}
return detectAvailableUnixProfiles(fsProvider, logService, configuredProfilesOnly, isMacintosh ? config?.profiles.osx : config?.profiles.linux, testPaths, variableResolver, workspaceFolder);
return detectAvailableUnixProfiles(
fsProvider,
logService,
configuredProfilesOnly,
safeConfigProvider(`terminal.integrated.profiles.${isMacintosh ? 'osx' : 'linux'}`),
testPaths,
variableResolver,
workspaceFolder
);
}
async function detectAvailableWindowsProfiles(configuredProfilesOnly: boolean, fsProvider: IFsProvider, logService?: ILogService, useWslProfiles?: boolean, configProfiles?: { [key: string]: ITerminalProfileObject }, variableResolver?: ExtHostVariableResolverService, workspaceFolder?: IWorkspaceFolder): Promise<ITerminalProfile[]> {
......
......@@ -5,6 +5,7 @@
import { deepStrictEqual, fail, ok, strictEqual } from 'assert';
import { isWindows } from 'vs/base/common/platform';
import { SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
import { ITerminalConfiguration, ITerminalProfile, ITerminalProfiles, ProfileSource } from 'vs/workbench/contrib/terminal/common/terminal';
import { detectAvailableProfiles, IFsProvider } from 'vs/workbench/contrib/terminal/node/terminalProfiles';
......@@ -25,6 +26,18 @@ function profilesEqual(actualProfiles: ITerminalProfile[], expectedProfiles: ITe
}
}
function buildTestSafeConfigProvider(config: ITestTerminalConfig): SafeConfigProvider {
return (key: string) => {
switch (key) {
case 'terminal.integrated.profiles.linux': return config.profiles.linux as any;
case 'terminal.integrated.profiles.osx': return config.profiles.osx as any;
case 'terminal.integrated.profiles.windows': return config.profiles.windows as any;
case 'terminal.integrated.useWslProfiles': return config.useWslProfiles;
default: throw new Error('Unexpected config key');
}
};
}
suite('Workbench - TerminalProfiles', () => {
suite('detectAvailableProfiles', () => {
if (isWindows) {
......@@ -42,7 +55,7 @@ suite('Workbench - TerminalProfiles', () => {
},
useWslProfiles: false
};
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, config as ITerminalConfiguration, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(config), fsProvider, undefined, undefined, undefined);
const expected = [
{ profileName: 'Git Bash', path: 'C:\\Program Files\\Git\\bin\\bash.exe', args: ['--login'] }
];
......@@ -62,7 +75,7 @@ suite('Workbench - TerminalProfiles', () => {
},
useWslProfiles: false
};
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, config as ITerminalConfiguration, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(config), fsProvider, undefined, undefined, undefined);
const expected = [
{ profileName: 'PowerShell NoProfile', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', overrideName: true, args: ['-NoProfile'] }
];
......@@ -82,7 +95,7 @@ suite('Workbench - TerminalProfiles', () => {
},
useWslProfiles: false
};
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, config as ITerminalConfiguration, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(config), fsProvider, undefined, undefined, undefined);
const expected = [{ profileName: 'Git Bash', path: 'C:\\Program Files\\Git\\bin\\bash.exe', args: [], isAutoDetected: undefined, overrideName: undefined }];
profilesEqual(profiles, expected);
});
......@@ -104,7 +117,7 @@ suite('Workbench - TerminalProfiles', () => {
'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe',
'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
]);
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, pwshSourceConfig, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined);
const expected = [
{ profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe' }
];
......@@ -117,7 +130,7 @@ suite('Workbench - TerminalProfiles', () => {
'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe',
'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
]);
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, pwshSourceConfig, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined);
const expected = [
{ profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe' }
];
......@@ -128,7 +141,7 @@ suite('Workbench - TerminalProfiles', () => {
'C:\\Windows\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe',
'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
]);
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, pwshSourceConfig, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined);
strictEqual(profiles.length, 1);
strictEqual(profiles[0].profileName, 'PowerShell');
});
......@@ -172,7 +185,7 @@ suite('Workbench - TerminalProfiles', () => {
'/bin/fakeshell1',
'/bin/fakeshell3'
]);
const profiles = await detectAvailableProfiles(true, fsProvider, undefined, absoluteConfig, undefined, undefined);
const profiles = await detectAvailableProfiles(true, buildTestSafeConfigProvider(absoluteConfig), fsProvider, undefined, undefined, undefined);
const expected: ITerminalProfile[] = [
{ profileName: 'fakeshell1', path: '/bin/fakeshell1' },
{ profileName: 'fakeshell3', path: '/bin/fakeshell3' }
......@@ -184,7 +197,7 @@ suite('Workbench - TerminalProfiles', () => {
'/bin/fakeshell1',
'/bin/fakeshell3'
], '/bin/fakeshell1\n/bin/fakeshell3');
const profiles = await detectAvailableProfiles(false, fsProvider, undefined, onPathConfig, undefined, undefined);
const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(onPathConfig), fsProvider, undefined, undefined, undefined);
const expected: ITerminalProfile[] = [
{ profileName: 'fakeshell1', path: 'fakeshell1' },
{ profileName: 'fakeshell3', path: 'fakeshell3' }
......@@ -196,7 +209,7 @@ suite('Workbench - TerminalProfiles', () => {
const fsProvider = createFsProvider([
'/bin/fakeshell1'
], '/bin/fakeshell1\n/bin/fakeshell3');
const profiles = await detectAvailableProfiles(false, fsProvider, undefined, onPathConfig, undefined, undefined);
const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(onPathConfig), fsProvider, undefined, undefined, undefined);
const expected: ITerminalProfile[] = [
{ profileName: 'fakeshell1', path: 'fakeshell1' }
];
......
......@@ -330,6 +330,8 @@ class SimpleTerminalProfileResolverService implements ITerminalProfileResolverSe
getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string> { throw new Error('Method not implemented.'); }
getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]> { throw new Error('Method not implemented.'); }
getShellEnvironment(remoteAuthority: string | undefined): Promise<IProcessEnvironment> { throw new Error('Method not implemented.'); }
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { throw new Error('Method not implemented.'); }
getSafeConfigValueFullKey(key: string): unknown | undefined { throw new Error('Method not implemented.'); }
}
registerSingleton(ITerminalProfileResolverService, SimpleTerminalProfileResolverService);
......
......@@ -1570,6 +1570,8 @@ export class TestTerminalProfileResolverService implements ITerminalProfileResol
async getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise<string> { return '/default'; }
async getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise<string | string[]> { return []; }
async getShellEnvironment(): Promise<IProcessEnvironment> { return process.env; }
getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { return undefined; }
getSafeConfigValueFullKey(key: string): unknown | undefined { return undefined; }
}
export class TestLocalTerminalService implements ILocalTerminalService {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册