Merge from vscode 112fa76c775ecb79ac2c9e9e5dba0d711d523543 (#6388)

This commit is contained in:
Anthony Dresser
2019-07-17 01:07:27 -07:00
committed by GitHub
parent 43bd7268e8
commit 2d73b6afb1
59 changed files with 652 additions and 638 deletions

View File

@@ -8,12 +8,15 @@ import * as platform from 'vs/base/common/platform';
import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal';
import Severity from 'vs/base/common/severity';
import { Terminal as XTermTerminal } from 'xterm';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal';
import { Emitter, Event } from 'vs/base/common/event';
import { basename } from 'vs/base/common/path';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
const MINIMUM_FONT_SIZE = 6;
const MAXIMUM_FONT_SIZE = 25;
@@ -35,7 +38,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
public constructor(
private readonly _linuxDistro: LinuxDistro,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IConfigurationService private readonly _workspaceConfigurationService: IConfigurationService,
@IExtensionManagementService private readonly _extensionManagementService: IExtensionManagementService,
@INotificationService private readonly _notificationService: INotificationService,
@IStorageService private readonly _storageService: IStorageService
) {
@@ -174,9 +177,9 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
public checkWorkspaceShellPermissions(osOverride: platform.OperatingSystem = platform.OS): boolean {
// Check whether there is a workspace setting
const platformKey = osOverride === platform.OperatingSystem.Windows ? 'windows' : osOverride === platform.OperatingSystem.Macintosh ? 'osx' : 'linux';
const shellConfigValue = this._workspaceConfigurationService.inspect<string>(`terminal.integrated.shell.${platformKey}`);
const shellArgsConfigValue = this._workspaceConfigurationService.inspect<string[]>(`terminal.integrated.shellArgs.${platformKey}`);
const envConfigValue = this._workspaceConfigurationService.inspect<{ [key: string]: string }>(`terminal.integrated.env.${platformKey}`);
const shellConfigValue = this._configurationService.inspect<string>(`terminal.integrated.shell.${platformKey}`);
const shellArgsConfigValue = this._configurationService.inspect<string[]>(`terminal.integrated.shellArgs.${platformKey}`);
const envConfigValue = this._configurationService.inspect<{ [key: string]: string }>(`terminal.integrated.env.${platformKey}`);
// Check if workspace setting exists and whether it's whitelisted
let isWorkspaceShellAllowed: boolean | undefined = false;
@@ -244,4 +247,48 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
}
return r;
}
private readonly NO_RECOMMENDATIONS_KEY = 'terminalConfigHelper/launchRecommendationsIgnore';
private recommendationsShown = false;
public async showRecommendations(shellLaunchConfig: IShellLaunchConfig): Promise<void> {
if (this.recommendationsShown) {
return;
}
this.recommendationsShown = true;
if (platform.isWindows && shellLaunchConfig.executable && basename(shellLaunchConfig.executable).toLowerCase() === 'wsl.exe') {
if (this._storageService.getBoolean(this.NO_RECOMMENDATIONS_KEY, StorageScope.WORKSPACE, false)) {
return;
}
if (! await this.isExtensionInstalled('ms-vscode-remote.remote-wsl')) {
this._notificationService.prompt(
Severity.Info,
nls.localize(
'useWslExtension.title',
"Check out the 'Visual Studio Code Remote - WSL' extension for a great development experience in WSL. Click [here]({0}) to learn more.",
'https://go.microsoft.com/fwlink/?linkid=2097212'
),
[
{
label: nls.localize('doNotShowAgain', "Don't Show Again"),
run: () => {
this._storageService.store(this.NO_RECOMMENDATIONS_KEY, true, StorageScope.WORKSPACE);
}
}
],
{
sticky: true
}
);
}
}
}
private isExtensionInstalled(id: string): Promise<boolean> {
return this._extensionManagementService.getInstalled(ExtensionType.User).then(extensions => {
return extensions.some(e => e.identifier.id === id);
});
}
}

View File

@@ -184,19 +184,32 @@ export class TerminalProcessManager implements ITerminalProcessManager {
rows: number,
isScreenReaderModeEnabled: boolean
): Promise<ITerminalChildProcess> {
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
const lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : null;
if (!shellLaunchConfig.executable) {
const defaultConfig = await this._terminalInstanceService.getDefaultShellAndArgs();
shellLaunchConfig.executable = defaultConfig.shell;
shellLaunchConfig.args = defaultConfig.args;
} else {
shellLaunchConfig.executable = this._configurationResolverService.resolve(lastActiveWorkspace === null ? undefined : lastActiveWorkspace, shellLaunchConfig.executable);
if (shellLaunchConfig.args) {
if (Array.isArray(shellLaunchConfig.args)) {
const resolvedArgs: string[] = [];
for (const arg of shellLaunchConfig.args) {
resolvedArgs.push(this._configurationResolverService.resolve(lastActiveWorkspace === null ? undefined : lastActiveWorkspace, arg));
}
shellLaunchConfig.args = resolvedArgs;
} else {
shellLaunchConfig.args = this._configurationResolverService.resolve(lastActiveWorkspace === null ? undefined : lastActiveWorkspace, shellLaunchConfig.args);
}
}
}
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
const initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, this._environmentService.userHome, activeWorkspaceRootUri, this._configHelper.config.cwd);
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
const lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : null;
const envFromConfigValue = this._workspaceConfigurationService.inspect<ITerminalEnvironment | undefined>(`terminal.integrated.env.${platformKey}`);
const isWorkspaceShellAllowed = this._configHelper.checkWorkspaceShellPermissions();
this._configHelper.showRecommendations(shellLaunchConfig);
const baseEnv = this._configHelper.config.inheritEnv ? process.env as platform.IProcessEnvironment : await this._terminalInstanceService.getMainProcessParentEnv();
const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, lastActiveWorkspace, envFromConfigValue, this._configurationResolverService, isWorkspaceShellAllowed, this._productService.version, this._configHelper.config.setLocaleVariables, baseEnv);

View File

@@ -122,6 +122,7 @@ export interface ITerminalConfigHelper {
/** Sets whether a workspace shell configuration is allowed or not */
setWorkspaceShellAllowed(isAllowed: boolean): void;
checkWorkspaceShellPermissions(osOverride?: OperatingSystem): boolean;
showRecommendations(shellLaunchConfig: IShellLaunchConfig): void;
}
export interface ITerminalFont {

View File

@@ -169,7 +169,9 @@ export function getDefaultShell(
defaultShell: string,
isWoW64: boolean,
windir: string | undefined,
platformOverride: platform.Platform = platform.platform
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
platformOverride: platform.Platform = platform.platform,
): string {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellConfigValue = fetchSetting(`terminal.integrated.shell.${platformKey}`);
@@ -190,17 +192,33 @@ export function getDefaultShell(
executable = executable.replace(/\//g, '\\');
}
if (configurationResolverService) {
executable = configurationResolverService.resolve(lastActiveWorkspace, executable);
}
return executable;
}
export function getDefaultShellArgs(
fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined },
isWorkspaceShellAllowed: boolean,
platformOverride: platform.Platform = platform.platform
): string[] {
lastActiveWorkspace: IWorkspaceFolder | undefined,
configurationResolverService: IConfigurationResolverService | undefined,
platformOverride: platform.Platform = platform.platform,
): string | string[] {
const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux';
const shellArgsConfigValue = fetchSetting(`terminal.integrated.shellArgs.${platformKey}`);
const args = (isWorkspaceShellAllowed ? <string[]>shellArgsConfigValue.value : <string[]>shellArgsConfigValue.user) || <string[]>shellArgsConfigValue.default;
let args = <string[] | string>((isWorkspaceShellAllowed ? shellArgsConfigValue.value : shellArgsConfigValue.user) || shellArgsConfigValue.default);
if (typeof args === 'string' && platformOverride === platform.Platform.Windows) {
return configurationResolverService ? configurationResolverService.resolve(lastActiveWorkspace, args) : args;
}
if (configurationResolverService) {
const resolvedArgs: string[] = [];
for (const arg of args) {
resolvedArgs.push(configurationResolverService.resolve(lastActiveWorkspace, arg));
}
args = resolvedArgs;
}
return args;
}
@@ -237,14 +255,14 @@ export function createTerminalEnvironment(
}
}
// Merge config (settings) and ShellLaunchConfig environments
mergeEnvironments(env, allowedEnvFromConfig);
mergeEnvironments(env, shellLaunchConfig.env);
// Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables
sanitizeProcessEnvironment(env, 'VSCODE_IPC_HOOK_CLI');
// Merge config (settings) and ShellLaunchConfig environments
mergeEnvironments(env, allowedEnvFromConfig);
mergeEnvironments(env, shellLaunchConfig.env);
// Adding other env keys necessary to create the process
addTerminalEnvironmentKeys(env, version, platform.locale, setLocaleVariables);
}

View File

@@ -17,6 +17,9 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
let Terminal: typeof XTermTerminal;
let WebLinksAddon: typeof XTermWebLinksAddon;
@@ -28,7 +31,10 @@ export class TerminalInstanceService implements ITerminalInstanceService {
constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IStorageService private readonly _storageService: IStorageService
@IStorageService private readonly _storageService: IStorageService,
@IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IHistoryService private readonly _historyService: IHistoryService
) {
}
@@ -65,19 +71,26 @@ export class TerminalInstanceService implements ITerminalInstanceService {
return this._storageService.getBoolean(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, StorageScope.WORKSPACE, false);
}
public getDefaultShellAndArgs(platformOverride: Platform = platform): Promise<{ shell: string, args: string[] | undefined }> {
public getDefaultShellAndArgs(platformOverride: Platform = platform): Promise<{ shell: string, args: string | string[] }> {
const isWorkspaceShellAllowed = this._isWorkspaceShellAllowed();
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot();
let lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : undefined;
lastActiveWorkspace = lastActiveWorkspace === null ? undefined : lastActiveWorkspace;
const shell = getDefaultShell(
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed,
getSystemShell(platformOverride),
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
process.env.windir,
lastActiveWorkspace,
this._configurationResolverService,
platformOverride
);
const args = getDefaultShellArgs(
(key) => this._configurationService.inspect(key),
isWorkspaceShellAllowed,
lastActiveWorkspace,
this._configurationResolverService,
platformOverride
);
return Promise.resolve({ shell, args });