gulpfile.vscode.js 26.3 KB
Newer Older
I
isidor 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

J
Joao Moreno 已提交
6 7 8 9
'use strict';

const gulp = require('gulp');
const fs = require('fs');
10 11
const os = require('os');
const cp = require('child_process');
J
Joao Moreno 已提交
12 13 14 15
const path = require('path');
const es = require('event-stream');
const azure = require('gulp-azure-storage');
const electron = require('gulp-atom-electron');
J
Joao Moreno 已提交
16
const vfs = require('vinyl-fs');
J
Joao Moreno 已提交
17 18 19 20 21 22
const rename = require('gulp-rename');
const replace = require('gulp-replace');
const filter = require('gulp-filter');
const json = require('gulp-json-editor');
const _ = require('underscore');
const util = require('./lib/util');
J
Joao Moreno 已提交
23
const ext = require('./lib/extensions');
J
Joao Moreno 已提交
24
const buildfile = require('../src/buildfile');
25
const common = require('./lib/optimize');
J
Joao Moreno 已提交
26 27
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
J
Joao Moreno 已提交
28 29
const packageJson = require('../package.json');
const product = require('../product.json');
A
Alex Dima 已提交
30
const crypto = require('crypto');
31
const i18n = require('./lib/i18n');
32
const deps = require('./dependencies');
J
Joao Moreno 已提交
33
const getElectronVersion = require('./lib/electron').getElectronVersion;
A
Alex Dima 已提交
34
const createAsar = require('./lib/asar').createAsar;
J
Joao Moreno 已提交
35

36
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
J
Joao Moreno 已提交
37
// @ts-ignore
J
Joao Moreno 已提交
38 39
const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n));
const nodeModules = ['electron', 'original-fs']
40
	// @ts-ignore JSON checking: dependencies property is optional
41 42
	.concat(Object.keys(product.dependencies || {}))
	.concat(_.uniq(productionDependencies.map(d => d.name)))
J
Joao Moreno 已提交
43
	.concat(baseModules);
I
isidor 已提交
44 45

// Build
J
Joao Moreno 已提交
46
const vscodeEntryPoints = _.flatten([
47
	buildfile.entrypoint('vs/workbench/workbench.main'),
I
isidor 已提交
48
	buildfile.base,
49 50
	buildfile.workbench,
	buildfile.code
I
isidor 已提交
51 52
]);

J
Joao Moreno 已提交
53
const vscodeResources = [
J
Joao Moreno 已提交
54
	'out-build/main.js',
J
Joao Moreno 已提交
55
	'out-build/cli.js',
J
Joao Moreno 已提交
56
	'out-build/driver.js',
I
isidor 已提交
57
	'out-build/bootstrap.js',
58
	'out-build/bootstrap-fork.js',
J
Joao Moreno 已提交
59
	'out-build/bootstrap-amd.js',
60
	'out-build/bootstrap-window.js',
J
Joao Moreno 已提交
61
	'out-build/paths.js',
J
Joao Moreno 已提交
62
	'out-build/vs/**/*.{svg,png,cur,html}',
63
	'out-build/vs/base/common/performance.js',
64
	'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}',
65
	'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
I
isidor 已提交
66 67 68
	'out-build/vs/workbench/browser/media/*-theme.css',
	'out-build/vs/workbench/parts/debug/**/*.json',
	'out-build/vs/workbench/parts/execution/**/*.scpt',
69
	'out-build/vs/workbench/parts/webview/electron-browser/webview-pre.js',
J
Joao Moreno 已提交
70
	'out-build/vs/**/markdown.css',
I
isidor 已提交
71
	'out-build/vs/workbench/parts/tasks/**/*.json',
72
	'out-build/vs/workbench/parts/welcome/walkThrough/**/*.md',
I
isidor 已提交
73 74
	'out-build/vs/workbench/services/files/**/*.exe',
	'out-build/vs/workbench/services/files/**/*.md',
75
	'out-build/vs/code/electron-browser/workbench/**',
76
	'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
77
	'out-build/vs/code/electron-browser/issue/issueReporter.js',
78
	'out-build/vs/code/electron-browser/processExplorer/processExplorer.js',
I
isidor 已提交
79 80 81
	'!**/test/**'
];

J
Joao Moreno 已提交
82
const BUNDLED_FILE_HEADER = [
I
isidor 已提交
83 84 85 86 87 88
	'/*!--------------------------------------------------------',
	' * Copyright (C) Microsoft Corporation. All rights reserved.',
	' *--------------------------------------------------------*/'
].join('\n');

gulp.task('clean-optimized-vscode', util.rimraf('out-vscode'));
J
Joao Moreno 已提交
89
gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compile-extensions-build'], common.optimizeTask({
90
	src: 'out-build',
I
isidor 已提交
91 92 93
	entryPoints: vscodeEntryPoints,
	otherSources: [],
	resources: vscodeResources,
94
	loaderConfig: common.loaderConfig(nodeModules),
I
isidor 已提交
95
	header: BUNDLED_FILE_HEADER,
96
	out: 'out-vscode',
E
Erich Gamma 已提交
97
	bundleInfo: undefined
I
isidor 已提交
98 99
}));

100 101

gulp.task('optimize-index-js', ['optimize-vscode'], () => {
102
	const fullpath = path.join(process.cwd(), 'out-vscode/vs/code/electron-browser/workbench/workbench.js');
103 104 105
	const contents = fs.readFileSync(fullpath).toString();
	const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules));
	fs.writeFileSync(fullpath, newContents);
B
Benjamin Pasero 已提交
106
});
107

108
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
I
isidor 已提交
109
gulp.task('clean-minified-vscode', util.rimraf('out-vscode-min'));
110
gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-index-js'], common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`));
I
isidor 已提交
111 112

// Package
113 114

// @ts-ignore JSON checking: darwinCredits is optional
J
Joao Moreno 已提交
115
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
I
isidor 已提交
116

117 118 119 120 121 122 123 124 125 126
function darwinBundleDocumentType(extensions, icon) {
	return {
		name: product.nameLong + ' document',
		role: 'Editor',
		ostypes: ["TEXT", "utxt", "TUTX", "****"],
		extensions: extensions,
		iconFile: icon
	};
}

J
Joao Moreno 已提交
127
const config = {
J
Joao Moreno 已提交
128
	version: getElectronVersion(),
I
isidor 已提交
129
	productAppName: product.nameLong,
J
Joao Moreno 已提交
130
	companyName: 'Microsoft Corporation',
131
	copyright: 'Copyright (C) 2018 Microsoft. All rights reserved',
J
Joao Moreno 已提交
132
	darwinIcon: 'resources/darwin/code.icns',
I
isidor 已提交
133
	darwinBundleIdentifier: product.darwinBundleIdentifier,
J
Joao Moreno 已提交
134
	darwinApplicationCategoryType: 'public.app-category.developer-tools',
135 136
	darwinHelpBookFolder: 'VS Code HelpBook',
	darwinHelpBookName: 'VS Code HelpBook',
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	darwinBundleDocumentTypes: [
		darwinBundleDocumentType(["bat", "cmd"], 'resources/darwin/bat.icns'),
		darwinBundleDocumentType(["bowerrc"], 'resources/darwin/bower.icns'),
		darwinBundleDocumentType(["c", "h"], 'resources/darwin/c.icns'),
		darwinBundleDocumentType(["config", "editorconfig", "gitattributes", "gitconfig", "gitignore", "ini"], 'resources/darwin/config.icns'),
		darwinBundleDocumentType(["cc", "cpp", "cxx", "hh", "hpp", "hxx"], 'resources/darwin/cpp.icns'),
		darwinBundleDocumentType(["cs", "csx"], 'resources/darwin/csharp.icns'),
		darwinBundleDocumentType(["css"], 'resources/darwin/css.icns'),
		darwinBundleDocumentType(["go"], 'resources/darwin/go.icns'),
		darwinBundleDocumentType(["asp", "aspx", "cshtml", "htm", "html", "jshtm", "phtml", "shtml"], 'resources/darwin/html.icns'),
		darwinBundleDocumentType(["jade"], 'resources/darwin/jade.icns'),
		darwinBundleDocumentType(["jav", "java"], 'resources/darwin/java.icns'),
		darwinBundleDocumentType(["js", "jscsrc", "jshintrc"], 'resources/darwin/javascript.icns'),
		darwinBundleDocumentType(["json"], 'resources/darwin/json.icns'),
		darwinBundleDocumentType(["less"], 'resources/darwin/less.icns'),
		darwinBundleDocumentType(["markdown", "md", "mdoc", "mdown", "mdtext", "mdtxt", "mdwn", "mkd", "mkdn"], 'resources/darwin/markdown.icns'),
		darwinBundleDocumentType(["php"], 'resources/darwin/php.icns'),
		darwinBundleDocumentType(["ps1", "psd1", "psm1"], 'resources/darwin/powershell.icns'),
		darwinBundleDocumentType(["py"], 'resources/darwin/python.icns'),
		darwinBundleDocumentType(["gemspec", "rb"], 'resources/darwin/ruby.icns'),
		darwinBundleDocumentType(["scss"], 'resources/darwin/scss.icns'),
		darwinBundleDocumentType(["bash", "bash_login", "bash_logout", "bash_profile", "bashrc", "profile", "rhistory", "rprofile", "sh", "zlogin", "zlogout", "zprofile", "zsh", "zshenv", "zshrc"], 'resources/darwin/shell.icns'),
		darwinBundleDocumentType(["sql"], 'resources/darwin/sql.icns'),
		darwinBundleDocumentType(["ts"], 'resources/darwin/typescript.icns'),
		darwinBundleDocumentType(["tsx", "jsx"], 'resources/darwin/react.icns'),
		darwinBundleDocumentType(["vue"], 'resources/darwin/vue.icns'),
		darwinBundleDocumentType(["ascx", "csproj", "dtd", "wxi", "wxl", "wxs", "xml", "xaml"], 'resources/darwin/xml.icns'),
		darwinBundleDocumentType(["eyaml", "eyml", "yaml", "yml"], 'resources/darwin/yaml.icns'),
		darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "jsp", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns')
	],
J
Joao Moreno 已提交
167 168 169
	darwinBundleURLTypes: [{
		role: 'Viewer',
		name: product.nameLong,
J
Joao Moreno 已提交
170
		urlSchemes: [product.urlProtocol]
J
Joao Moreno 已提交
171
	}],
172
	darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
173
	linuxExecutableName: product.applicationName,
J
Joao Moreno 已提交
174
	winIcon: 'resources/win32/code.ico',
175
	token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || void 0,
176 177

	// @ts-ignore JSON checking: electronRepository is optional
178
	repo: product.electronRepository || void 0
I
isidor 已提交
179 180
};

J
fix es6  
Joao Moreno 已提交
181
function getElectron(arch) {
J
Joao Moreno 已提交
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	return () => {
		const electronOpts = _.extend({}, config, {
			platform: process.platform,
			arch,
			ffmpegChromium: true,
			keepDefaultApp: true
		});

		return gulp.src('package.json')
			.pipe(json({ name: product.nameShort }))
			.pipe(electron(electronOpts))
			.pipe(filter(['**', '!**/app/package.json']))
			.pipe(vfs.dest('.build/electron'));
	};
}
197

J
Joao Moreno 已提交
198
gulp.task('clean-electron', util.rimraf('.build/electron'));
J
fix es6  
Joao Moreno 已提交
199
gulp.task('electron', ['clean-electron'], getElectron(process.arch));
J
Joao Moreno 已提交
200 201
gulp.task('electron-ia32', ['clean-electron'], getElectron('ia32'));
gulp.task('electron-x64', ['clean-electron'], getElectron('x64'));
202 203
gulp.task('electron-arm', ['clean-electron'], getElectron('arm'));
gulp.task('electron-arm64', ['clean-electron'], getElectron('arm64'));
I
isidor 已提交
204 205


A
Alex Dima 已提交
206 207 208 209 210 211 212 213 214
/**
 * 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) {
	var result = {};
215
	filenames.forEach(function (filename) {
A
Alex Dima 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
		var fullPath = path.join(process.cwd(), out, filename);
		result[filename] = computeChecksum(fullPath);
	});
	return result;
}

/**
 * Compute checksum for a file.
 *
 * @param {string} filename The absolute path to a filename.
 * @return {string} The checksum for `filename`.
 */
function computeChecksum(filename) {
	var contents = fs.readFileSync(filename);

	var hash = crypto
		.createHash('md5')
		.update(contents)
		.digest('base64')
		.replace(/=+$/, '');

	return hash;
}

J
fix es6  
Joao Moreno 已提交
240 241 242
function packageTask(platform, arch, opts) {
	opts = opts || {};

J
Joao Moreno 已提交
243
	const destination = path.join(path.dirname(root), 'VSCode') + (platform ? '-' + platform : '') + (arch ? '-' + arch : '');
I
isidor 已提交
244 245
	platform = platform || process.platform;

J
Joao Moreno 已提交
246 247
	return () => {
		const out = opts.minified ? 'out-vscode-min' : 'out-vscode';
I
isidor 已提交
248

A
Alex Dima 已提交
249
		const checksums = computeChecksums(out, [
250 251
			'vs/workbench/workbench.main.js',
			'vs/workbench/workbench.main.css',
252 253
			'vs/code/electron-browser/workbench/workbench.html',
			'vs/code/electron-browser/workbench/workbench.js'
A
Alex Dima 已提交
254 255
		]);

J
Joao Moreno 已提交
256
		const src = gulp.src(out + '/**', { base: '.' })
257 258 259
			.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); }))
			.pipe(util.setExecutableBit(['**/*.sh']))
			.pipe(filter(['**', '!**/*.js.map']));
I
isidor 已提交
260

261 262
		const root = path.resolve(path.join(__dirname, '..'));

263 264
		const sources = es.merge(src, ext.packageExtensionsStream({
			sourceMappingURLBase: sourceMappingURLBase
265 266
		}));

J
Joao Moreno 已提交
267
		let version = packageJson.version;
268
		// @ts-ignore JSON checking: quality is optional
J
Joao Moreno 已提交
269
		const quality = product.quality;
J
Joao Moreno 已提交
270 271 272 273 274

		if (quality && quality !== 'stable') {
			version += '-' + quality;
		}

J
Joao Moreno 已提交
275
		const name = product.nameShort;
276 277 278 279 280 281 282
		const packageJsonUpdates = { name, version };

		// for linux url handling
		if (platform === 'linux') {
			packageJsonUpdates.desktopName = `${product.applicationName}-url-handler.desktop`;
		}

J
Joao Moreno 已提交
283
		const packageJsonStream = gulp.src(['package.json'], { base: '.' })
284
			.pipe(json(packageJsonUpdates));
J
Joao Moreno 已提交
285 286

		const date = new Date().toISOString();
287 288
		const productJsonUpdate = { commit, date, checksums };

289
		if (shouldSetupSettingsSearch()) {
290 291 292
			productJsonUpdate.settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
		}

J
Joao Moreno 已提交
293
		const productJsonStream = gulp.src(['product.json'], { base: '.' })
294
			.pipe(json(productJsonUpdate));
I
isidor 已提交
295

296
		const license = gulp.src(['LICENSES.chromium.html', 'LICENSE.txt', 'ThirdPartyNotices.txt', 'licenses/**'], { base: '.' });
I
isidor 已提交
297

298 299
		const watermark = gulp.src(['resources/letterpress.svg', 'resources/letterpress-dark.svg', 'resources/letterpress-hc.svg'], { base: '.' });

J
Joao Moreno 已提交
300 301 302
		// TODO the API should be copied to `out` during compile, not here
		const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts'));

303 304
		const depsSrc = [
			..._.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])),
305
			// @ts-ignore JSON checking: dependencies is optional
306 307
			..._.flatten(Object.keys(product.dependencies || {}).map(d => [`node_modules/${d}/**`, `!node_modules/${d}/**/{test,tests}/**`]))
		];
I
isidor 已提交
308

J
Joao Moreno 已提交
309
		const deps = gulp.src(depsSrc, { base: '.', dot: true })
J
Joao Moreno 已提交
310
			.pipe(filter(['**', '!**/package-lock.json']))
J
Joao Moreno 已提交
311
			.pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], ['**/*.node']))
312
			.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/*.js']))
J
Joao Moreno 已提交
313 314
			.pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
			.pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node']))
315
			.pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node']))
316
			.pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
J
Joao Moreno 已提交
317
			.pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['**/*.node']))
B
Benjamin Pasero 已提交
318
			.pipe(util.cleanNodeModule('jschardet', ['dist/**']))
319
			.pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
A
Amy Qiu 已提交
320
			.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
321
			.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
C
Christof Marti 已提交
322
			.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
323
			.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node']))
324
			.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
A
Alex Dima 已提交
325 326
			.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
			.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
I
isidor 已提交
327

J
Joao Moreno 已提交
328
		let all = es.merge(
J
Joao Moreno 已提交
329
			packageJsonStream,
J
Joao Moreno 已提交
330
			productJsonStream,
I
isidor 已提交
331
			license,
332
			watermark,
J
Joao Moreno 已提交
333
			api,
I
isidor 已提交
334
			sources,
J
Joao Moreno 已提交
335
			deps
J
Joao Moreno 已提交
336 337 338
		);

		if (platform === 'win32') {
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
			all = es.merge(all, gulp.src([
				'resources/win32/bower.ico',
				'resources/win32/c.ico',
				'resources/win32/config.ico',
				'resources/win32/cpp.ico',
				'resources/win32/csharp.ico',
				'resources/win32/css.ico',
				'resources/win32/default.ico',
				'resources/win32/go.ico',
				'resources/win32/html.ico',
				'resources/win32/jade.ico',
				'resources/win32/java.ico',
				'resources/win32/javascript.ico',
				'resources/win32/json.ico',
				'resources/win32/less.ico',
				'resources/win32/markdown.ico',
				'resources/win32/php.ico',
				'resources/win32/powershell.ico',
				'resources/win32/python.ico',
				'resources/win32/react.ico',
				'resources/win32/ruby.ico',
				'resources/win32/sass.ico',
				'resources/win32/shell.ico',
				'resources/win32/sql.ico',
				'resources/win32/typescript.ico',
				'resources/win32/vue.ico',
				'resources/win32/xml.ico',
				'resources/win32/yaml.ico',
				'resources/win32/code_70x70.png',
				'resources/win32/code_150x150.png'
			], { base: '.' }));
J
Joao Moreno 已提交
370 371
		} else if (platform === 'linux') {
			all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' }));
J
Joao Moreno 已提交
372
		} else if (platform === 'darwin') {
J
Joao Moreno 已提交
373
			const shortcut = gulp.src('resources/darwin/bin/code.sh')
J
Joao Moreno 已提交
374 375 376
				.pipe(rename('bin/code'));

			all = es.merge(all, shortcut);
J
Joao Moreno 已提交
377
		}
I
isidor 已提交
378

J
Joao Moreno 已提交
379
		let result = all
J
Joao Moreno 已提交
380
			.pipe(util.skipDirectories())
I
isidor 已提交
381
			.pipe(util.fixWin32DirectoryPermissions())
382
			.pipe(electron(_.extend({}, config, { platform, arch, ffmpegChromium: true })))
383
			.pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version']));
I
isidor 已提交
384 385

		if (platform === 'win32') {
J
typo  
João Moreno 已提交
386
			result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32' }));
J
Joao Moreno 已提交
387

J
typo  
João Moreno 已提交
388
			result = es.merge(result, gulp.src('resources/win32/bin/code.cmd', { base: 'resources/win32' })
J
Joao Moreno 已提交
389
				.pipe(replace('@@NAME@@', product.nameShort))
J
Joao Moreno 已提交
390 391
				.pipe(rename(function (f) { f.basename = product.applicationName; })));

J
typo  
João Moreno 已提交
392
			result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
J
Joao Moreno 已提交
393 394
				.pipe(replace('@@NAME@@', product.nameShort))
				.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
395 396

			result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
397
				.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
398 399 400 401
		} else if (platform === 'linux') {
			result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
				.pipe(replace('@@NAME@@', product.applicationName))
				.pipe(rename('bin/' + product.applicationName)));
I
isidor 已提交
402 403
		}

J
Johannes Rieken 已提交
404 405 406 407 408
		// submit all stats that have been collected
		// during the build phase
		if (opts.stats) {
			result.on('end', () => {
				const { submitAllStats } = require('./lib/stats');
J
Johannes Rieken 已提交
409
				submitAllStats(product, commit).then(() => console.log('Submitted bundle stats!'));
J
Johannes Rieken 已提交
410 411 412
			});
		}

J
Joao Moreno 已提交
413
		return result.pipe(vfs.dest(destination));
I
isidor 已提交
414 415 416
	};
}

J
Joao Moreno 已提交
417 418
const buildRoot = path.dirname(root);

J
Joao Moreno 已提交
419 420
gulp.task('clean-vscode-win32-ia32', util.rimraf(path.join(buildRoot, 'VSCode-win32-ia32')));
gulp.task('clean-vscode-win32-x64', util.rimraf(path.join(buildRoot, 'VSCode-win32-x64')));
J
Joao Moreno 已提交
421 422 423 424
gulp.task('clean-vscode-darwin', util.rimraf(path.join(buildRoot, 'VSCode-darwin')));
gulp.task('clean-vscode-linux-ia32', util.rimraf(path.join(buildRoot, 'VSCode-linux-ia32')));
gulp.task('clean-vscode-linux-x64', util.rimraf(path.join(buildRoot, 'VSCode-linux-x64')));
gulp.task('clean-vscode-linux-arm', util.rimraf(path.join(buildRoot, 'VSCode-linux-arm')));
A
ava1ar 已提交
425
gulp.task('clean-vscode-linux-arm64', util.rimraf(path.join(buildRoot, 'VSCode-linux-arm64')));
I
isidor 已提交
426

J
Joao Moreno 已提交
427 428
gulp.task('vscode-win32-ia32', ['optimize-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32'));
gulp.task('vscode-win32-x64', ['optimize-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64'));
429
gulp.task('vscode-darwin', ['optimize-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { stats: true }));
I
isidor 已提交
430 431
gulp.task('vscode-linux-ia32', ['optimize-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32'));
gulp.task('vscode-linux-x64', ['optimize-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64'));
432
gulp.task('vscode-linux-arm', ['optimize-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm'));
A
ava1ar 已提交
433
gulp.task('vscode-linux-arm64', ['optimize-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64'));
I
isidor 已提交
434

J
Joao Moreno 已提交
435 436
gulp.task('vscode-win32-ia32-min', ['minify-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32', { minified: true }));
gulp.task('vscode-win32-x64-min', ['minify-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64', { minified: true }));
437
gulp.task('vscode-darwin-min', ['minify-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { minified: true, stats: true }));
I
isidor 已提交
438 439
gulp.task('vscode-linux-ia32-min', ['minify-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32', { minified: true }));
gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64', { minified: true }));
440
gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true }));
A
ava1ar 已提交
441
gulp.task('vscode-linux-arm64-min', ['minify-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64', { minified: true }));
I
isidor 已提交
442

443
// Transifex Localizations
D
Dirk Baeumer 已提交
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

const innoSetupConfig = {
	'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } },
	'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } },
	'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } },
	'ja': { codePage: 'CP932' },
	'de': { codePage: 'CP1252' },
	'fr': { codePage: 'CP1252' },
	'es': { codePage: 'CP1252' },
	'ru': { codePage: 'CP1251' },
	'it': { codePage: 'CP1252' },
	'pt-br': { codePage: 'CP1252' },
	'hu': { codePage: 'CP1250' },
	'tr': { codePage: 'CP1254' }
};
459

460
const apiHostname = process.env.TRANSIFEX_API_URL;
461 462 463
const apiName = process.env.TRANSIFEX_API_NAME;
const apiToken = process.env.TRANSIFEX_API_TOKEN;

J
Joao Moreno 已提交
464
gulp.task('vscode-translations-push', ['optimize-vscode'], function () {
465
	const pathToMetadata = './out-vscode/nls.metadata.json';
D
Dirk Baeumer 已提交
466
	const pathToExtensions = './extensions/*';
467 468
	const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';

469
	return es.merge(
D
Dirk Baeumer 已提交
470 471 472
		gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
		gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
		gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
473
	).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
J
Joao Moreno 已提交
474
	).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken));
475 476
});

J
Joao Moreno 已提交
477
gulp.task('vscode-translations-push-test', ['optimize-vscode'], function () {
D
Dirk Baeumer 已提交
478 479 480 481
	const pathToMetadata = './out-vscode/nls.metadata.json';
	const pathToExtensions = './extensions/*';
	const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';

482
	return es.merge(
D
Dirk Baeumer 已提交
483 484 485
		gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
		gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
		gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
486
	).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
J
Joao Moreno 已提交
487
	).pipe(vfs.dest('../vscode-transifex-input'));
D
Dirk Baeumer 已提交
488 489 490
});

gulp.task('vscode-translations-pull', function () {
491
	return es.merge([...i18n.defaultLanguages, ...i18n.extraLanguages].map(language => {
D
Dirk Baeumer 已提交
492
		let includeDefault = !!innoSetupConfig[language.id].defaultInfo;
493 494
		return i18n.pullSetupXlfFiles(apiHostname, apiName, apiToken, language, includeDefault).pipe(vfs.dest(`../vscode-localization/${language.id}/setup`));
	}));
495 496
});

497
gulp.task('vscode-translations-import', function () {
498
	return es.merge([...i18n.defaultLanguages, ...i18n.extraLanguages].map(language => {
499
		return gulp.src(`../vscode-localization/${language.id}/setup/*/*.xlf`)
D
Dirk Baeumer 已提交
500 501
			.pipe(i18n.prepareIslFiles(language, innoSetupConfig[language.id]))
			.pipe(vfs.dest(`./build/win32/i18n`));
502
	}));
503 504
});

I
isidor 已提交
505 506
// Sourcemaps

J
Johannes Rieken 已提交
507
gulp.task('upload-vscode-sourcemaps', ['vscode-darwin-min', 'minify-vscode'], () => {
J
Joao Moreno 已提交
508 509
	const vs = gulp.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' })
		.pipe(es.mapSync(f => {
510
			f.path = `${f.base}/core/${f.relative}`;
J
Joao Moreno 已提交
511 512 513
			return f;
		}));

514 515
	const extensionsOut = gulp.src('extensions/**/out/**/*.map', { base: '.' });
	const extensionsDist = gulp.src('extensions/**/dist/**/*.map', { base: '.' });
J
Joao Moreno 已提交
516

517
	return es.merge(vs, extensionsOut, extensionsDist)
J
Johannes Rieken 已提交
518 519 520 521 522
		.pipe(es.through(function (data) {
			// debug
			console.log('Uploading Sourcemap', data.relative);
			this.emit('data', data);
		}))
I
isidor 已提交
523 524 525 526
		.pipe(azure.upload({
			account: process.env.AZURE_STORAGE_ACCOUNT,
			key: process.env.AZURE_STORAGE_ACCESS_KEY,
			container: 'sourcemaps',
J
Joao Moreno 已提交
527
			prefix: commit + '/'
I
isidor 已提交
528
		}));
529
});
530 531 532

const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => {
533 534
	if (!shouldSetupSettingsSearch()) {
		const branch = process.env.BUILD_SOURCEBRANCH;
535 536 537 538
		console.log(`Only runs on master and release branches, not ${branch}`);
		return;
	}

539
	if (!fs.existsSync(allConfigDetailsPath)) {
540
		throw new Error(`configuration file at ${allConfigDetailsPath} does not exist`);
541 542
	}

543
	const settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
544
	if (!settingsSearchBuildId) {
545
		throw new Error('Failed to compute build number');
R
Rob Lourens 已提交
546 547
	}

548 549 550 551 552
	return gulp.src(allConfigDetailsPath)
		.pipe(azure.upload({
			account: process.env.AZURE_STORAGE_ACCOUNT,
			key: process.env.AZURE_STORAGE_ACCESS_KEY,
			container: 'configuration',
553
			prefix: `${settingsSearchBuildId}/${commit}/`
554 555 556
		}));
});

557 558 559 560
function shouldSetupSettingsSearch() {
	const branch = process.env.BUILD_SOURCEBRANCH;
	return branch && (/\/master$/.test(branch) || branch.indexOf('/release/') >= 0);
}
R
Rob Lourens 已提交
561

562
function getSettingsSearchBuildId(packageJson) {
R
Rob Lourens 已提交
563
	try {
564 565 566
		const branch = process.env.BUILD_SOURCEBRANCH;
		const branchId = branch.indexOf('/release/') >= 0 ? 0 :
			/\/master$/.test(branch) ? 1 :
567
				2; // Some unexpected branch
568

R
Rob Lourens 已提交
569
		const out = cp.execSync(`git rev-list HEAD --count`);
R
Rob Lourens 已提交
570
		const count = parseInt(out.toString());
571 572 573 574

		// <version number><commit count><branchId (avoid unlikely conflicts)>
		// 1.25.1, 1,234,567 commits, master = 1250112345671
		return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId;
R
Rob Lourens 已提交
575
	} catch (e) {
576
		throw new Error('Could not determine build number: ' + e.toString());
R
Rob Lourens 已提交
577 578 579
	}
}

580
// This task is only run for the MacOS build
581 582 583 584 585 586 587
gulp.task('generate-vscode-configuration', () => {
	return new Promise((resolve, reject) => {
		const buildDir = process.env['AGENT_BUILDDIRECTORY'];
		if (!buildDir) {
			return reject(new Error('$AGENT_BUILDDIRECTORY not set'));
		}

J
Joao Moreno 已提交
588 589 590 591
		if (process.env.VSCODE_QUALITY !== 'insider' && process.env.VSCODE_QUALITY !== 'stable') {
			return resolve();
		}

592 593
		const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
		const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
594 595
		const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
		const appPath = path.join(buildDir, `VSCode-darwin/${appName}/Contents/Resources/app/bin/code`);
596
		const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`);
597 598 599

		const timer = setTimeout(() => {
			codeProc.kill();
600
			reject(new Error('export-default-configuration process timed out'));
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
		}, 10 * 1000);

		codeProc.stdout.on('data', d => console.log(d.toString()));
		codeProc.stderr.on('data', d => console.log(d.toString()));

		codeProc.on('exit', () => {
			clearTimeout(timer);
			resolve();
		});

		codeProc.on('error', err => {
			clearTimeout(timer);
			reject(err);
		});
	});
});