gulpfile.vscode.js 26.6 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
	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'),
B
Benjamin Pasero 已提交
146
		darwinBundleDocumentType(["asp", "aspx", "cshtml", "htm", "html", "jshtm", "jsp", "phtml", "shtml"], 'resources/darwin/html.icns'),
147 148
		darwinBundleDocumentType(["jade"], 'resources/darwin/jade.icns'),
		darwinBundleDocumentType(["jav", "java"], 'resources/darwin/java.icns'),
B
Benjamin Pasero 已提交
149
		darwinBundleDocumentType(["js", "jscsrc", "jshintrc", "mjs"], 'resources/darwin/javascript.icns'),
150 151 152 153 154 155 156
		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'),
M
Miguel Solorio 已提交
157
		darwinBundleDocumentType(["scss"], 'resources/darwin/sass.icns'),
158 159 160 161 162 163 164
		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'),
B
Benjamin Pasero 已提交
165
		darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "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')
166
	],
J
Joao Moreno 已提交
167 168 169
	darwinBundleURLTypes: [{
		role: 'Viewer',
		name: product.nameLong,
J
Joao Moreno 已提交
170
		urlSchemes: [product.urlProtocol]
J
Joao Moreno 已提交
171
	}],
172
	darwinForceDarkModeSupport: true,
173
	darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
174
	linuxExecutableName: product.applicationName,
J
Joao Moreno 已提交
175
	winIcon: 'resources/win32/code.ico',
176
	token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || void 0,
177 178

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

J
fix es6  
Joao Moreno 已提交
182
function getElectron(arch) {
J
Joao Moreno 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
	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'));
	};
}
198

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


A
Alex Dima 已提交
207 208 209 210 211 212 213 214 215
/**
 * 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 = {};
216
	filenames.forEach(function (filename) {
A
Alex Dima 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
		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 已提交
241 242 243
function packageTask(platform, arch, opts) {
	opts = opts || {};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

J
Joao Moreno 已提交
301 302 303
		// 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'));

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

J
Joao Moreno 已提交
310
		const deps = gulp.src(depsSrc, { base: '.', dot: true })
J
Joao Moreno 已提交
311
			.pipe(filter(['**', '!**/package-lock.json']))
J
Joao Moreno 已提交
312
			.pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], ['**/*.node']))
313 314
			.pipe(util.cleanNodeModule('vscode-sqlite3', ['binding.gyp', 'benchmark/**', 'cloudformation/**', 'deps/**', 'test/**', 'build/**', 'src/**'], ['build/Release/*.node']))
			.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/*.js']))
J
Joao Moreno 已提交
315
			.pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
316 317 318 319
			.pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node']))
			.pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node']))
			.pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['build/Release/*.node']))
			.pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['build/Release/*.node']))
B
Benjamin Pasero 已提交
320
			.pipe(util.cleanNodeModule('jschardet', ['dist/**']))
321
			.pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
A
Amy Qiu 已提交
322
			.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
323
			.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/index.js']))
C
Christof Marti 已提交
324
			.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
325
			.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node']))
326
			.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['build/Release/*.node', '**/*.a']))
A
Alex Dima 已提交
327 328
			.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 已提交
329

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

		if (platform === 'win32') {
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 370 371
			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 已提交
372 373
		} else if (platform === 'linux') {
			all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' }));
J
Joao Moreno 已提交
374
		} else if (platform === 'darwin') {
J
Joao Moreno 已提交
375
			const shortcut = gulp.src('resources/darwin/bin/code.sh')
J
Joao Moreno 已提交
376 377 378
				.pipe(rename('bin/code'));

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

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

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

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

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

			result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
399
				.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
400 401 402 403
		} 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 已提交
404 405
		}

J
Johannes Rieken 已提交
406 407 408 409 410
		// 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 已提交
411
				submitAllStats(product, commit).then(() => console.log('Submitted bundle stats!'));
J
Johannes Rieken 已提交
412 413 414
			});
		}

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

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

J
Joao Moreno 已提交
421 422
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 已提交
423 424 425 426
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 已提交
427
gulp.task('clean-vscode-linux-arm64', util.rimraf(path.join(buildRoot, 'VSCode-linux-arm64')));
I
isidor 已提交
428

J
Joao Moreno 已提交
429 430
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'));
431
gulp.task('vscode-darwin', ['optimize-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { stats: true }));
I
isidor 已提交
432 433
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'));
434
gulp.task('vscode-linux-arm', ['optimize-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm'));
A
ava1ar 已提交
435
gulp.task('vscode-linux-arm64', ['optimize-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64'));
I
isidor 已提交
436

J
Joao Moreno 已提交
437 438
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 }));
439
gulp.task('vscode-darwin-min', ['minify-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { minified: true, stats: true }));
I
isidor 已提交
440 441
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 }));
442
gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true }));
A
ava1ar 已提交
443
gulp.task('vscode-linux-arm64-min', ['minify-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64', { minified: true }));
I
isidor 已提交
444

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

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' }
};
461

462
const apiHostname = process.env.TRANSIFEX_API_URL;
463 464 465
const apiName = process.env.TRANSIFEX_API_NAME;
const apiToken = process.env.TRANSIFEX_API_TOKEN;

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

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

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

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

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

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

I
isidor 已提交
507 508
// Sourcemaps

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

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

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

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

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

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

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

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

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

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

		// <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 已提交
577
	} catch (e) {
578
		throw new Error('Could not determine build number: ' + e.toString());
R
Rob Lourens 已提交
579 580 581
	}
}

582
// This task is only run for the MacOS build
583 584 585 586 587 588 589
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 已提交
590 591 592 593
		if (process.env.VSCODE_QUALITY !== 'insider' && process.env.VSCODE_QUALITY !== 'stable') {
			return resolve();
		}

594 595
		const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
		const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
596 597
		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`);
598
		const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`);
599 600 601

		const timer = setTimeout(() => {
			codeProc.kill();
602
			reject(new Error('export-default-configuration process timed out'));
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
		}, 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);
		});
	});
});