Skip to content

Commit a2b4ed8

Browse files
Add support for KDE Neon (and other Linux distros with ID_LIKE)
This checkin adds support for checking the ID_LIKE field in the os-release file to try and find a compatible base OS. This support is imperfect since ID_LIKE doesn't provide a version number for the downstream OS(s). But this at least works for KDE Neon.
1 parent 7acb873 commit a2b4ed8

File tree

2 files changed

+129
-50
lines changed

2 files changed

+129
-50
lines changed

src/platform.ts

Lines changed: 88 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ const unknown = 'unknown';
1818
export class LinuxDistribution {
1919
public constructor(
2020
public name: string,
21-
public version: string) { }
21+
public version: string,
22+
public idLike?: string[]) { }
2223

2324
public static GetCurrent(): Promise<LinuxDistribution> {
2425
// Try /etc/os-release and fallback to /usr/lib/os-release per the synopsis
@@ -48,6 +49,7 @@ export class LinuxDistribution {
4849
public static FromReleaseInfo(releaseInfo: string, eol: string = os.EOL): LinuxDistribution {
4950
let name = unknown;
5051
let version = unknown;
52+
let idLike : string[] = null;
5153

5254
const lines = releaseInfo.split(eol);
5355
for (let line of lines) {
@@ -69,14 +71,17 @@ export class LinuxDistribution {
6971
else if (key === 'VERSION_ID') {
7072
version = value;
7173
}
74+
else if (key === 'ID_LIKE') {
75+
idLike = value.split(" ");
76+
}
7277

73-
if (name !== unknown && version !== unknown) {
78+
if (name !== unknown && version !== unknown && idLike !== null) {
7479
break;
7580
}
7681
}
7782
}
7883

79-
return new LinuxDistribution(name, version);
84+
return new LinuxDistribution(name, version, idLike);
8085
}
8186
}
8287

@@ -215,56 +220,28 @@ export class PlatformInformation {
215220

216221
case 'linux':
217222
if (architecture === 'x86_64') {
218-
const centos_7 = 'centos.7-x64';
219-
const debian_8 = 'debian.8-x64';
220-
const fedora_23 = 'fedora.23-x64';
221-
const opensuse_13_2 = 'opensuse.13.2-x64';
222-
const rhel_7 = 'rhel.7-x64';
223-
const ubuntu_14_04 = 'ubuntu.14.04-x64';
224-
const ubuntu_16_04 = 'ubuntu.16.04-x64';
225-
226-
switch (distribution.name) {
227-
case 'ubuntu':
228-
if (distribution.version.startsWith("14")) {
229-
// This also works for Linux Mint
230-
return ubuntu_14_04;
231-
}
232-
else if (distribution.version.startsWith("16")) {
233-
return ubuntu_16_04;
234-
}
235-
236-
break;
237-
case 'elementary':
238-
case 'elementary OS':
239-
if (distribution.version.startsWith("0.3")) {
240-
// Elementary OS 0.3 Freya is binary compatible with Ubuntu 14.04
241-
return ubuntu_14_04;
242-
}
243-
else if (distribution.version.startsWith("0.4")) {
244-
// Elementary OS 0.4 Loki is binary compatible with Ubuntu 16.04
245-
return ubuntu_16_04;
246-
}
247223

248-
break;
249-
case 'linuxmint':
250-
if (distribution.version.startsWith("18")) {
251-
// Linux Mint 18 is binary compatible with Ubuntu 16.04
252-
return ubuntu_16_04;
224+
const unknown_distribution = 'unknown_distribution';
225+
const unknown_version = 'unknown_version';
226+
227+
// First try the distribution name
228+
let runtimeId = PlatformInformation.getRuntimeIdHelper(distribution.name, distribution.version);
229+
230+
// If the distribution isn't one that we understand, but the 'ID_LIKE' field has something that we understand, use that
231+
//
232+
// NOTE: 'ID_LIKE' doesn't specify the version of the 'like' OS. So we will use the 'VERSION_ID' value. This will restrict
233+
// how useful ID_LIKE will be since it requires the version numbers to match up, but it is the best we can do.
234+
if (runtimeId === unknown_distribution && distribution.idLike && distribution.idLike.length > 0) {
235+
for (let id of distribution.idLike) {
236+
runtimeId = PlatformInformation.getRuntimeIdHelper(id, distribution.version);
237+
if (runtimeId !== unknown_distribution) {
238+
break;
253239
}
240+
}
241+
}
254242

255-
break;
256-
case 'centos':
257-
case 'ol':
258-
// Oracle Linux is binary compatible with CentOS
259-
return centos_7;
260-
case 'fedora':
261-
return fedora_23;
262-
case 'opensuse':
263-
return opensuse_13_2;
264-
case 'rhel':
265-
return rhel_7;
266-
case 'debian':
267-
return debian_8;
243+
if (runtimeId !== unknown_distribution && runtimeId !== unknown_version) {
244+
return runtimeId;
268245
}
269246
}
270247

@@ -276,4 +253,65 @@ export class PlatformInformation {
276253
// Chances are, VS Code doesn't support these platforms either.
277254
throw Error('Unsupported platform ' + platform);
278255
}
256+
257+
private static getRuntimeIdHelper(distributionName: string, distributionVersion: string): string {
258+
const unknown_distribution = 'unknown_distribution';
259+
const unknown_version = 'unknown_version';
260+
261+
const centos_7 = 'centos.7-x64';
262+
const debian_8 = 'debian.8-x64';
263+
const fedora_23 = 'fedora.23-x64';
264+
const opensuse_13_2 = 'opensuse.13.2-x64';
265+
const rhel_7 = 'rhel.7-x64';
266+
const ubuntu_14_04 = 'ubuntu.14.04-x64';
267+
const ubuntu_16_04 = 'ubuntu.16.04-x64';
268+
269+
switch (distributionName) {
270+
case 'ubuntu':
271+
if (distributionVersion.startsWith("14")) {
272+
// This also works for Linux Mint
273+
return ubuntu_14_04;
274+
}
275+
else if (distributionVersion.startsWith("16")) {
276+
return ubuntu_16_04;
277+
}
278+
279+
break;
280+
case 'elementary':
281+
case 'elementary OS':
282+
if (distributionVersion.startsWith("0.3")) {
283+
// Elementary OS 0.3 Freya is binary compatible with Ubuntu 14.04
284+
return ubuntu_14_04;
285+
}
286+
else if (distributionVersion.startsWith("0.4")) {
287+
// Elementary OS 0.4 Loki is binary compatible with Ubuntu 16.04
288+
return ubuntu_16_04;
289+
}
290+
291+
break;
292+
case 'linuxmint':
293+
if (distributionVersion.startsWith("18")) {
294+
// Linux Mint 18 is binary compatible with Ubuntu 16.04
295+
return ubuntu_16_04;
296+
}
297+
298+
break;
299+
case 'centos':
300+
case 'ol':
301+
// Oracle Linux is binary compatible with CentOS
302+
return centos_7;
303+
case 'fedora':
304+
return fedora_23;
305+
case 'opensuse':
306+
return opensuse_13_2;
307+
case 'rhel':
308+
return rhel_7;
309+
case 'debian':
310+
return debian_8;
311+
default:
312+
return unknown_distribution;
313+
}
314+
315+
return unknown_version;
316+
}
279317
}

test/platform.tests.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,23 @@ suite("Platform", () => {
9191
platformInfo.runtimeId.should.equal('centos.7-x64');
9292
})
9393

94+
test("Compute correct RID for KDE neon", () => {
95+
const platformInfo = new PlatformInformation('linux', 'x86_64', distro_kde_neon_5_8());
96+
97+
platformInfo.runtimeId.should.equal('ubuntu.16.04-x64');
98+
})
99+
94100
test("Compute no RID for CentOS 7 with 32-bit architecture", () => {
95101
const platformInfo = new PlatformInformation('linux', 'x86', distro_centos_7());
96102

97103
should().equal(platformInfo.runtimeId, null);
98104
})
105+
106+
test("Compute no RID for fake distro with no ID_LIKE", () => {
107+
const platformInfo = new PlatformInformation('linux', 'x86_64', distro_unknown_no_id_like());
108+
109+
should().equal(platformInfo.runtimeId, null);
110+
})
99111
});
100112

101113
function distro_ubuntu_14_04(): LinuxDistribution {
@@ -171,5 +183,34 @@ CENTOS_MANTISBT_PROJECT_VERSION="7"
171183
REDHAT_SUPPORT_PRODUCT="centos"
172184
REDHAT_SUPPORT_PRODUCT_VERSION="7"`;
173185

186+
return LinuxDistribution.FromReleaseInfo(input, '\n');
187+
}
188+
189+
function distro_kde_neon_5_8(): LinuxDistribution {
190+
// Copied from /etc/os-release on KDE Neon 5.8
191+
const input = `
192+
NAME="KDE neon"
193+
VERSION="5.8"
194+
ID=neon
195+
ID_LIKE="ubuntu debian"
196+
PRETTY_NAME="KDE neon User Edition 5.8"
197+
VERSION_ID="16.04"
198+
HOME_URL="http://neon.kde.org/"
199+
SUPPORT_URL="http://neon.kde.org/"
200+
BUG_REPORT_URL="http://bugs.kde.org/"
201+
VERSION_CODENAME=xenial
202+
UBUNTU_CODENAME=xenial`;
203+
204+
return LinuxDistribution.FromReleaseInfo(input, '\n');
205+
}
206+
207+
function distro_unknown_no_id_like(): LinuxDistribution {
208+
const input = `
209+
PRETTY_NAME="Make believe 1.0"
210+
NAME="Make believe"
211+
VERSION_ID="1.0"
212+
VERSION="1.0 (rogers)"
213+
ID=MakeBelieve`;
214+
174215
return LinuxDistribution.FromReleaseInfo(input, '\n');
175216
}

0 commit comments

Comments
 (0)