Skip to content

Commit d47a991

Browse files
authored
May point release with fixes for shell detection (#5925)
* Fixes * Rename news file * New point release
1 parent 9b0e94c commit d47a991

File tree

12 files changed

+693
-205
lines changed

12 files changed

+693
-205
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Changelog
22

3-
## 2019.5.2 (4 June 2019)
3+
## 2019.5.3 (5 June 2019)
4+
5+
### Fixes
6+
7+
1. Fixes to detection of the shell.
8+
([#5916](https://github.com/microsoft/vscode-python/issues/5916))
9+
10+
11+
## 2019.5.18426 (4 June 2019)
412

513
### Fixes
614

package-lock.json

Lines changed: 189 additions & 45 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "python",
33
"displayName": "Python",
44
"description": "Linting, Debugging (multi-threaded, remote), Intellisense, code formatting, refactoring, unit tests, snippets, and more.",
5-
"version": "2019.5.2",
5+
"version": "2019.5.3",
66
"languageServerVersion": "0.2.82",
77
"publisher": "ms-python",
88
"author": {
@@ -2252,7 +2252,7 @@
22522252
"@types/request": "^2.47.0",
22532253
"@types/semver": "^5.5.0",
22542254
"@types/shortid": "^0.0.29",
2255-
"@types/sinon": "^4.3.0",
2255+
"@types/sinon": "^4.3.3",
22562256
"@types/stack-trace": "0.0.29",
22572257
"@types/strip-json-comments": "0.0.30",
22582258
"@types/temp": "^0.8.32",
@@ -2326,6 +2326,7 @@
23262326
"rewiremock": "^3.13.0",
23272327
"sass-loader": "^7.1.0",
23282328
"shortid": "^2.2.8",
2329+
"sinon": "^7.3.2",
23292330
"style-loader": "^0.23.1",
23302331
"styled-jsx": "^3.1.0",
23312332
"svg-inline-loader": "^0.8.0",

src/client/common/platform/platformService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ export class PlatformService implements IPlatformService {
5757
public get isLinux(): boolean {
5858
return this.osType === OSType.Linux;
5959
}
60+
public get osRelease(): string {
61+
return os.release();
62+
}
6063
public get is64bit(): boolean {
6164
// tslint:disable-next-line:no-require-imports
6265
const arch = require('arch');

src/client/common/platform/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface IRegistry {
2020
export const IPlatformService = Symbol('IPlatformService');
2121
export interface IPlatformService {
2222
readonly osType: OSType;
23+
osRelease: string;
2324
readonly pathVariableName: 'Path' | 'PATH';
2425
readonly virtualEnvBinName: 'bin' | 'Scripts';
2526

src/client/common/terminal/helper.ts

Lines changed: 12 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,22 @@
22
// Licensed under the MIT License.
33

44
import { inject, injectable, named } from 'inversify';
5-
import * as os from 'os';
65
import { Terminal, Uri } from 'vscode';
76
import { ICondaService, IInterpreterService, InterpreterType, PythonInterpreter } from '../../interpreter/contracts';
87
import { sendTelemetryEvent } from '../../telemetry';
98
import { EventName } from '../../telemetry/constants';
10-
import { ITerminalManager } from '../application/types';
9+
import { ITerminalManager, IWorkspaceService } from '../application/types';
1110
import '../extensions';
1211
import { traceDecorators, traceError } from '../logger';
1312
import { IPlatformService } from '../platform/types';
1413
import { IConfigurationService, ICurrentProcess, Resource } from '../types';
1514
import { OSType } from '../utils/platform';
15+
import { ShellDetector } from './shellDetector';
1616
import { ITerminalActivationCommandProvider, ITerminalHelper, TerminalActivationProviders, TerminalShellType } from './types';
1717

18-
// Types of shells can be found here:
19-
// 1. https://wiki.ubuntu.com/ChangingShells
20-
const IS_GITBASH = /(gitbash.exe$)/i;
21-
const IS_BASH = /(bash.exe$|bash$)/i;
22-
const IS_WSL = /(wsl.exe$)/i;
23-
const IS_ZSH = /(zsh$)/i;
24-
const IS_KSH = /(ksh$)/i;
25-
const IS_COMMAND = /(cmd.exe$|cmd$)/i;
26-
const IS_POWERSHELL = /(powershell.exe$|powershell$)/i;
27-
const IS_POWERSHELL_CORE = /(pwsh.exe$|pwsh$)/i;
28-
const IS_FISH = /(fish$)/i;
29-
const IS_CSHELL = /(csh$)/i;
30-
const IS_TCSHELL = /(tcsh$)/i;
31-
const IS_XONSH = /(xonsh$)/i;
32-
33-
const defaultOSShells = {
34-
[OSType.Linux]: TerminalShellType.bash,
35-
[OSType.OSX]: TerminalShellType.bash,
36-
[OSType.Windows]: TerminalShellType.commandPrompt,
37-
[OSType.Unknown]: undefined
38-
};
39-
4018
@injectable()
4119
export class TerminalHelper implements ITerminalHelper {
42-
private readonly detectableShells: Map<TerminalShellType, RegExp>;
20+
private readonly shellDetector: ShellDetector;
4321
constructor(@inject(IPlatformService) private readonly platform: IPlatformService,
4422
@inject(ITerminalManager) private readonly terminalManager: ITerminalManager,
4523
@inject(ICondaService) private readonly condaService: ICondaService,
@@ -50,61 +28,17 @@ export class TerminalHelper implements ITerminalHelper {
5028
@inject(ITerminalActivationCommandProvider) @named(TerminalActivationProviders.commandPromptAndPowerShell) private readonly commandPromptAndPowerShell: ITerminalActivationCommandProvider,
5129
@inject(ITerminalActivationCommandProvider) @named(TerminalActivationProviders.pyenv) private readonly pyenv: ITerminalActivationCommandProvider,
5230
@inject(ITerminalActivationCommandProvider) @named(TerminalActivationProviders.pipenv) private readonly pipenv: ITerminalActivationCommandProvider,
53-
@inject(IConfigurationService) private readonly currentProcess: ICurrentProcess
31+
@inject(ICurrentProcess) private readonly currentProcess: ICurrentProcess,
32+
@inject(IWorkspaceService) private readonly workspace: IWorkspaceService
5433
) {
55-
this.detectableShells = new Map<TerminalShellType, RegExp>();
56-
this.detectableShells.set(TerminalShellType.powershell, IS_POWERSHELL);
57-
this.detectableShells.set(TerminalShellType.gitbash, IS_GITBASH);
58-
this.detectableShells.set(TerminalShellType.bash, IS_BASH);
59-
this.detectableShells.set(TerminalShellType.wsl, IS_WSL);
60-
this.detectableShells.set(TerminalShellType.zsh, IS_ZSH);
61-
this.detectableShells.set(TerminalShellType.ksh, IS_KSH);
62-
this.detectableShells.set(TerminalShellType.commandPrompt, IS_COMMAND);
63-
this.detectableShells.set(TerminalShellType.fish, IS_FISH);
64-
this.detectableShells.set(TerminalShellType.tcshell, IS_TCSHELL);
65-
this.detectableShells.set(TerminalShellType.cshell, IS_CSHELL);
66-
this.detectableShells.set(TerminalShellType.powershellCore, IS_POWERSHELL_CORE);
67-
this.detectableShells.set(TerminalShellType.xonsh, IS_XONSH);
34+
this.shellDetector = new ShellDetector(this.platform, this.currentProcess, this.workspace);
35+
6836
}
6937
public createTerminal(title?: string): Terminal {
7038
return this.terminalManager.createTerminal({ name: title });
7139
}
7240
public identifyTerminalShell(terminal?: Terminal): TerminalShellType {
73-
let shell = TerminalShellType.other;
74-
let usingDefaultShell = false;
75-
const terminalProvided = !!terminal;
76-
// Determine shell based on the name of the terminal.
77-
// See solution here https://github.com/microsoft/vscode/issues/74233#issuecomment-497527337
78-
if (terminal) {
79-
shell = this.identifyTerminalShellByName(terminal.name);
80-
}
81-
82-
// If still unable to identify, then use fall back to determine path to the default shell.
83-
if (shell === TerminalShellType.other) {
84-
const shellPath = getDefaultShell(this.platform.osType, this.currentProcess);
85-
shell = Array.from(this.detectableShells.keys())
86-
.reduce((matchedShell, shellToDetect) => {
87-
if (matchedShell === TerminalShellType.other && this.detectableShells.get(shellToDetect)!.test(shellPath)) {
88-
return shellToDetect;
89-
}
90-
return matchedShell;
91-
}, TerminalShellType.other);
92-
93-
// We have restored to using the default shell.
94-
usingDefaultShell = shell !== TerminalShellType.other;
95-
}
96-
const properties = { failed: shell === TerminalShellType.other, usingDefaultShell, terminalProvided };
97-
sendTelemetryEvent(EventName.TERMINAL_SHELL_IDENTIFICATION, undefined, properties);
98-
return shell;
99-
}
100-
public identifyTerminalShellByName(name: string): TerminalShellType {
101-
return Array.from(this.detectableShells.keys())
102-
.reduce((matchedShell, shellToDetect) => {
103-
if (matchedShell === TerminalShellType.other && this.detectableShells.get(shellToDetect)!.test(name)) {
104-
return shellToDetect;
105-
}
106-
return matchedShell;
107-
}, TerminalShellType.other);
41+
return this.shellDetector.identifyTerminalShell(terminal);
10842
}
10943

11044
public buildCommandForTerminal(terminalShellType: TerminalShellType, command: string, args: string[]) {
@@ -119,7 +53,10 @@ export class TerminalHelper implements ITerminalHelper {
11953
return promise;
12054
}
12155
public async getEnvironmentActivationShellCommands(resource: Resource, interpreter?: PythonInterpreter): Promise<string[] | undefined> {
122-
const shell = defaultOSShells[this.platform.osType];
56+
if (this.platform.osType === OSType.Unknown){
57+
return;
58+
}
59+
const shell = this.shellDetector.identifyTerminalShell();
12360
if (!shell) {
12461
return;
12562
}
@@ -181,30 +118,3 @@ export class TerminalHelper implements ITerminalHelper {
181118
}
182119
}
183120
}
184-
185-
/*
186-
The following code is based on VS Code from https://github.com/microsoft/vscode/blob/5c65d9bfa4c56538150d7f3066318e0db2c6151f/src/vs/workbench/contrib/terminal/node/terminal.ts#L12-L55
187-
This is only a fall back to identify the default shell used by VSC.
188-
On Windows, determine the default shell.
189-
On others, default to bash.
190-
*/
191-
function getDefaultShell(osType: OSType, currentProcess: ICurrentProcess): string {
192-
if (osType === OSType.Windows) {
193-
return getTerminalDefaultShellWindows(osType, currentProcess);
194-
}
195-
return '/bin/bash';
196-
}
197-
let _TERMINAL_DEFAULT_SHELL_WINDOWS: string | null = null;
198-
function getTerminalDefaultShellWindows(osType: OSType, currentProcess: ICurrentProcess): string {
199-
if (!_TERMINAL_DEFAULT_SHELL_WINDOWS) {
200-
const isAtLeastWindows10 = osType === OSType.Windows && parseFloat(os.release()) >= 10;
201-
const is32ProcessOn64Windows = process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
202-
const powerShellPath = `${process.env.windir}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`;
203-
_TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : getWindowsShell(currentProcess);
204-
}
205-
return _TERMINAL_DEFAULT_SHELL_WINDOWS;
206-
}
207-
208-
function getWindowsShell(currentProcess: ICurrentProcess): string {
209-
return currentProcess.env.comspec || 'cmd.exe';
210-
}

0 commit comments

Comments
 (0)