-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathcopyExtensionBinaries.ts
More file actions
113 lines (93 loc) · 4.05 KB
/
copyExtensionBinaries.ts
File metadata and controls
113 lines (93 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { cp, readdir, rm, stat } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { $args, $root, green, heading, note } from './common';
const extensionPrefix = 'ms-vscode.cpptools-';
const foldersToCopy = ['bin', 'debugAdapters', 'LLVM'] as const;
type InstalledExtension = {
path: string;
version: number[];
modified: number;
};
function compareVersions(left: number[], right: number[]): number {
const maxLength: number = Math.max(left.length, right.length);
for (let i = 0; i < maxLength; i++) {
const diff: number = (left[i] ?? 0) - (right[i] ?? 0);
if (diff !== 0) {
return diff;
}
}
return 0;
}
function tryParseVersion(folderName: string): number[] | undefined {
if (!folderName.startsWith(extensionPrefix)) {
return undefined;
}
const versionText: string | undefined = folderName.substring(extensionPrefix.length).match(/^\d+\.\d+\.\d+/)?.[0];
return versionText?.split('.').map(each => Number(each));
}
async function getInstalledExtensions(root: string): Promise<InstalledExtension[]> {
try {
const entries = await readdir(root, { withFileTypes: true });
const candidates: Promise<InstalledExtension | undefined>[] = entries.map(async (entry) => {
if (!entry.isDirectory()) {
return undefined;
}
const version: number[] | undefined = tryParseVersion(entry.name);
if (!version) {
return undefined;
}
const extensionPath: string = join(root, entry.name);
for (const folder of foldersToCopy) {
const info = await stat(join(extensionPath, folder)).catch(() => undefined);
if (!info?.isDirectory()) {
return undefined;
}
}
const info = await stat(extensionPath);
return {
path: extensionPath,
version,
modified: info.mtimeMs
};
});
const found = await Promise.all(candidates);
return found.filter((entry): entry is InstalledExtension => entry !== undefined);
} catch {
return [];
}
}
async function findLatestInstalledExtension(providedPath?: string): Promise<string> {
if (providedPath) {
return providedPath;
}
const searchRoots: string[] = [
join(homedir(), '.vscode', 'extensions'),
join(homedir(), '.vscode-insiders', 'extensions'),
join(homedir(), '.vscode-server', 'extensions'),
join(homedir(), '.vscode-server-insiders', 'extensions')
];
const installed: InstalledExtension[] = (await Promise.all(searchRoots.map(each => getInstalledExtensions(each)))).flat();
if (!installed.length) {
throw new Error(`Unable to find an installed C/C++ extension under ${searchRoots.join(' or ')}.`);
}
installed.sort((left, right) => compareVersions(right.version, left.version) || right.modified - left.modified);
return installed[0].path;
}
export async function main(sourcePath = $args[0]) {
console.log(heading('Copy installed extension binaries'));
const installedExtensionPath: string = await findLatestInstalledExtension(sourcePath);
note(`Using installed extension at ${installedExtensionPath}`);
for (const folder of foldersToCopy) {
const source: string = join(installedExtensionPath, folder);
const destination: string = join($root, folder);
console.log(`Copying ${green(folder)} from ${source}`);
await rm(destination, { recursive: true, force: true });
await cp(source, destination, { recursive: true, force: true });
}
note(`Copied installed binaries into ${$root}`);
}