Convert gulp files to ts

For #277526

Had to add a few ugly casts in difficult cases but mostly trying to add proper types
This commit is contained in:
Matt Bierner
2025-11-21 15:38:55 -08:00
parent 538db6134e
commit fcfb37c8f8
17 changed files with 217 additions and 274 deletions

View File

@@ -12,12 +12,11 @@ import * as cp from 'child_process';
import { tmpdir } from 'os'; import { tmpdir } from 'os';
import { existsSync, mkdirSync, rmSync } from 'fs'; import { existsSync, mkdirSync, rmSync } from 'fs';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import * as watcher from './lib/watch/index.ts'; import watcher from './lib/watch/index.ts';
import * as utilModule from './lib/util.ts'; import * as utilModule from './lib/util.ts';
import * as reporterModule from './lib/reporter.ts'; import * as reporterModule from './lib/reporter.ts';
import untar from 'gulp-untar'; import untar from 'gulp-untar';
import gunzip from 'gulp-gunzip'; import gunzip from 'gulp-gunzip';
import { fileURLToPath } from 'url';
const { debounce } = utilModule; const { debounce } = utilModule;
const { createReporter } = reporterModule; const { createReporter } = reporterModule;
@@ -43,8 +42,7 @@ const platformOpensslDirName =
const platformOpensslDir = path.join(rootAbs, 'openssl', 'package', 'out', platformOpensslDirName); const platformOpensslDir = path.join(rootAbs, 'openssl', 'package', 'out', platformOpensslDirName);
const hasLocalRust = (() => { const hasLocalRust = (() => {
/** @type boolean | undefined */ let result: boolean | undefined = undefined;
let result = undefined;
return () => { return () => {
if (result !== undefined) { if (result !== undefined) {
return result; return result;
@@ -61,15 +59,14 @@ const hasLocalRust = (() => {
}; };
})(); })();
const compileFromSources = (callback) => { const compileFromSources = (callback: (err?: string) => void) => {
const proc = cp.spawn('cargo', ['--color', 'always', 'build'], { const proc = cp.spawn('cargo', ['--color', 'always', 'build'], {
cwd: root, cwd: root,
stdio: ['ignore', 'pipe', 'pipe'], stdio: ['ignore', 'pipe', 'pipe'],
env: existsSync(platformOpensslDir) ? { OPENSSL_DIR: platformOpensslDir, ...process.env } : process.env env: existsSync(platformOpensslDir) ? { OPENSSL_DIR: platformOpensslDir, ...process.env } : process.env
}); });
/** @type Buffer[] */ const stdoutErr: Buffer[] = [];
const stdoutErr = [];
proc.stdout.on('data', d => stdoutErr.push(d)); proc.stdout.on('data', d => stdoutErr.push(d));
proc.stderr.on('data', d => stdoutErr.push(d)); proc.stderr.on('data', d => stdoutErr.push(d));
proc.on('error', callback); proc.on('error', callback);
@@ -82,7 +79,7 @@ const compileFromSources = (callback) => {
}); });
}; };
const acquireBuiltOpenSSL = (callback) => { const acquireBuiltOpenSSL = (callback: (err?: unknown) => void) => {
const dir = path.join(tmpdir(), 'vscode-openssl-download'); const dir = path.join(tmpdir(), 'vscode-openssl-download');
mkdirSync(dir, { recursive: true }); mkdirSync(dir, { recursive: true });
@@ -103,29 +100,28 @@ const acquireBuiltOpenSSL = (callback) => {
}); });
}; };
const compileWithOpenSSLCheck = (/** @type import('./lib/reporter').IReporter */ reporter) => es.map((_, callback) => { const compileWithOpenSSLCheck = (reporter: import('./lib/reporter.ts').IReporter) => es.map((_, callback) => {
compileFromSources(err => { compileFromSources(err => {
if (!err) { if (!err) {
// no-op callback();
} else if (err.toString().includes('Could not find directory of OpenSSL installation') && !existsSync(platformOpensslDir)) { } else if (err.toString().includes('Could not find directory of OpenSSL installation') && !existsSync(platformOpensslDir)) {
fancyLog(ansiColors.yellow(`[cli]`), 'OpenSSL libraries not found, acquiring prebuilt bits...'); fancyLog(ansiColors.yellow(`[cli]`), 'OpenSSL libraries not found, acquiring prebuilt bits...');
acquireBuiltOpenSSL(err => { acquireBuiltOpenSSL(err => {
if (err) { if (err) {
callback(err); callback(err as Error);
} else { } else {
compileFromSources(err => { compileFromSources(err => {
if (err) { if (err) {
reporter(err.toString()); reporter(err.toString());
} }
callback(null, ''); callback();
}); });
} }
}); });
} else { } else {
reporter(err.toString()); reporter(err.toString());
callback();
} }
callback(null, '');
}); });
}); });
@@ -147,8 +143,14 @@ const compileCliTask = task.define('compile-cli', () => {
const watchCliTask = task.define('watch-cli', () => { const watchCliTask = task.define('watch-cli', () => {
warnIfRustNotInstalled(); warnIfRustNotInstalled();
const compile = () => {
const reporter = createReporter('cli');
return gulp.src(`${root}/Cargo.toml`)
.pipe(compileWithOpenSSLCheck(reporter))
.pipe(reporter.end(true));
};
return watcher(`${src}/**`, { read: false }) return watcher(`${src}/**`, { read: false })
.pipe(debounce(compileCliTask)); .pipe(debounce(compile));
}); });
gulp.task(compileCliTask); gulp.task(compileCliTask);

View File

@@ -2,17 +2,14 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
//@ts-check
import gulp from 'gulp'; import gulp from 'gulp';
import * as util from './lib/util.ts'; import * as util from './lib/util.ts';
import * as date from './lib/date.ts'; import * as date from './lib/date.ts';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import * as compilation from './lib/compilation.ts'; import * as compilation from './lib/compilation.ts';
/** function makeCompileBuildTask(disableMangle: boolean) {
* @param {boolean} disableMangle
*/
function makeCompileBuildTask(disableMangle) {
return task.series( return task.series(
util.rimraf('out-build'), util.rimraf('out-build'),
date.writeISODate('out-build'), date.writeISODate('out-build'),

View File

@@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
//@ts-check
import gulp from 'gulp'; import gulp from 'gulp';
import path from 'path'; import path from 'path';
import * as util from './lib/util.ts'; import * as util from './lib/util.ts';
@@ -84,10 +84,7 @@ const compileEditorESMTask = task.define('compile-editor-esm', () => {
); );
}); });
/** function toExternalDTS(contents: string) {
* @param {string} contents
*/
function toExternalDTS(contents) {
const lines = contents.split(/\r\n|\r|\n/); const lines = contents.split(/\r\n|\r|\n/);
let killNextCloseCurlyBrace = false; let killNextCloseCurlyBrace = false;
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
@@ -230,10 +227,7 @@ gulp.task('monacodts', task.define('monacodts', () => {
//#region monaco type checking //#region monaco type checking
/** function createTscCompileTask(watch: boolean) {
* @param {boolean} watch
*/
function createTscCompileTask(watch) {
return () => { return () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit']; const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit'];
@@ -244,11 +238,10 @@ function createTscCompileTask(watch) {
cwd: path.join(import.meta.dirname, '..'), cwd: path.join(import.meta.dirname, '..'),
// stdio: [null, 'pipe', 'inherit'] // stdio: [null, 'pipe', 'inherit']
}); });
const errors = []; const errors: string[] = [];
const reporter = createReporter('monaco'); const reporter = createReporter('monaco');
/** @type {NodeJS.ReadWriteStream | undefined} */ let report: NodeJS.ReadWriteStream | undefined;
let report;
const magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings const magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
child.stdout.on('data', data => { child.stdout.on('data', data => {
@@ -287,13 +280,7 @@ export const monacoTypecheckTask = task.define('monaco-typecheck', createTscComp
//#endregion //#endregion
/** function setUnsetField(obj: Record<string, unknown>, field: string, value: unknown) {
* Sets a field on an object only if it's not already set, otherwise throws an error
* @param {any} obj - The object to modify
* @param {string} field - The field name to set
* @param {any} value - The value to set
*/
function setUnsetField(obj, field, value) {
if (obj[field] !== undefined) { if (obj[field] !== undefined) {
throw new Error(`Field "${field}" is already set (but was expected to not be).`); throw new Error(`Field "${field}" is already set (but was expected to not be).`);
} }

View File

@@ -22,7 +22,6 @@ import plumber from 'gulp-plumber';
import * as ext from './lib/extensions.ts'; import * as ext from './lib/extensions.ts';
import * as tsb from './lib/tsb/index.ts'; import * as tsb from './lib/tsb/index.ts';
import sourcemaps from 'gulp-sourcemaps'; import sourcemaps from 'gulp-sourcemaps';
import { fileURLToPath } from 'url';
const { getVersion } = getVersionModule; const { getVersion } = getVersionModule;
const { createReporter } = reporterModule; const { createReporter } = reporterModule;
@@ -79,13 +78,13 @@ const compilations = [
'.vscode/extensions/vscode-selfhost-import-aid/tsconfig.json', '.vscode/extensions/vscode-selfhost-import-aid/tsconfig.json',
]; ];
const getBaseUrl = out => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`; const getBaseUrl = (out: string) => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`;
const tasks = compilations.map(function (tsconfigFile) { const tasks = compilations.map(function (tsconfigFile) {
const absolutePath = path.join(root, tsconfigFile); const absolutePath = path.join(root, tsconfigFile);
const relativeDirname = path.dirname(tsconfigFile.replace(/^(.*\/)?extensions\//i, '')); const relativeDirname = path.dirname(tsconfigFile.replace(/^(.*\/)?extensions\//i, ''));
const overrideOptions = {}; const overrideOptions: { sourceMap?: boolean; inlineSources?: boolean; base?: string } = {};
overrideOptions.sourceMap = true; overrideOptions.sourceMap = true;
const name = relativeDirname.replace(/\//g, '-'); const name = relativeDirname.replace(/\//g, '-');
@@ -98,7 +97,7 @@ const tasks = compilations.map(function (tsconfigFile) {
const out = path.join(srcRoot, 'out'); const out = path.join(srcRoot, 'out');
const baseUrl = getBaseUrl(out); const baseUrl = getBaseUrl(out);
function createPipeline(build, emitError, transpileOnly) { function createPipeline(build: boolean, emitError?: boolean, transpileOnly?: boolean) {
const reporter = createReporter('extensions'); const reporter = createReporter('extensions');
overrideOptions.inlineSources = Boolean(build); overrideOptions.inlineSources = Boolean(build);
@@ -122,14 +121,14 @@ const tasks = compilations.map(function (tsconfigFile) {
.pipe(compilation()) .pipe(compilation())
.pipe(build ? util.stripSourceMappingURL() : es.through()) .pipe(build ? util.stripSourceMappingURL() : es.through())
.pipe(sourcemaps.write('.', { .pipe(sourcemaps.write('.', {
sourceMappingURL: !build ? null : f => `${baseUrl}/${f.relative}.map`, sourceMappingURL: !build ? undefined : f => `${baseUrl}/${f.relative}.map`,
addComment: !!build, addComment: !!build,
includeContent: !!build, includeContent: !!build,
// note: trailing slash is important, else the source URLs in V8's file coverage are incorrect // note: trailing slash is important, else the source URLs in V8's file coverage are incorrect
sourceRoot: '../src/', sourceRoot: '../src/',
})) }))
.pipe(tsFilter.restore) .pipe(tsFilter.restore)
.pipe(reporter.end(emitError)); .pipe(reporter.end(!!emitError));
return es.duplex(input, output); return es.duplex(input, output);
}; };
@@ -266,10 +265,7 @@ gulp.task(compileWebExtensionsTask);
export const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true)); export const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true));
gulp.task(watchWebExtensionsTask); gulp.task(watchWebExtensionsTask);
/** async function buildWebExtensions(isWatch: boolean) {
* @param {boolean} isWatch
*/
async function buildWebExtensions(isWatch) {
const extensionsPath = path.join(root, 'extensions'); const extensionsPath = path.join(root, 'extensions');
const webpackConfigLocations = await nodeUtil.promisify(glob)( const webpackConfigLocations = await nodeUtil.promisify(glob)(
path.join(extensionsPath, '**', 'extension-browser.webpack.config.js'), path.join(extensionsPath, '**', 'extension-browser.webpack.config.js'),

View File

@@ -11,13 +11,10 @@ import { hygiene } from './hygiene.ts';
const dirName = path.dirname(new URL(import.meta.url).pathname); const dirName = path.dirname(new URL(import.meta.url).pathname);
/** function checkPackageJSON(this: NodeJS.ReadWriteStream, actualPath: string) {
* @param {string} actualPath
*/
function checkPackageJSON(actualPath) {
const actual = JSON.parse(fs.readFileSync(path.join(dirName, '..', actualPath), 'utf8')); const actual = JSON.parse(fs.readFileSync(path.join(dirName, '..', actualPath), 'utf8'));
const rootPackageJSON = JSON.parse(fs.readFileSync(path.join(dirName, '..', 'package.json'), 'utf8')); const rootPackageJSON = JSON.parse(fs.readFileSync(path.join(dirName, '..', 'package.json'), 'utf8'));
const checkIncluded = (set1, set2) => { const checkIncluded = (set1: Record<string, string>, set2: Record<string, string>) => {
for (const depName in set1) { for (const depName in set1) {
const depVersion = set1[depName]; const depVersion = set1[depName];
const rootDepVersion = set2[depName]; const rootDepVersion = set2[depName];

View File

@@ -7,16 +7,16 @@ import gulp from 'gulp';
import * as path from 'path'; import * as path from 'path';
import es from 'event-stream'; import es from 'event-stream';
import * as util from './lib/util.ts'; import * as util from './lib/util.ts';
import * as getVersionModule from './lib/getVersion.ts'; import { getVersion } from './lib/getVersion.ts';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import * as optimize from './lib/optimize.ts'; import * as optimize from './lib/optimize.ts';
import * as inlineMetaModule from './lib/inlineMeta.ts'; import { inlineMeta } from './lib/inlineMeta.ts';
import product from '../product.json' with { type: 'json' }; import product from '../product.json' with { type: 'json' };
import rename from 'gulp-rename'; import rename from 'gulp-rename';
import replace from 'gulp-replace'; import replace from 'gulp-replace';
import filter from 'gulp-filter'; import filter from 'gulp-filter';
import * as dependenciesModule from './lib/dependencies.ts'; import { getProductionDependencies } from './lib/dependencies.ts';
import * as dateModule from './lib/date.ts'; import { readISODate } from './lib/date.ts';
import vfs from 'vinyl-fs'; import vfs from 'vinyl-fs';
import packageJson from '../package.json' with { type: 'json' }; import packageJson from '../package.json' with { type: 'json' };
import flatmap from 'gulp-flatmap'; import flatmap from 'gulp-flatmap';
@@ -25,21 +25,15 @@ import untar from 'gulp-untar';
import File from 'vinyl'; import File from 'vinyl';
import * as fs from 'fs'; import * as fs from 'fs';
import glob from 'glob'; import glob from 'glob';
import { compileBuildWithManglingTask } from './gulpfile.compile.mjs'; import { compileBuildWithManglingTask } from './gulpfile.compile.ts';
import { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } from './gulpfile.extensions.mjs'; import { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } from './gulpfile.extensions.ts';
import { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } from './gulpfile.vscode.web.mjs'; import { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } from './gulpfile.vscode.web.ts';
import * as cp from 'child_process'; import * as cp from 'child_process';
import log from 'fancy-log'; import log from 'fancy-log';
import buildfile from './buildfile.ts'; import buildfile from './buildfile.ts';
import { fileURLToPath } from 'url'; import { fetchUrls, fetchGithub } from './lib/fetch.ts';
import * as fetchModule from './lib/fetch.ts';
import jsonEditor from 'gulp-json-editor'; import jsonEditor from 'gulp-json-editor';
const { inlineMeta } = inlineMetaModule;
const { getVersion } = getVersionModule;
const { getProductionDependencies } = dependenciesModule;
const { readISODate } = dateModule;
const { fetchUrls, fetchGithub } = fetchModule;
const REPO_ROOT = path.dirname(import.meta.dirname); const REPO_ROOT = path.dirname(import.meta.dirname);
const commit = getVersion(REPO_ROOT); const commit = getVersion(REPO_ROOT);
@@ -146,12 +140,12 @@ const bootstrapEntryPoints = [
function getNodeVersion() { function getNodeVersion() {
const npmrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.npmrc'), 'utf8'); const npmrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.npmrc'), 'utf8');
const nodeVersion = /^target="(.*)"$/m.exec(npmrc)[1]; const nodeVersion = /^target="(.*)"$/m.exec(npmrc)![1];
const internalNodeVersion = /^ms_build_id="(.*)"$/m.exec(npmrc)[1]; const internalNodeVersion = /^ms_build_id="(.*)"$/m.exec(npmrc)![1];
return { nodeVersion, internalNodeVersion }; return { nodeVersion, internalNodeVersion };
} }
function getNodeChecksum(expectedName) { function getNodeChecksum(expectedName: string): string | undefined {
const nodeJsChecksums = fs.readFileSync(path.join(REPO_ROOT, 'build', 'checksums', 'nodejs.txt'), 'utf8'); const nodeJsChecksums = fs.readFileSync(path.join(REPO_ROOT, 'build', 'checksums', 'nodejs.txt'), 'utf8');
for (const line of nodeJsChecksums.split('\n')) { for (const line of nodeJsChecksums.split('\n')) {
const [checksum, name] = line.split(/\s+/); const [checksum, name] = line.split(/\s+/);
@@ -162,11 +156,12 @@ function getNodeChecksum(expectedName) {
return undefined; return undefined;
} }
function extractAlpinefromDocker(nodeVersion, platform, arch) { function extractAlpinefromDocker(nodeVersion: string, platform: string, arch: string) {
const imageName = arch === 'arm64' ? 'arm64v8/node' : 'node'; const imageName = arch === 'arm64' ? 'arm64v8/node' : 'node';
log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from docker image ${imageName}`); log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from docker image ${imageName}`);
const contents = cp.execSync(`docker run --rm ${imageName}:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' }); const contents = cp.execSync(`docker run --rm ${imageName}:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' });
return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } })]); // eslint-disable-next-line local/code-no-dangerous-type-assertions
return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } as fs.Stats })]);
} }
const { nodeVersion, internalNodeVersion } = getNodeVersion(); const { nodeVersion, internalNodeVersion } = getNodeVersion();
@@ -178,7 +173,7 @@ BUILD_TARGETS.forEach(({ platform, arch }) => {
if (!fs.existsSync(nodePath)) { if (!fs.existsSync(nodePath)) {
util.rimraf(nodePath); util.rimraf(nodePath);
return nodejs(platform, arch) return nodejs(platform, arch)!
.pipe(vfs.dest(nodePath)); .pipe(vfs.dest(nodePath));
} }
@@ -189,10 +184,10 @@ BUILD_TARGETS.forEach(({ platform, arch }) => {
const defaultNodeTask = gulp.task(`node-${process.platform}-${process.arch}`); const defaultNodeTask = gulp.task(`node-${process.platform}-${process.arch}`);
if (defaultNodeTask) { if (defaultNodeTask) {
gulp.task(task.define('node', defaultNodeTask)); gulp.task(task.define('node', () => defaultNodeTask));
} }
function nodejs(platform, arch) { function nodejs(platform: string, arch: string): NodeJS.ReadWriteStream | undefined {
if (arch === 'armhf') { if (arch === 'armhf') {
arch = 'armv7l'; arch = 'armv7l';
@@ -204,7 +199,7 @@ function nodejs(platform, arch) {
log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejsRepository}...`); log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejsRepository}...`);
const glibcPrefix = process.env['VSCODE_NODE_GLIBC'] ?? ''; const glibcPrefix = process.env['VSCODE_NODE_GLIBC'] ?? '';
let expectedName; let expectedName: string | undefined;
switch (platform) { switch (platform) {
case 'win32': case 'win32':
expectedName = product.nodejsRepository !== 'https://nodejs.org' ? expectedName = product.nodejsRepository !== 'https://nodejs.org' ?
@@ -221,7 +216,7 @@ function nodejs(platform, arch) {
expectedName = `node-v${nodeVersion}-linux-${arch}-musl.tar.gz`; expectedName = `node-v${nodeVersion}-linux-${arch}-musl.tar.gz`;
break; break;
} }
const checksumSha256 = getNodeChecksum(expectedName); const checksumSha256 = expectedName ? getNodeChecksum(expectedName) : undefined;
if (checksumSha256) { if (checksumSha256) {
log(`Using SHA256 checksum for checking integrity: ${checksumSha256}`); log(`Using SHA256 checksum for checking integrity: ${checksumSha256}`);
@@ -232,13 +227,13 @@ function nodejs(platform, arch) {
switch (platform) { switch (platform) {
case 'win32': case 'win32':
return (product.nodejsRepository !== 'https://nodejs.org' ? return (product.nodejsRepository !== 'https://nodejs.org' ?
fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) : fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName!, checksumSha256 }) :
fetchUrls(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org', checksumSha256 })) fetchUrls(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org', checksumSha256 }))
.pipe(rename('node.exe')); .pipe(rename('node.exe'));
case 'darwin': case 'darwin':
case 'linux': case 'linux':
return (product.nodejsRepository !== 'https://nodejs.org' ? return (product.nodejsRepository !== 'https://nodejs.org' ?
fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) : fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName!, checksumSha256 }) :
fetchUrls(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org', checksumSha256 }) fetchUrls(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org', checksumSha256 })
).pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) ).pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar())))
.pipe(filter('**/node')) .pipe(filter('**/node'))
@@ -246,7 +241,7 @@ function nodejs(platform, arch) {
.pipe(rename('node')); .pipe(rename('node'));
case 'alpine': case 'alpine':
return product.nodejsRepository !== 'https://nodejs.org' ? return product.nodejsRepository !== 'https://nodejs.org' ?
fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName!, checksumSha256 })
.pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) .pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar())))
.pipe(filter('**/node')) .pipe(filter('**/node'))
.pipe(util.setExecutableBit('**')) .pipe(util.setExecutableBit('**'))
@@ -255,17 +250,17 @@ function nodejs(platform, arch) {
} }
} }
function packageTask(type, platform, arch, sourceFolderName, destinationFolderName) { function packageTask(type: string, platform: string, arch: string, sourceFolderName: string, destinationFolderName: string) {
const destination = path.join(BUILD_ROOT, destinationFolderName); const destination = path.join(BUILD_ROOT, destinationFolderName);
return () => { return () => {
const src = gulp.src(sourceFolderName + '/**', { base: '.' }) const src = gulp.src(sourceFolderName + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) .pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); }))
.pipe(util.setExecutableBit(['**/*.sh'])) .pipe(util.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', '!**/*.{js,css}.map'])); .pipe(filter(['**', '!**/*.{js,css}.map']));
const workspaceExtensionPoints = ['debuggers', 'jsonValidation']; const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
const isUIExtension = (manifest) => { const isUIExtension = (manifest: { extensionKind?: string; main?: string; contributes?: Record<string, unknown> }) => {
switch (manifest.extensionKind) { switch (manifest.extensionKind) {
case 'ui': return true; case 'ui': return true;
case 'workspace': return false; case 'workspace': return false;
@@ -294,9 +289,9 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
}).map((extensionPath) => path.basename(path.dirname(extensionPath))) }).map((extensionPath) => path.basename(path.dirname(extensionPath)))
.filter(name => name !== 'vscode-api-tests' && name !== 'vscode-test-resolver'); // Do not ship the test extensions .filter(name => name !== 'vscode-api-tests' && name !== 'vscode-test-resolver'); // Do not ship the test extensions
const marketplaceExtensions = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'product.json'), 'utf8')).builtInExtensions const marketplaceExtensions = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'product.json'), 'utf8')).builtInExtensions
.filter(entry => !entry.platforms || new Set(entry.platforms).has(platform)) .filter((entry: { platforms?: string[]; clientOnly?: boolean }) => !entry.platforms || new Set(entry.platforms).has(platform))
.filter(entry => !entry.clientOnly) .filter((entry: { clientOnly?: boolean }) => !entry.clientOnly)
.map(entry => entry.name); .map((entry: { name: string }) => entry.name);
const extensionPaths = [...localWorkspaceExtensions, ...marketplaceExtensions] const extensionPaths = [...localWorkspaceExtensions, ...marketplaceExtensions]
.map(name => `.build/extensions/${name}/**`); .map(name => `.build/extensions/${name}/**`);
@@ -306,7 +301,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
.pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true })); .pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true }));
let version = packageJson.version; let version = packageJson.version;
const quality = product.quality; const quality = (product as typeof product & { quality?: string }).quality;
if (quality && quality !== 'stable') { if (quality && quality !== 'stable') {
version += '-' + quality; version += '-' + quality;
@@ -314,7 +309,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
const name = product.nameShort; const name = product.nameShort;
let packageJsonContents; let packageJsonContents: string = '';
const packageJsonStream = gulp.src(['remote/package.json'], { base: 'remote' }) const packageJsonStream = gulp.src(['remote/package.json'], { base: 'remote' })
.pipe(jsonEditor({ name, version, dependencies: undefined, optionalDependencies: undefined, type: 'module' })) .pipe(jsonEditor({ name, version, dependencies: undefined, optionalDependencies: undefined, type: 'module' }))
.pipe(es.through(function (file) { .pipe(es.through(function (file) {
@@ -322,7 +317,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
this.emit('data', file); this.emit('data', file);
})); }));
let productJsonContents; let productJsonContents: string = '';
const productJsonStream = gulp.src(['product.json'], { base: '.' }) const productJsonStream = gulp.src(['product.json'], { base: '.' })
.pipe(jsonEditor({ commit, date: readISODate('out-build'), version })) .pipe(jsonEditor({ commit, date: readISODate('out-build'), version }))
.pipe(es.through(function (file) { .pipe(es.through(function (file) {
@@ -348,7 +343,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
const nodePath = `.build/node/v${nodeVersion}/${platform}-${arch}`; const nodePath = `.build/node/v${nodeVersion}/${platform}-${arch}`;
const node = gulp.src(`${nodePath}/**`, { base: nodePath, dot: true }); const node = gulp.src(`${nodePath}/**`, { base: nodePath, dot: true });
let web = []; let web: NodeJS.ReadWriteStream[] = [];
if (type === 'reh-web') { if (type === 'reh-web') {
web = [ web = [
'resources/server/favicon.ico', 'resources/server/favicon.ico',
@@ -376,12 +371,12 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
result = es.merge(result, result = es.merge(result,
gulp.src('resources/server/bin/remote-cli/code.cmd', { base: '.' }) gulp.src('resources/server/bin/remote-cli/code.cmd', { base: '.' })
.pipe(replace('@@VERSION@@', version)) .pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@COMMIT@@', commit || ''))
.pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/remote-cli/${product.applicationName}.cmd`)), .pipe(rename(`bin/remote-cli/${product.applicationName}.cmd`)),
gulp.src('resources/server/bin/helpers/browser.cmd', { base: '.' }) gulp.src('resources/server/bin/helpers/browser.cmd', { base: '.' })
.pipe(replace('@@VERSION@@', version)) .pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@COMMIT@@', commit || ''))
.pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/helpers/browser.cmd`)), .pipe(rename(`bin/helpers/browser.cmd`)),
gulp.src('resources/server/bin/code-server.cmd', { base: '.' }) gulp.src('resources/server/bin/code-server.cmd', { base: '.' })
@@ -391,13 +386,13 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
result = es.merge(result, result = es.merge(result,
gulp.src(`resources/server/bin/remote-cli/${platform === 'darwin' ? 'code-darwin.sh' : 'code-linux.sh'}`, { base: '.' }) gulp.src(`resources/server/bin/remote-cli/${platform === 'darwin' ? 'code-darwin.sh' : 'code-linux.sh'}`, { base: '.' })
.pipe(replace('@@VERSION@@', version)) .pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@COMMIT@@', commit || ''))
.pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/remote-cli/${product.applicationName}`)) .pipe(rename(`bin/remote-cli/${product.applicationName}`))
.pipe(util.setExecutableBit()), .pipe(util.setExecutableBit()),
gulp.src(`resources/server/bin/helpers/${platform === 'darwin' ? 'browser-darwin.sh' : 'browser-linux.sh'}`, { base: '.' }) gulp.src(`resources/server/bin/helpers/${platform === 'darwin' ? 'browser-darwin.sh' : 'browser-linux.sh'}`, { base: '.' })
.pipe(replace('@@VERSION@@', version)) .pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@COMMIT@@', commit || ''))
.pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/helpers/browser.sh`)) .pipe(rename(`bin/helpers/browser.sh`))
.pipe(util.setExecutableBit()), .pipe(util.setExecutableBit()),
@@ -425,11 +420,8 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
}; };
} }
/** function tweakProductForServerWeb(product: typeof import('../product.json')) {
* @param {object} product The parsed product.json file contents const result: typeof product & { webEndpointUrlTemplate?: string } = { ...product };
*/
function tweakProductForServerWeb(product) {
const result = { ...product };
delete result.webEndpointUrlTemplate; delete result.webEndpointUrlTemplate;
return result; return result;
} }
@@ -461,7 +453,7 @@ function tweakProductForServerWeb(product) {
gulp.task(minifyTask); gulp.task(minifyTask);
BUILD_TARGETS.forEach(buildTarget => { BUILD_TARGETS.forEach(buildTarget => {
const dashed = (str) => (str ? `-${str}` : ``); const dashed = (str: string) => (str ? `-${str}` : ``);
const platform = buildTarget.platform; const platform = buildTarget.platform;
const arch = buildTarget.arch; const arch = buildTarget.arch;
@@ -471,7 +463,13 @@ function tweakProductForServerWeb(product) {
const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series( const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series(
compileNativeExtensionsBuildTask, compileNativeExtensionsBuildTask,
gulp.task(`node-${platform}-${arch}`), () => {
const nodeTask = gulp.task(`node-${platform}-${arch}`) as task.CallbackTask;
if (nodeTask) {
return nodeTask();
}
return Promise.resolve();
},
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)), util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
packageTask(type, platform, arch, sourceFolderName, destinationFolderName) packageTask(type, platform, arch, sourceFolderName, destinationFolderName)
)); ));

View File

@@ -12,9 +12,9 @@ import * as electronConfigModule from './lib/electron.ts';
import filter from 'gulp-filter'; import filter from 'gulp-filter';
import * as deps from './lib/dependencies.ts'; import * as deps from './lib/dependencies.ts';
import { existsSync, readdirSync } from 'fs'; import { existsSync, readdirSync } from 'fs';
import { fileURLToPath } from 'url';
const { config } = electronConfigModule; const { config } = electronConfigModule;
const electronDest = (electron as unknown as { dest: (destination: string, options: unknown) => NodeJS.ReadWriteStream }).dest;
const root = path.dirname(import.meta.dirname); const root = path.dirname(import.meta.dirname);
@@ -35,32 +35,32 @@ const excludedCheckList = [
]; ];
BUILD_TARGETS.forEach(buildTarget => { BUILD_TARGETS.forEach(buildTarget => {
const dashed = (/** @type {string | null} */ str) => (str ? `-${str}` : ``); const dashed = (str: string | null) => (str ? `-${str}` : ``);
const platform = buildTarget.platform; const platform = buildTarget.platform;
const arch = buildTarget.arch; const arch = buildTarget.arch;
const destinationExe = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'bin'); const destinationExe = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'bin');
const destinationPdb = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'pdb'); const destinationPdb = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'pdb');
const tasks = []; const tasks: task.Task[] = [];
// removal tasks // removal tasks
tasks.push(util.rimraf(destinationExe), util.rimraf(destinationPdb)); tasks.push(util.rimraf(destinationExe), util.rimraf(destinationPdb));
// electron // electron
tasks.push(() => electron.dest(destinationExe, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch })); tasks.push(() => electronDest(destinationExe, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch }));
// pdbs for windows // pdbs for windows
if (platform === 'win32') { if (platform === 'win32') {
tasks.push( tasks.push(
() => electron.dest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, pdbs: true }), () => electronDest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, pdbs: true }),
() => confirmPdbsExist(destinationExe, destinationPdb) () => confirmPdbsExist(destinationExe, destinationPdb)
); );
} }
if (platform === 'linux') { if (platform === 'linux') {
tasks.push( tasks.push(
() => electron.dest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, symbols: true }) () => electronDest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, symbols: true })
); );
} }
@@ -81,7 +81,7 @@ function getProductionDependencySources() {
return productionDependencies.map(d => path.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat(); return productionDependencies.map(d => path.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat();
} }
function nodeModules(destinationExe, destinationPdb, platform) { function nodeModules(destinationExe: string, destinationPdb: string, platform: string): task.CallbackTask {
const exe = () => { const exe = () => {
return gulp.src(getProductionDependencySources(), { base: '.', dot: true }) return gulp.src(getProductionDependencySources(), { base: '.', dot: true })
@@ -101,7 +101,7 @@ function nodeModules(destinationExe, destinationPdb, platform) {
.pipe(gulp.dest(destinationPdb)); .pipe(gulp.dest(destinationPdb));
}; };
return gulp.parallel(exe, pdb); return gulp.parallel(exe, pdb) as task.CallbackTask;
} }
if (platform === 'linux') { if (platform === 'linux') {
@@ -111,13 +111,13 @@ function nodeModules(destinationExe, destinationPdb, platform) {
.pipe(gulp.dest(destinationPdb)); .pipe(gulp.dest(destinationPdb));
}; };
return gulp.parallel(exe, pdb); return gulp.parallel(exe, pdb) as task.CallbackTask;
} }
return exe; return exe;
} }
function confirmPdbsExist(destinationExe, destinationPdb) { function confirmPdbsExist(destinationExe: string, destinationPdb: string) {
readdirSync(destinationExe).forEach(file => { readdirSync(destinationExe).forEach(file => {
if (excludedCheckList.includes(file)) { if (excludedCheckList.includes(file)) {
return; return;

View File

@@ -6,8 +6,8 @@ import { EventEmitter } from 'events';
import glob from 'glob'; import glob from 'glob';
import gulp from 'gulp'; import gulp from 'gulp';
import { createRequire } from 'node:module'; import { createRequire } from 'node:module';
import { monacoTypecheckTask /* , monacoTypecheckWatchTask */ } from './gulpfile.editor.mjs'; import { monacoTypecheckTask /* , monacoTypecheckWatchTask */ } from './gulpfile.editor.ts';
import { compileExtensionMediaTask, compileExtensionsTask, watchExtensionsTask } from './gulpfile.extensions.mjs'; import { compileExtensionMediaTask, compileExtensionsTask, watchExtensionsTask } from './gulpfile.extensions.ts';
import * as compilation from './lib/compilation.ts'; import * as compilation from './lib/compilation.ts';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import * as util from './lib/util.ts'; import * as util from './lib/util.ts';
@@ -52,7 +52,7 @@ process.on('unhandledRejection', (reason, p) => {
}); });
// Load all the gulpfiles only if running tasks other than the editor tasks // Load all the gulpfiles only if running tasks other than the editor tasks
glob.sync('gulpfile.*.{mjs,js}', { cwd: import.meta.dirname }) glob.sync('gulpfile.*.ts', { cwd: import.meta.dirname })
.forEach(f => { .forEach(f => {
return require(`./${f}`); return require(`./${f}`);
}); });

View File

@@ -8,35 +8,33 @@ import replace from 'gulp-replace';
import rename from 'gulp-rename'; import rename from 'gulp-rename';
import es from 'event-stream'; import es from 'event-stream';
import vfs from 'vinyl-fs'; import vfs from 'vinyl-fs';
import * as utilModule from './lib/util.ts'; import { rimraf } from './lib/util.ts';
import * as getVersionModule from './lib/getVersion.ts'; import { getVersion } from './lib/getVersion.ts';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import packageJson from '../package.json' with { type: 'json' }; import packageJson from '../package.json' with { type: 'json' };
import product from '../product.json' with { type: 'json' }; import product from '../product.json' with { type: 'json' };
import { getDependencies } from './linux/dependencies-generator.ts'; import { getDependencies } from './linux/dependencies-generator.ts';
import * as depLists from './linux/debian/dep-lists.ts'; import { recommendedDeps as debianRecommendedDependencies } from './linux/debian/dep-lists.ts';
import * as path from 'path'; import * as path from 'path';
import * as cp from 'child_process'; import * as cp from 'child_process';
import { promisify } from 'util'; import { promisify } from 'util';
import { fileURLToPath } from 'url';
const { rimraf } = utilModule;
const { getVersion } = getVersionModule;
const { recommendedDeps: debianRecommendedDependencies } = depLists;
const exec = promisify(cp.exec); const exec = promisify(cp.exec);
const root = path.dirname(import.meta.dirname); const root = path.dirname(import.meta.dirname);
const commit = getVersion(root); const commit = getVersion(root);
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000); const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
/** function getDebPackageArch(arch: string): string {
* @param {string} arch switch (arch) {
*/ case 'x64': return 'amd64';
function getDebPackageArch(arch) { case 'armhf': return 'armhf';
return { x64: 'amd64', armhf: 'armhf', arm64: 'arm64' }[arch]; case 'arm64': return 'arm64';
default: throw new Error(`Unknown arch: ${arch}`);
}
} }
function prepareDebPackage(arch) { function prepareDebPackage(arch: string) {
const binaryDir = '../VSCode-linux-' + arch; const binaryDir = '../VSCode-linux-' + arch;
const debArch = getDebPackageArch(arch); const debArch = getDebPackageArch(arch);
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch; const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
@@ -94,7 +92,7 @@ function prepareDebPackage(arch) {
.pipe(replace('@@ARCHITECTURE@@', debArch)) .pipe(replace('@@ARCHITECTURE@@', debArch))
.pipe(replace('@@DEPENDS@@', dependencies.join(', '))) .pipe(replace('@@DEPENDS@@', dependencies.join(', ')))
.pipe(replace('@@RECOMMENDS@@', debianRecommendedDependencies.join(', '))) .pipe(replace('@@RECOMMENDS@@', debianRecommendedDependencies.join(', ')))
.pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024))) .pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024).toString()))
.pipe(rename('DEBIAN/control')) .pipe(rename('DEBIAN/control'))
.pipe(es.through(function (f) { that.emit('data', f); }, function () { that.emit('end'); })); .pipe(es.through(function (f) { that.emit('data', f); }, function () { that.emit('end'); }));
})); }));
@@ -122,10 +120,7 @@ function prepareDebPackage(arch) {
}; };
} }
/** function buildDebPackage(arch: string) {
* @param {string} arch
*/
function buildDebPackage(arch) {
const debArch = getDebPackageArch(arch); const debArch = getDebPackageArch(arch);
const cwd = `.build/linux/deb/${debArch}`; const cwd = `.build/linux/deb/${debArch}`;
@@ -136,24 +131,20 @@ function buildDebPackage(arch) {
}; };
} }
/** function getRpmBuildPath(rpmArch: string): string {
* @param {string} rpmArch
*/
function getRpmBuildPath(rpmArch) {
return '.build/linux/rpm/' + rpmArch + '/rpmbuild'; return '.build/linux/rpm/' + rpmArch + '/rpmbuild';
} }
/** function getRpmPackageArch(arch: string): string {
* @param {string} arch switch (arch) {
*/ case 'x64': return 'x86_64';
function getRpmPackageArch(arch) { case 'armhf': return 'armv7hl';
return { x64: 'x86_64', armhf: 'armv7hl', arm64: 'aarch64' }[arch]; case 'arm64': return 'aarch64';
default: throw new Error(`Unknown arch: ${arch}`);
}
} }
/** function prepareRpmPackage(arch: string) {
* @param {string} arch
*/
function prepareRpmPackage(arch) {
const binaryDir = '../VSCode-linux-' + arch; const binaryDir = '../VSCode-linux-' + arch;
const rpmArch = getRpmPackageArch(arch); const rpmArch = getRpmPackageArch(arch);
const stripBinary = process.env['STRIP'] ?? '/usr/bin/strip'; const stripBinary = process.env['STRIP'] ?? '/usr/bin/strip';
@@ -205,11 +196,11 @@ function prepareRpmPackage(arch) {
.pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@ICON@@', product.linuxIconName)) .pipe(replace('@@ICON@@', product.linuxIconName))
.pipe(replace('@@VERSION@@', packageJson.version)) .pipe(replace('@@VERSION@@', packageJson.version))
.pipe(replace('@@RELEASE@@', linuxPackageRevision)) .pipe(replace('@@RELEASE@@', linuxPackageRevision.toString()))
.pipe(replace('@@ARCHITECTURE@@', rpmArch)) .pipe(replace('@@ARCHITECTURE@@', rpmArch))
.pipe(replace('@@LICENSE@@', product.licenseName)) .pipe(replace('@@LICENSE@@', product.licenseName))
.pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@')) .pipe(replace('@@QUALITY@@', (product as typeof product & { quality?: string }).quality || '@@QUALITY@@'))
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) .pipe(replace('@@UPDATEURL@@', (product as typeof product & { updateUrl?: string }).updateUrl || '@@UPDATEURL@@'))
.pipe(replace('@@DEPENDENCIES@@', dependencies.join(', '))) .pipe(replace('@@DEPENDENCIES@@', dependencies.join(', ')))
.pipe(replace('@@STRIP@@', stripBinary)) .pipe(replace('@@STRIP@@', stripBinary))
.pipe(rename('SPECS/' + product.applicationName + '.spec')); .pipe(rename('SPECS/' + product.applicationName + '.spec'));
@@ -223,10 +214,7 @@ function prepareRpmPackage(arch) {
}; };
} }
/** function buildRpmPackage(arch: string) {
* @param {string} arch
*/
function buildRpmPackage(arch) {
const rpmArch = getRpmPackageArch(arch); const rpmArch = getRpmPackageArch(arch);
const rpmBuildPath = getRpmBuildPath(rpmArch); const rpmBuildPath = getRpmBuildPath(rpmArch);
const rpmOut = `${rpmBuildPath}/RPMS/${rpmArch}`; const rpmOut = `${rpmBuildPath}/RPMS/${rpmArch}`;
@@ -239,17 +227,11 @@ function buildRpmPackage(arch) {
}; };
} }
/** function getSnapBuildPath(arch: string): string {
* @param {string} arch
*/
function getSnapBuildPath(arch) {
return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`; return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`;
} }
/** function prepareSnapPackage(arch: string) {
* @param {string} arch
*/
function prepareSnapPackage(arch) {
const binaryDir = '../VSCode-linux-' + arch; const binaryDir = '../VSCode-linux-' + arch;
const destination = getSnapBuildPath(arch); const destination = getSnapBuildPath(arch);
@@ -279,7 +261,7 @@ function prepareSnapPackage(arch) {
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' }) const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', commit.substr(0, 8))) .pipe(replace('@@VERSION@@', commit!.substr(0, 8)))
// Possible run-on values https://snapcraft.io/docs/architectures // Possible run-on values https://snapcraft.io/docs/architectures
.pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch)) .pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch))
.pipe(rename('snap/snapcraft.yaml')); .pipe(rename('snap/snapcraft.yaml'));
@@ -293,10 +275,7 @@ function prepareSnapPackage(arch) {
}; };
} }
/** function buildSnapPackage(arch: string) {
* @param {string} arch
*/
function buildSnapPackage(arch) {
const cwd = getSnapBuildPath(arch); const cwd = getSnapBuildPath(arch);
return () => exec('snapcraft', { cwd }); return () => exec('snapcraft', { cwd });
} }

View File

@@ -14,33 +14,27 @@ import filter from 'gulp-filter';
import electron from '@vscode/gulp-electron'; import electron from '@vscode/gulp-electron';
import jsonEditor from 'gulp-json-editor'; import jsonEditor from 'gulp-json-editor';
import * as util from './lib/util.ts'; import * as util from './lib/util.ts';
import * as getVersionModule from './lib/getVersion.ts'; import { getVersion } from './lib/getVersion.ts';
import * as dateModule from './lib/date.ts'; import { readISODate } from './lib/date.ts';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import buildfile from './buildfile.ts'; import buildfile from './buildfile.ts';
import * as optimize from './lib/optimize.ts'; import * as optimize from './lib/optimize.ts';
import * as inlineMetaModule from './lib/inlineMeta.ts'; import { inlineMeta } from './lib/inlineMeta.ts';
import packageJson from '../package.json' with { type: 'json' }; import packageJson from '../package.json' with { type: 'json' };
import product from '../product.json' with { type: 'json' }; import product from '../product.json' with { type: 'json' };
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import * as i18n from './lib/i18n.ts'; import * as i18n from './lib/i18n.ts';
import * as dependenciesModule from './lib/dependencies.ts'; import { getProductionDependencies } from './lib/dependencies.ts';
import * as electronModule from './lib/electron.ts'; import { config } from './lib/electron.ts';
import * as asarModule from './lib/asar.ts'; import { createAsar } from './lib/asar.ts';
import minimist from 'minimist'; import minimist from 'minimist';
import { compileBuildWithoutManglingTask, compileBuildWithManglingTask } from './gulpfile.compile.mjs'; import { compileBuildWithoutManglingTask, compileBuildWithManglingTask } from './gulpfile.compile.ts';
import { compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileAllExtensionsBuildTask, compileExtensionMediaBuildTask, cleanExtensionsBuildTask } from './gulpfile.extensions.mjs'; import { compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileAllExtensionsBuildTask, compileExtensionMediaBuildTask, cleanExtensionsBuildTask } from './gulpfile.extensions.ts';
import { promisify } from 'util'; import { promisify } from 'util';
import globCallback from 'glob'; import globCallback from 'glob';
import rceditCallback from 'rcedit'; import rceditCallback from 'rcedit';
import { fileURLToPath } from 'url';
const { getVersion } = getVersionModule;
const { readISODate } = dateModule;
const { inlineMeta } = inlineMetaModule;
const { getProductionDependencies } = dependenciesModule;
const { config } = electronModule;
const { createAsar } = asarModule;
const glob = promisify(globCallback); const glob = promisify(globCallback);
const rcedit = promisify(rceditCallback); const rcedit = promisify(rceditCallback);
const root = path.dirname(import.meta.dirname); const root = path.dirname(import.meta.dirname);
@@ -164,34 +158,30 @@ const minifyVSCodeTask = task.define('minify-vscode', task.series(
gulp.task(minifyVSCodeTask); gulp.task(minifyVSCodeTask);
const coreCI = task.define('core-ci', task.series( const coreCI = task.define('core-ci', task.series(
gulp.task('compile-build-with-mangling'), gulp.task('compile-build-with-mangling') as task.Task,
task.parallel( task.parallel(
gulp.task('minify-vscode'), gulp.task('minify-vscode') as task.Task,
gulp.task('minify-vscode-reh'), gulp.task('minify-vscode-reh') as task.Task,
gulp.task('minify-vscode-reh-web'), gulp.task('minify-vscode-reh-web') as task.Task,
) )
)); ));
gulp.task(coreCI); gulp.task(coreCI);
const coreCIPR = task.define('core-ci-pr', task.series( const coreCIPR = task.define('core-ci-pr', task.series(
gulp.task('compile-build-without-mangling'), gulp.task('compile-build-without-mangling') as task.Task,
task.parallel( task.parallel(
gulp.task('minify-vscode'), gulp.task('minify-vscode') as task.Task,
gulp.task('minify-vscode-reh'), gulp.task('minify-vscode-reh') as task.Task,
gulp.task('minify-vscode-reh-web'), gulp.task('minify-vscode-reh-web') as task.Task,
) )
)); ));
gulp.task(coreCIPR); gulp.task(coreCIPR);
/** /**
* Compute checksums for some files. * Compute checksums for some files.
*
* @param {string} out The out folder to read the file from.
* @param {string[]} filenames The paths to compute a checksum for.
* @return {Object} A map of paths to checksums.
*/ */
function computeChecksums(out, filenames) { function computeChecksums(out: string, filenames: string[]): Record<string, string> {
const result = {}; const result: Record<string, string> = {};
filenames.forEach(function (filename) { filenames.forEach(function (filename) {
const fullPath = path.join(process.cwd(), out, filename); const fullPath = path.join(process.cwd(), out, filename);
result[filename] = computeChecksum(fullPath); result[filename] = computeChecksum(fullPath);
@@ -200,12 +190,9 @@ function computeChecksums(out, filenames) {
} }
/** /**
* Compute checksum for a file. * Compute checksums for a file.
*
* @param {string} filename The absolute path to a filename.
* @return {string} The checksum for `filename`.
*/ */
function computeChecksum(filename) { function computeChecksum(filename: string): string {
const contents = fs.readFileSync(filename); const contents = fs.readFileSync(filename);
const hash = crypto const hash = crypto
@@ -217,9 +204,7 @@ function computeChecksum(filename) {
return hash; return hash;
} }
function packageTask(platform, arch, sourceFolderName, destinationFolderName, opts) { function packageTask(platform: string, arch: string, sourceFolderName: string, destinationFolderName: string, _opts?: { stats?: boolean }) {
opts = opts || {};
const destination = path.join(path.dirname(root), destinationFolderName); const destination = path.join(path.dirname(root), destinationFolderName);
platform = platform || process.platform; platform = platform || process.platform;
@@ -236,15 +221,15 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
]); ]);
const src = gulp.src(out + '/**', { base: '.' }) const src = gulp.src(out + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); })) .pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + out), 'out'); }))
.pipe(util.setExecutableBit(['**/*.sh'])); .pipe(util.setExecutableBit(['**/*.sh']));
const platformSpecificBuiltInExtensionsExclusions = product.builtInExtensions.filter(ext => { const platformSpecificBuiltInExtensionsExclusions = product.builtInExtensions.filter(ext => {
if (!ext.platforms) { if (!(ext as { platforms?: string[] }).platforms) {
return false; return false;
} }
const set = new Set(ext.platforms); const set = new Set((ext as { platforms?: string[] }).platforms);
return !set.has(platform); return !set.has(platform);
}).map(ext => `!.build/extensions/${ext.name}/**`); }).map(ext => `!.build/extensions/${ext.name}/**`);
@@ -254,20 +239,20 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
.pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true })); .pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true }));
let version = packageJson.version; let version = packageJson.version;
const quality = product.quality; const quality = (product as { quality?: string }).quality;
if (quality && quality !== 'stable') { if (quality && quality !== 'stable') {
version += '-' + quality; version += '-' + quality;
} }
const name = product.nameShort; const name = product.nameShort;
const packageJsonUpdates = { name, version }; const packageJsonUpdates: Record<string, unknown> = { name, version };
if (platform === 'linux') { if (platform === 'linux') {
packageJsonUpdates.desktopName = `${product.applicationName}.desktop`; packageJsonUpdates.desktopName = `${product.applicationName}.desktop`;
} }
let packageJsonContents; let packageJsonContents: string;
const packageJsonStream = gulp.src(['package.json'], { base: '.' }) const packageJsonStream = gulp.src(['package.json'], { base: '.' })
.pipe(jsonEditor(packageJsonUpdates)) .pipe(jsonEditor(packageJsonUpdates))
.pipe(es.through(function (file) { .pipe(es.through(function (file) {
@@ -275,7 +260,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
this.emit('data', file); this.emit('data', file);
})); }));
let productJsonContents; let productJsonContents: string;
const productJsonStream = gulp.src(['product.json'], { base: '.' }) const productJsonStream = gulp.src(['product.json'], { base: '.' })
.pipe(jsonEditor({ commit, date: readISODate('out-build'), checksums, version })) .pipe(jsonEditor({ commit, date: readISODate('out-build'), checksums, version }))
.pipe(es.through(function (file) { .pipe(es.through(function (file) {
@@ -373,7 +358,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
all = es.merge(all, shortcut, policyDest); all = es.merge(all, shortcut, policyDest);
} }
let result = all let result: NodeJS.ReadWriteStream = all
.pipe(util.skipDirectories()) .pipe(util.skipDirectories())
.pipe(util.fixWin32DirectoryPermissions()) .pipe(util.fixWin32DirectoryPermissions())
.pipe(filter(['**', '!**/.github/**'], { dot: true })) // https://github.com/microsoft/vscode/issues/116523 .pipe(filter(['**', '!**/.github/**'], { dot: true })) // https://github.com/microsoft/vscode/issues/116523
@@ -401,10 +386,10 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
.pipe(replace('@@NAME@@', product.nameShort)) .pipe(replace('@@NAME@@', product.nameShort))
.pipe(replace('@@PRODNAME@@', product.nameLong)) .pipe(replace('@@PRODNAME@@', product.nameLong))
.pipe(replace('@@VERSION@@', version)) .pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@COMMIT@@', commit ?? ''))
.pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(replace('@@SERVERDATAFOLDER@@', product.serverDataFolderName || '.vscode-remote')) .pipe(replace('@@SERVERDATAFOLDER@@', product.serverDataFolderName || '.vscode-remote'))
.pipe(replace('@@QUALITY@@', quality)) .pipe(replace('@@QUALITY@@', quality ?? ''))
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; }))); .pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' }) result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
@@ -425,7 +410,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
.pipe(replace('@@ApplicationIdShort@@', product.win32RegValueName)) .pipe(replace('@@ApplicationIdShort@@', product.win32RegValueName))
.pipe(replace('@@ApplicationExe@@', product.nameShort + '.exe')) .pipe(replace('@@ApplicationExe@@', product.nameShort + '.exe'))
.pipe(replace('@@FileExplorerContextMenuID@@', quality === 'stable' ? 'OpenWithCode' : 'OpenWithCodeInsiders')) .pipe(replace('@@FileExplorerContextMenuID@@', quality === 'stable' ? 'OpenWithCode' : 'OpenWithCodeInsiders'))
.pipe(replace('@@FileExplorerContextMenuCLSID@@', product.win32ContextMenu[arch].clsid)) .pipe(replace('@@FileExplorerContextMenuCLSID@@', (product as { win32ContextMenu?: Record<string, { clsid: string }> }).win32ContextMenu![arch].clsid))
.pipe(replace('@@FileExplorerContextMenuDLL@@', `${quality === 'stable' ? 'code' : 'code_insider'}_explorer_command_${arch}.dll`)) .pipe(replace('@@FileExplorerContextMenuDLL@@', `${quality === 'stable' ? 'code' : 'code_insider'}_explorer_command_${arch}.dll`))
.pipe(rename(f => f.dirname = `appx/manifest`))); .pipe(rename(f => f.dirname = `appx/manifest`)));
} }
@@ -448,7 +433,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
return task; return task;
} }
function patchWin32DependenciesTask(destinationFolderName) { function patchWin32DependenciesTask(destinationFolderName: string) {
const cwd = path.join(path.dirname(root), destinationFolderName); const cwd = path.join(path.dirname(root), destinationFolderName);
return async () => { return async () => {
@@ -489,7 +474,7 @@ const BUILD_TARGETS = [
{ platform: 'linux', arch: 'arm64' }, { platform: 'linux', arch: 'arm64' },
]; ];
BUILD_TARGETS.forEach(buildTarget => { BUILD_TARGETS.forEach(buildTarget => {
const dashed = (str) => (str ? `-${str}` : ``); const dashed = (str: string) => (str ? `-${str}` : ``);
const platform = buildTarget.platform; const platform = buildTarget.platform;
const arch = buildTarget.arch; const arch = buildTarget.arch;
const opts = buildTarget.opts; const opts = buildTarget.opts;
@@ -532,7 +517,7 @@ BUILD_TARGETS.forEach(buildTarget => {
// #region nls // #region nls
const innoSetupConfig = { const innoSetupConfig: Record<string, { codePage: string; defaultInfo?: { name: string; id: string } }> = {
'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } }, 'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } },
'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } }, 'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } },
'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } }, 'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } },

View File

@@ -7,33 +7,28 @@ import gulp from 'gulp';
import * as path from 'path'; import * as path from 'path';
import es from 'event-stream'; import es from 'event-stream';
import * as util from './lib/util.ts'; import * as util from './lib/util.ts';
import * as getVersionModule from './lib/getVersion.ts'; import { getVersion } from './lib/getVersion.ts';
import * as task from './lib/task.ts'; import * as task from './lib/task.ts';
import * as optimize from './lib/optimize.ts'; import * as optimize from './lib/optimize.ts';
import * as dateModule from './lib/date.ts'; import { readISODate } from './lib/date.ts';
import product from '../product.json' with { type: 'json' }; import product from '../product.json' with { type: 'json' };
import rename from 'gulp-rename'; import rename from 'gulp-rename';
import filter from 'gulp-filter'; import filter from 'gulp-filter';
import * as dependenciesModule from './lib/dependencies.ts'; import { getProductionDependencies } from './lib/dependencies.ts';
import vfs from 'vinyl-fs'; import vfs from 'vinyl-fs';
import packageJson from '../package.json' with { type: 'json' }; import packageJson from '../package.json' with { type: 'json' };
import { compileBuildWithManglingTask } from './gulpfile.compile.mjs'; import { compileBuildWithManglingTask } from './gulpfile.compile.ts';
import * as extensions from './lib/extensions.ts'; import * as extensions from './lib/extensions.ts';
import VinylFile from 'vinyl'; import VinylFile from 'vinyl';
import jsonEditor from 'gulp-json-editor'; import jsonEditor from 'gulp-json-editor';
import buildfile from './buildfile.ts'; import buildfile from './buildfile.ts';
import { fileURLToPath } from 'url';
const { getVersion } = getVersionModule;
const { readISODate } = dateModule;
const { getProductionDependencies } = dependenciesModule;
const REPO_ROOT = path.dirname(import.meta.dirname); const REPO_ROOT = path.dirname(import.meta.dirname);
const BUILD_ROOT = path.dirname(REPO_ROOT); const BUILD_ROOT = path.dirname(REPO_ROOT);
const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web'); const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web');
const commit = getVersion(REPO_ROOT); const commit = getVersion(REPO_ROOT);
const quality = product.quality; const quality = (product as { quality?: string }).quality;
const version = (quality && quality !== 'stable') ? `${packageJson.version}-${quality}` : packageJson.version; const version = (quality && quality !== 'stable') ? `${packageJson.version}-${quality}` : packageJson.version;
export const vscodeWebResourceIncludes = [ export const vscodeWebResourceIncludes = [
@@ -90,16 +85,8 @@ const vscodeWebEntryPoints = [
buildfile.entrypoint('vs/workbench/workbench.web.main.internal') // TODO@esm remove line when we stop supporting web-amd-esm-bridge buildfile.entrypoint('vs/workbench/workbench.web.main.internal') // TODO@esm remove line when we stop supporting web-amd-esm-bridge
].flat(); ].flat();
/** export const createVSCodeWebFileContentMapper = (extensionsRoot: string, product: typeof import('../product.json')) => {
* @param extensionsRoot {string} The location where extension will be read from return (path: string): ((content: string) => string) | undefined => {
* @param {object} product The parsed product.json file contents
*/
export const createVSCodeWebFileContentMapper = (extensionsRoot, product) => {
/**
* @param {string} path
* @returns {((content: string) => string) | undefined}
*/
return path => {
if (path.endsWith('vs/platform/product/common/product.js')) { if (path.endsWith('vs/platform/product/common/product.js')) {
return content => { return content => {
const productConfiguration = JSON.stringify({ const productConfiguration = JSON.stringify({
@@ -143,16 +130,12 @@ const minifyVSCodeWebTask = task.define('minify-vscode-web', task.series(
)); ));
gulp.task(minifyVSCodeWebTask); gulp.task(minifyVSCodeWebTask);
/** function packageTask(sourceFolderName: string, destinationFolderName: string) {
* @param {string} sourceFolderName
* @param {string} destinationFolderName
*/
function packageTask(sourceFolderName, destinationFolderName) {
const destination = path.join(BUILD_ROOT, destinationFolderName); const destination = path.join(BUILD_ROOT, destinationFolderName);
return () => { return () => {
const src = gulp.src(sourceFolderName + '/**', { base: '.' }) const src = gulp.src(sourceFolderName + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })); .pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); }));
const extensions = gulp.src('.build/web/extensions/**', { base: '.build/web', dot: true }); const extensions = gulp.src('.build/web/extensions/**', { base: '.build/web', dot: true });
@@ -218,7 +201,7 @@ const compileWebExtensionsBuildTask = task.define('compile-web-extensions-build'
)); ));
gulp.task(compileWebExtensionsBuildTask); gulp.task(compileWebExtensionsBuildTask);
const dashed = (/** @type {string} */ str) => (str ? `-${str}` : ``); const dashed = (str: string) => (str ? `-${str}` : ``);
['', 'min'].forEach(minified => { ['', 'min'].forEach(minified => {
const sourceFolderName = `out-vscode-web${dashed(minified)}`; const sourceFolderName = `out-vscode-web${dashed(minified)}`;

View File

@@ -17,15 +17,13 @@ import { createRequire } from 'module';
const require = createRequire(import.meta.url); const require = createRequire(import.meta.url);
const repoPath = path.dirname(import.meta.dirname); const repoPath = path.dirname(import.meta.dirname);
const buildPath = (/** @type {string} */ arch) => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`); const buildPath = (arch: string) => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`);
const setupDir = (/** @type {string} */ arch, /** @type {string} */ target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`); const setupDir = (arch: string, target: string) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
const issPath = path.join(import.meta.dirname, 'win32', 'code.iss'); const issPath = path.join(import.meta.dirname, 'win32', 'code.iss');
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup'))), 'bin', 'ISCC.exe'); const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup'))), 'bin', 'ISCC.exe');
const signWin32Path = path.join(repoPath, 'build', 'azure-pipelines', 'common', 'sign-win32.ts'); const signWin32Path = path.join(repoPath, 'build', 'azure-pipelines', 'common', 'sign-win32.ts');
function packageInnoSetup(iss, options, cb) { function packageInnoSetup(iss: string, options: { definitions?: Record<string, string> }, cb: (err?: Error | null) => void) {
options = options || {};
const definitions = options.definitions || {}; const definitions = options.definitions || {};
if (process.argv.some(arg => arg === '--debug-inno')) { if (process.argv.some(arg => arg === '--debug-inno')) {
@@ -58,16 +56,12 @@ function packageInnoSetup(iss, options, cb) {
}); });
} }
/** function buildWin32Setup(arch: string, target: string) {
* @param {string} arch
* @param {string} target
*/
function buildWin32Setup(arch, target) {
if (target !== 'system' && target !== 'user') { if (target !== 'system' && target !== 'user') {
throw new Error('Invalid setup target'); throw new Error('Invalid setup target');
} }
return cb => { return (cb?: (err?: any) => void) => {
const x64AppId = target === 'system' ? product.win32x64AppId : product.win32x64UserAppId; const x64AppId = target === 'system' ? product.win32x64AppId : product.win32x64UserAppId;
const arm64AppId = target === 'system' ? product.win32arm64AppId : product.win32arm64UserAppId; const arm64AppId = target === 'system' ? product.win32arm64AppId : product.win32arm64UserAppId;
@@ -81,8 +75,8 @@ function buildWin32Setup(arch, target) {
productJson['target'] = target; productJson['target'] = target;
fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t')); fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t'));
const quality = product.quality || 'dev'; const quality = (product as { quality?: string }).quality || 'dev';
const definitions = { const definitions: Record<string, any> = {
NameLong: product.nameLong, NameLong: product.nameLong,
NameShort: product.nameShort, NameShort: product.nameShort,
DirName: product.win32DirName, DirName: product.win32DirName,
@@ -117,15 +111,11 @@ function buildWin32Setup(arch, target) {
definitions['AppxPackageName'] = `${product.win32AppUserModelId}`; definitions['AppxPackageName'] = `${product.win32AppUserModelId}`;
} }
packageInnoSetup(issPath, { definitions }, cb); packageInnoSetup(issPath, { definitions }, cb as (err?: Error | null) => void);
}; };
} }
/** function defineWin32SetupTasks(arch: string, target: string) {
* @param {string} arch
* @param {string} target
*/
function defineWin32SetupTasks(arch, target) {
const cleanTask = util.rimraf(setupDir(arch, target)); const cleanTask = util.rimraf(setupDir(arch, target));
gulp.task(task.define(`vscode-win32-${arch}-${target}-setup`, task.series(cleanTask, buildWin32Setup(arch, target)))); gulp.task(task.define(`vscode-win32-${arch}-${target}-setup`, task.series(cleanTask, buildWin32Setup(arch, target))));
} }
@@ -135,20 +125,14 @@ defineWin32SetupTasks('arm64', 'system');
defineWin32SetupTasks('x64', 'user'); defineWin32SetupTasks('x64', 'user');
defineWin32SetupTasks('arm64', 'user'); defineWin32SetupTasks('arm64', 'user');
/** function copyInnoUpdater(arch: string) {
* @param {string} arch
*/
function copyInnoUpdater(arch) {
return () => { return () => {
return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' }) return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' })
.pipe(vfs.dest(path.join(buildPath(arch), 'tools'))); .pipe(vfs.dest(path.join(buildPath(arch), 'tools')));
}; };
} }
/** function updateIcon(executablePath: string): task.CallbackTask {
* @param {string} executablePath
*/
function updateIcon(executablePath) {
return cb => { return cb => {
const icon = path.join(repoPath, 'resources', 'win32', 'code.ico'); const icon = path.join(repoPath, 'resources', 'win32', 'code.ico');
rcedit(executablePath, { icon }, cb); rcedit(executablePath, { icon }, cb);

View File

@@ -30,7 +30,7 @@ interface VinylFileWithLines extends VinylFile {
/** /**
* Main hygiene function that runs checks on files * Main hygiene function that runs checks on files
*/ */
export function hygiene(some: NodeJS.ReadWriteStream | string[], runEslint = true): NodeJS.ReadWriteStream { export function hygiene(some: NodeJS.ReadWriteStream | string[] | undefined, runEslint = true): NodeJS.ReadWriteStream {
console.log('Starting hygiene...'); console.log('Starting hygiene...');
let errorCount = 0; let errorCount = 0;

View File

@@ -209,7 +209,7 @@ function bundleESMTask(opts: IBundleESMTaskOpts): NodeJS.ReadWriteStream {
})); }));
} }
export interface IBundleESMTaskOpts { export interface IBundleTaskOpts {
/** /**
* Destination folder for the bundled files. * Destination folder for the bundled files.
*/ */
@@ -220,7 +220,7 @@ export interface IBundleESMTaskOpts {
esm: IBundleESMTaskOpts; esm: IBundleESMTaskOpts;
} }
export function bundleTask(opts: IBundleESMTaskOpts): () => NodeJS.ReadWriteStream { export function bundleTask(opts: IBundleTaskOpts): () => NodeJS.ReadWriteStream {
return function () { return function () {
return bundleESMTask(opts.esm).pipe(gulp.dest(opts.out)); return bundleESMTask(opts.esm).pipe(gulp.dest(opts.out));
}; };

15
build/lib/typings/gulp-gunzip.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'gulp-gunzip' {
import type { Transform } from 'stream';
/**
* Gunzip plugin for gulp
*/
function gunzip(): Transform;
export = gunzip;
}

15
build/lib/typings/gulp-untar.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'gulp-untar' {
import type { Transform } from 'stream';
/**
* Extract TAR files
*/
function untar(): Transform;
export = untar;
}

5
build/lib/typings/rcedit.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
declare module 'rcedit' {
export default function rcedit(exePath, options, cb): Promise<void>;
}