Skip to content

Commit 0d3c066

Browse files
author
MikhailArkhipov
committed
Linux version check
1 parent 4e12b3c commit 0d3c066

File tree

4 files changed

+109
-22
lines changed

4 files changed

+109
-22
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,12 @@
817817
"description": "Path to directory containing the Jedi library (this path will contain the 'Jedi' sub directory).",
818818
"scope": "resource"
819819
},
820+
"python.analysis.checkOSVersion": {
821+
"type": "boolean",
822+
"default": true,
823+
"description": "Enables checking of the OS version to determine if the Language Server will run.",
824+
"scope": "resource"
825+
},
820826
"python.analysis.openFilesOnly": {
821827
"type": "boolean",
822828
"default": true,

src/client/activation/languageServer.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,14 @@ export class LanguageServerExtensionActivator implements IExtensionActivator {
125125
(this.configuration.getSettings() as PythonSettings).removeListener('change', this.onSettingsChanged.bind(this));
126126
}
127127

128-
private checkSupportedPlatform(): boolean {
128+
private async checkSupportedPlatform(): Promise<boolean> {
129129
const platform = this.services.get<IPlatformService>(IPlatformService);
130-
if (!platform.isNetCoreCompatibleOS) {
130+
const message = await platform.isNetCoreCompatibleOS();
131+
if (message && message.length > 0) {
131132
if (platform.isMac) {
132-
this.services.get<ILogger>(ILogger).logError('Unsupported MacOS');
133-
this.appShell.showErrorMessage('Microsoft Python Language Server does not support MacOS older than 10.12.');
133+
this.services.get<ILogger>(ILogger).logError(message);
134+
this.appShell.showErrorMessage(message);
134135
}
135-
// tslint:disable-next-line:no-suspicious-comment
136-
// TODO: Linux messages
137136
return false;
138137
}
139138
return true;

src/client/common/platform/platformService.ts

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
// Licensed under the MIT License.
33
'use strict';
44

5-
import { injectable } from 'inversify';
5+
import { inject, injectable } from 'inversify';
66
import { arch, release } from 'os';
7+
import { IServiceContainer } from '../../ioc/types';
8+
import { IProcessService, IProcessServiceFactory } from '../process/types';
79
import { NON_WINDOWS_PATH_VARIABLE_NAME, WINDOWS_PATH_VARIABLE_NAME } from './constants';
810
import { IPlatformService, IVersion } from './types';
911

@@ -21,20 +23,105 @@ class OSVersion implements IVersion {
2123
}
2224
}
2325

26+
enum OSCheckResult {
27+
Compatible,
28+
Incompatible,
29+
Unknown
30+
}
31+
2432
class MacOSVersion {
25-
public get isCompatibleOS(): boolean {
33+
public isCompatibleOS(): Promise<string> {
2634
// https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history
2735
// 10.12 == Darwin 16.0
28-
return new OSVersion().versionMajor >= 16;
36+
return Promise.resolve(new OSVersion().versionMajor >= 16 ? '' : 'Microsoft Python Language Server does not support MacOS older than 10.12.');
37+
}
38+
}
39+
40+
class LinuxVersion {
41+
constructor(private serviceContainer: IServiceContainer) { }
42+
public async isCompatibleOS(): Promise<string> {
43+
const factory = this.serviceContainer.get<IProcessServiceFactory>(IProcessServiceFactory);
44+
const process = await factory.create();
45+
46+
// https://github.com/dotnet/core/blob/master/release-notes/2.1/2.1-supported-os.md
47+
// OS version run 'lsb_release -a' on Ubuntu
48+
let result = await this.checkLinux(process, 'lsb_release', ['-a'], 'Ubuntu', 'Release:', ['18', '16', '14']);
49+
if (result === OSCheckResult.Compatible) {
50+
return Promise.resolve('');
51+
} else if (result === OSCheckResult.Incompatible) {
52+
return Promise.resolve('Microsoft Python Language Server only supports Ubuntu 18, 16 or 14.');
53+
}
54+
55+
// 'cat /etc/centos-release' on CentOS
56+
result = await this.checkLinux(process, 'cat', ['/etc/centos-release'], 'CentOS', 'release', ['7']);
57+
if (result === OSCheckResult.Compatible) {
58+
return Promise.resolve('');
59+
} else if (result === OSCheckResult.Incompatible) {
60+
return Promise.resolve('Microsoft Python Language Server only support CentOS 7.');
61+
}
62+
63+
// 'cat /etc/fedora-release' on Fedora
64+
result = await this.checkLinux(process, 'cat', ['/etc/fedora-release'], 'Fedora', 'release', ['28', '27']);
65+
if (result === OSCheckResult.Compatible) {
66+
return Promise.resolve('');
67+
} else if (result === OSCheckResult.Incompatible) {
68+
return Promise.resolve('Microsoft Python Language Server only support Fedora 28 and 27.');
69+
}
70+
71+
// 'cat /etc/redhat-release' on RedHat
72+
result = await this.checkLinux(process, 'cat', ['/etc/redhat-release'], 'Red Hat', 'release', ['7', '6']);
73+
if (result === OSCheckResult.Compatible) {
74+
return Promise.resolve('');
75+
} else if (result === OSCheckResult.Incompatible) {
76+
return Promise.resolve('Microsoft Python Language Server only support RedHat 6 or 7.');
77+
}
78+
79+
// 'cat /etc/suse-release' on SUSE
80+
result = await this.checkLinux(process, 'cat', ['/etc/suse-release'], 'SUSE', 'release', ['12']);
81+
if (result === OSCheckResult.Compatible) {
82+
return Promise.resolve('');
83+
} else if (result === OSCheckResult.Incompatible) {
84+
return Promise.resolve('Microsoft Python Language Server only support SUSE 12.');
85+
}
86+
87+
// 'cat /etc/suse-release' on Debian
88+
result = await this.checkLinux(process, 'lsb_release', ['-a'], 'Debian', 'Release:', ['9', '8.7']);
89+
if (result === OSCheckResult.Compatible) {
90+
return Promise.resolve('');
91+
} else if (result === OSCheckResult.Incompatible) {
92+
return Promise.resolve('Microsoft Python Language Server only support SUSE 12.');
93+
}
94+
95+
return Promise.resolve(''); // Optimistic for other Linuxes
96+
}
97+
98+
private async checkLinux(process: IProcessService, command: string, args: string[], osName: string, key: string, values: string[]): Promise<OSCheckResult> {
99+
const result = await process.exec(command, args);
100+
const words = result.stdout.split(' \t\n');
101+
if (words.indexOf(osName) > 0) {
102+
const index = words.indexOf(key);
103+
if (index >= 0 && index < words.length - 1) {
104+
const version = words[index + 1];
105+
const major = version.split('.')[0];
106+
for (const v of values) {
107+
if (major === v) {
108+
return Promise.resolve(OSCheckResult.Compatible);
109+
}
110+
}
111+
}
112+
return Promise.resolve(OSCheckResult.Incompatible);
113+
}
114+
return Promise.resolve(OSCheckResult.Unknown);
29115
}
30116
}
31117

118+
// tslint:disable-next-line:max-classes-per-file
32119
@injectable()
33120
export class PlatformService implements IPlatformService {
34121
private _isWindows: boolean;
35122
private _isMac: boolean;
36123

37-
constructor() {
124+
constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
38125
this._isWindows = /^win/.test(process.platform);
39126
this._isMac = /^darwin/.test(process.platform);
40127
}
@@ -56,18 +143,13 @@ export class PlatformService implements IPlatformService {
56143
public get virtualEnvBinName() {
57144
return this.isWindows ? 'scripts' : 'bin';
58145
}
59-
public get isNetCoreCompatibleOS(): boolean {
146+
public isNetCoreCompatibleOS(): Promise<string> {
60147
if (this.isMac) {
61-
return new MacOSVersion().isCompatibleOS;
148+
return new MacOSVersion().isCompatibleOS();
62149
}
63-
// tslint:disable-next-line:no-suspicious-comment
64-
// TODO: implement Linux checks. They are all over.
65-
// release() reports kernel version. For the actual
66-
// OS version run 'lsb_release -a' on Ubuntu,
67-
// 'cat /etc/centos-release' on CentOS
68-
// 'cat /etc/fedora-release' on Fedora
69-
// 'cat /etc/lsb-release' on Mint
70-
// 'cat /etc/redhat-release' on Red Hat
71-
return true; // Windows matches between .NET Core and VS Code.
150+
if (this.isLinux) {
151+
return new LinuxVersion(this.serviceContainer).isCompatibleOS();
152+
}
153+
return Promise.resolve(''); // Windows matches between .NET Core and VS Code.
72154
}
73155
}

src/client/common/platform/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export interface IPlatformService {
2727
is64bit: boolean;
2828
pathVariableName: 'Path' | 'PATH';
2929
virtualEnvBinName: 'bin' | 'scripts';
30-
isNetCoreCompatibleOS: boolean;
30+
isNetCoreCompatibleOS(): Promise<string>;
3131
}
3232

3333
export type TemporaryFile = { filePath: string } & Disposable;

0 commit comments

Comments
 (0)