mirror of
https://github.com/coder/code-server.git
synced 2024-12-02 16:28:30 +03:00
eae5d8c807
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
278 lines
13 KiB
JavaScript
278 lines
13 KiB
JavaScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
'use strict';
|
|
|
|
const gulp = require('gulp');
|
|
const replace = require('gulp-replace');
|
|
const rename = require('gulp-rename');
|
|
const shell = require('gulp-shell');
|
|
const es = require('event-stream');
|
|
const vfs = require('vinyl-fs');
|
|
const util = require('./lib/util');
|
|
const task = require('./lib/task');
|
|
const packageJson = require('../package.json');
|
|
const product = require('../product.json');
|
|
const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
|
|
const path = require('path');
|
|
const root = path.dirname(__dirname);
|
|
const commit = util.getVersion(root);
|
|
|
|
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
|
|
|
|
function getDebPackageArch(arch) {
|
|
return { x64: 'amd64', armhf: 'armhf', arm64: 'arm64' }[arch];
|
|
}
|
|
|
|
function prepareDebPackage(arch) {
|
|
const binaryDir = '../VSCode-linux-' + arch;
|
|
const debArch = getDebPackageArch(arch);
|
|
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
|
|
|
|
return function () {
|
|
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
|
|
.pipe(rename('usr/share/applications/' + product.applicationName + '.desktop'));
|
|
|
|
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
|
|
.pipe(rename('usr/share/applications/' + product.applicationName + '-url-handler.desktop'));
|
|
|
|
const desktops = es.merge(desktop, desktopUrlHandler)
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@EXEC@@', `/usr/share/${product.applicationName}/${product.applicationName}`))
|
|
.pipe(replace('@@ICON@@', product.linuxIconName))
|
|
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
|
|
|
|
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@LICENSE@@', product.licenseName))
|
|
.pipe(rename('usr/share/appdata/' + product.applicationName + '.appdata.xml'));
|
|
|
|
const workspaceMime = gulp.src('resources/linux/code-workspace.xml', { base: '.' })
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(rename('usr/share/mime/packages/' + product.applicationName + '-workspace.xml'));
|
|
|
|
const icon = gulp.src('resources/linux/code.png', { base: '.' })
|
|
.pipe(rename('usr/share/pixmaps/' + product.linuxIconName + '.png'));
|
|
|
|
const bash_completion = gulp.src('resources/completions/bash/code')
|
|
.pipe(replace('@@APPNAME@@', product.applicationName))
|
|
.pipe(rename('usr/share/bash-completion/completions/' + product.applicationName));
|
|
|
|
const zsh_completion = gulp.src('resources/completions/zsh/_code')
|
|
.pipe(replace('@@APPNAME@@', product.applicationName))
|
|
.pipe(rename('usr/share/zsh/vendor-completions/_' + product.applicationName));
|
|
|
|
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
|
|
.pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; }));
|
|
|
|
let size = 0;
|
|
const control = code.pipe(es.through(
|
|
function (f) { size += f.isDirectory() ? 4096 : f.contents.length; },
|
|
function () {
|
|
const that = this;
|
|
gulp.src('resources/linux/debian/control.template', { base: '.' })
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@VERSION@@', packageJson.version + '-' + linuxPackageRevision))
|
|
.pipe(replace('@@ARCHITECTURE@@', debArch))
|
|
.pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024)))
|
|
.pipe(rename('DEBIAN/control'))
|
|
.pipe(es.through(function (f) { that.emit('data', f); }, function () { that.emit('end'); }));
|
|
}));
|
|
|
|
const prerm = gulp.src('resources/linux/debian/prerm.template', { base: '.' })
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(rename('DEBIAN/prerm'));
|
|
|
|
const postrm = gulp.src('resources/linux/debian/postrm.template', { base: '.' })
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(rename('DEBIAN/postrm'));
|
|
|
|
const postinst = gulp.src('resources/linux/debian/postinst.template', { base: '.' })
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(rename('DEBIAN/postinst'));
|
|
|
|
const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, workspaceMime, icon, bash_completion, zsh_completion, code);
|
|
|
|
return all.pipe(vfs.dest(destination));
|
|
};
|
|
}
|
|
|
|
function buildDebPackage(arch) {
|
|
const debArch = getDebPackageArch(arch);
|
|
return shell.task([
|
|
'chmod 755 ' + product.applicationName + '-' + debArch + '/DEBIAN/postinst ' + product.applicationName + '-' + debArch + '/DEBIAN/prerm ' + product.applicationName + '-' + debArch + '/DEBIAN/postrm',
|
|
'mkdir -p deb',
|
|
'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb'
|
|
], { cwd: '.build/linux/deb/' + debArch });
|
|
}
|
|
|
|
function getRpmBuildPath(rpmArch) {
|
|
return '.build/linux/rpm/' + rpmArch + '/rpmbuild';
|
|
}
|
|
|
|
function getRpmPackageArch(arch) {
|
|
return { x64: 'x86_64', armhf: 'armv7hl', arm64: 'aarch64' }[arch];
|
|
}
|
|
|
|
function prepareRpmPackage(arch) {
|
|
const binaryDir = '../VSCode-linux-' + arch;
|
|
const rpmArch = getRpmPackageArch(arch);
|
|
|
|
return function () {
|
|
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
|
|
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '.desktop'));
|
|
|
|
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
|
|
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '-url-handler.desktop'));
|
|
|
|
const desktops = es.merge(desktop, desktopUrlHandler)
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@EXEC@@', `/usr/share/${product.applicationName}/${product.applicationName}`))
|
|
.pipe(replace('@@ICON@@', product.linuxIconName))
|
|
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
|
|
|
|
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@LICENSE@@', product.licenseName))
|
|
.pipe(rename('usr/share/appdata/' + product.applicationName + '.appdata.xml'));
|
|
|
|
const workspaceMime = gulp.src('resources/linux/code-workspace.xml', { base: '.' })
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(rename('BUILD/usr/share/mime/packages/' + product.applicationName + '-workspace.xml'));
|
|
|
|
const icon = gulp.src('resources/linux/code.png', { base: '.' })
|
|
.pipe(rename('BUILD/usr/share/pixmaps/' + product.linuxIconName + '.png'));
|
|
|
|
const bash_completion = gulp.src('resources/completions/bash/code')
|
|
.pipe(replace('@@APPNAME@@', product.applicationName))
|
|
.pipe(rename('BUILD/usr/share/bash-completion/completions/' + product.applicationName));
|
|
|
|
const zsh_completion = gulp.src('resources/completions/zsh/_code')
|
|
.pipe(replace('@@APPNAME@@', product.applicationName))
|
|
.pipe(rename('BUILD/usr/share/zsh/site-functions/_' + product.applicationName));
|
|
|
|
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
|
|
.pipe(rename(function (p) { p.dirname = 'BUILD/usr/share/' + product.applicationName + '/' + p.dirname; }));
|
|
|
|
const spec = gulp.src('resources/linux/rpm/code.spec.template', { base: '.' })
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@ICON@@', product.linuxIconName))
|
|
.pipe(replace('@@VERSION@@', packageJson.version))
|
|
.pipe(replace('@@RELEASE@@', linuxPackageRevision))
|
|
.pipe(replace('@@ARCHITECTURE@@', rpmArch))
|
|
.pipe(replace('@@LICENSE@@', product.licenseName))
|
|
.pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@'))
|
|
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@'))
|
|
.pipe(replace('@@DEPENDENCIES@@', rpmDependencies[rpmArch].join(', ')))
|
|
.pipe(rename('SPECS/' + product.applicationName + '.spec'));
|
|
|
|
const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' })
|
|
.pipe(rename('SOURCES/' + product.applicationName + '.xpm'));
|
|
|
|
const all = es.merge(code, desktops, appdata, workspaceMime, icon, bash_completion, zsh_completion, spec, specIcon);
|
|
|
|
return all.pipe(vfs.dest(getRpmBuildPath(rpmArch)));
|
|
};
|
|
}
|
|
|
|
function buildRpmPackage(arch) {
|
|
const rpmArch = getRpmPackageArch(arch);
|
|
const rpmBuildPath = getRpmBuildPath(rpmArch);
|
|
const rpmOut = rpmBuildPath + '/RPMS/' + rpmArch;
|
|
const destination = '.build/linux/rpm/' + rpmArch;
|
|
|
|
return shell.task([
|
|
'mkdir -p ' + destination,
|
|
'HOME="$(pwd)/' + destination + '" fakeroot rpmbuild -bb ' + rpmBuildPath + '/SPECS/' + product.applicationName + '.spec --target=' + rpmArch,
|
|
'cp "' + rpmOut + '/$(ls ' + rpmOut + ')" ' + destination + '/'
|
|
]);
|
|
}
|
|
|
|
function getSnapBuildPath(arch) {
|
|
return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`;
|
|
}
|
|
|
|
function prepareSnapPackage(arch) {
|
|
const binaryDir = '../VSCode-linux-' + arch;
|
|
const destination = getSnapBuildPath(arch);
|
|
|
|
return function () {
|
|
// A desktop file that is placed in snap/gui will be placed into meta/gui verbatim.
|
|
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
|
|
.pipe(rename(`snap/gui/${product.applicationName}.desktop`));
|
|
|
|
// A desktop file that is placed in snap/gui will be placed into meta/gui verbatim.
|
|
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
|
|
.pipe(rename(`snap/gui/${product.applicationName}-url-handler.desktop`));
|
|
|
|
const desktops = es.merge(desktop, desktopUrlHandler)
|
|
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
|
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@EXEC@@', `${product.applicationName} --force-user-env`))
|
|
.pipe(replace('@@ICON@@', `\${SNAP}/meta/gui/${product.linuxIconName}.png`))
|
|
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
|
|
|
|
// An icon that is placed in snap/gui will be placed into meta/gui verbatim.
|
|
const icon = gulp.src('resources/linux/code.png', { base: '.' })
|
|
.pipe(rename(`snap/gui/${product.linuxIconName}.png`));
|
|
|
|
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
|
|
.pipe(rename(function (p) { p.dirname = `usr/share/${product.applicationName}/${p.dirname}`; }));
|
|
|
|
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
|
|
.pipe(replace('@@NAME@@', product.applicationName))
|
|
.pipe(replace('@@VERSION@@', commit.substr(0, 8)))
|
|
// Possible run-on values https://snapcraft.io/docs/architectures
|
|
.pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch))
|
|
.pipe(rename('snap/snapcraft.yaml'));
|
|
|
|
const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' })
|
|
.pipe(rename('electron-launch'));
|
|
|
|
const all = es.merge(desktops, icon, code, snapcraft, electronLaunch);
|
|
|
|
return all.pipe(vfs.dest(destination));
|
|
};
|
|
}
|
|
|
|
function buildSnapPackage(arch) {
|
|
const snapBuildPath = getSnapBuildPath(arch);
|
|
// Default target for snapcraft runs: pull, build, stage and prime, and finally assembles the snap.
|
|
return shell.task(`cd ${snapBuildPath} && snapcraft`);
|
|
}
|
|
|
|
const BUILD_TARGETS = [
|
|
{ arch: 'x64' },
|
|
{ arch: 'armhf' },
|
|
{ arch: 'arm64' },
|
|
];
|
|
|
|
BUILD_TARGETS.forEach(({ arch }) => {
|
|
const debArch = getDebPackageArch(arch);
|
|
const prepareDebTask = task.define(`vscode-linux-${arch}-prepare-deb`, task.series(util.rimraf(`.build/linux/deb/${debArch}`), prepareDebPackage(arch)));
|
|
const buildDebTask = task.define(`vscode-linux-${arch}-build-deb`, task.series(prepareDebTask, buildDebPackage(arch)));
|
|
gulp.task(buildDebTask);
|
|
|
|
const rpmArch = getRpmPackageArch(arch);
|
|
const prepareRpmTask = task.define(`vscode-linux-${arch}-prepare-rpm`, task.series(util.rimraf(`.build/linux/rpm/${rpmArch}`), prepareRpmPackage(arch)));
|
|
const buildRpmTask = task.define(`vscode-linux-${arch}-build-rpm`, task.series(prepareRpmTask, buildRpmPackage(arch)));
|
|
gulp.task(buildRpmTask);
|
|
|
|
const prepareSnapTask = task.define(`vscode-linux-${arch}-prepare-snap`, task.series(util.rimraf(`.build/linux/snap/${arch}`), prepareSnapPackage(arch)));
|
|
gulp.task(prepareSnapTask);
|
|
const buildSnapTask = task.define(`vscode-linux-${arch}-build-snap`, task.series(prepareSnapTask, buildSnapPackage(arch)));
|
|
gulp.task(buildSnapTask);
|
|
});
|