diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 1f1c3332..86a451ba 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -1,3 +1,5 @@ +import path from 'path'; +import fs from 'fs'; import gulp from 'gulp'; import pump from 'pump'; import del from 'del'; @@ -8,6 +10,7 @@ import replace from 'gulp-replace'; import copydeps from './scripts/copydeps'; import file from 'gulp-file'; import editjson from 'gulp-json-editor'; +import {mkdeb} from './scripts/dpkg'; import corepkg from './core/package'; import clientpkg from './client/package'; @@ -153,3 +156,50 @@ gulp.task('del-release', function() { gulp.task('dependencies', gulp.series('node-modules', gulp.parallel('node-sass-bindings', 'keytar-bindings'))); gulp.task('build-release', gulp.parallel('core-release', 'client-release', 'editor-release', 'dependencies')); gulp.task('release', gulp.series('del-release', 'build-release')); + +// Debian packages + +gulp.task('build-inject-deb', function () { + const control = fs.readFileSync(path.join(__dirname, 'other', 'deb', 'control', 'control'), 'utf-8'); + const version = (control.match(/^Version:\s*(.*)$/m) || [, '1.0.0'])[1]; + const arch = (control.match(/^Architecture:\s*(.*)$/m) || [, 'all'])[1]; + + return mkdeb(`betterdiscord_${version}-${arch}`, 'other/deb/injector/**/*', '/usr/share/discord/resources/app', 'other/deb/control/**/*'); +}); + +gulp.task('build-inject-deb-ptb', function () { + const control = fs.readFileSync(path.join(__dirname, 'other', 'deb', 'control-ptb', 'control'), 'utf-8'); + const version = (control.match(/^Version:\s*(.*)$/m) || [, '1.0.0'])[1]; + const arch = (control.match(/^Architecture:\s*(.*)$/m) || [, 'all'])[1]; + + return mkdeb(`betterdiscord-ptb_${version}-${arch}`, 'other/deb/injector/**/*', '/usr/share/discord-ptb/resources/app', 'other/deb/control-ptb/**/*'); +}); + +gulp.task('build-inject-deb-canary', function () { + const control = fs.readFileSync(path.join(__dirname, 'other', 'deb', 'control-canary', 'control'), 'utf-8'); + const version = (control.match(/^Version:\s*(.*)$/m) || [, '1.0.0'])[1]; + const arch = (control.match(/^Architecture:\s*(.*)$/m) || [, 'all'])[1]; + + return mkdeb(`betterdiscord-canary_${version}-${arch}`, 'other/deb/injector/**/*', '/usr/share/discord-canary/resources/app', 'other/deb/control-canary/**/*'); +}); + +gulp.task('build-inject-debs', gulp.parallel('build-inject-deb', 'build-inject-deb-ptb', 'build-inject-deb-canary')); + +gulp.task('build-core-deb', function () { + return mkdeb(`betterdiscord-core_${corepkg.version}-all`, 'release/core/**/*', '/usr/lib/betterdiscord/core', 'other/deb/control-core/**/*', { + VERSION: corepkg.version + }); +}); + +gulp.task('build-client-deb', function () { + return mkdeb(`betterdiscord-client_${clientpkg.version}-all`, 'release/client/**/*', '/usr/lib/betterdiscord/client', 'other/deb/control-client/**/*', { + VERSION: clientpkg.version + }); +}); + +gulp.task('build-editor-deb', function () { + return mkdeb(`betterdiscord-editor_${clientpkg.version}-all`, 'release/editor/**/*', '/usr/lib/betterdiscord/editor', 'other/deb/control-editor/**/*', { + VERSION: editorpkg.version + }); +}); +gulp.task('build-debs', gulp.parallel('build-inject-debs', 'build-core-deb', 'build-client-deb', 'build-editor-deb')); diff --git a/other/deb/control-canary/conffiles b/other/deb/control-canary/conffiles new file mode 100644 index 00000000..85690f30 --- /dev/null +++ b/other/deb/control-canary/conffiles @@ -0,0 +1 @@ +/usr/share/discord-canary/resources/app/bd.json diff --git a/other/deb/control-canary/control b/other/deb/control-canary/control new file mode 100644 index 00000000..1d9d8e91 --- /dev/null +++ b/other/deb/control-canary/control @@ -0,0 +1,6 @@ +Package: betterdiscord-canary +Version: 1.0.0 +Architecture: all +Maintainer: - +Description: BetterDiscord v2 for Discord Canary +Depends: discord-canary, betterdiscord-core, betterdiscord-client, betterdiscord-editor diff --git a/other/deb/control-client/control b/other/deb/control-client/control new file mode 100644 index 00000000..0f99bbcf --- /dev/null +++ b/other/deb/control-client/control @@ -0,0 +1,5 @@ +Package: betterdiscord-client +Version: ${VERSION} +Architecture: all +Maintainer: - +Description: BetterDiscord v2 client bundle diff --git a/other/deb/control-core/control b/other/deb/control-core/control new file mode 100644 index 00000000..3f24ef1d --- /dev/null +++ b/other/deb/control-core/control @@ -0,0 +1,6 @@ +Package: betterdiscord-core +Version: ${VERSION} +Architecture: all +Maintainer: - +Description: BetterDiscord v2 core files +Depends: libsecret-1-0 diff --git a/other/deb/control-editor/control b/other/deb/control-editor/control new file mode 100644 index 00000000..8e709644 --- /dev/null +++ b/other/deb/control-editor/control @@ -0,0 +1,5 @@ +Package: betterdiscord-editor +Version: ${VERSION} +Architecture: all +Maintainer: - +Description: BetterDiscord v2 editor bundle diff --git a/other/deb/control-ptb/conffiles b/other/deb/control-ptb/conffiles new file mode 100644 index 00000000..bc6d142a --- /dev/null +++ b/other/deb/control-ptb/conffiles @@ -0,0 +1 @@ +/usr/share/discord-ptb/resources/app/bd.json diff --git a/other/deb/control-ptb/control b/other/deb/control-ptb/control new file mode 100644 index 00000000..3197c345 --- /dev/null +++ b/other/deb/control-ptb/control @@ -0,0 +1,6 @@ +Package: betterdiscord-ptb +Version: 1.0.0 +Architecture: all +Maintainer: - +Description: BetterDiscord v2 for Discord PTB +Depends: discord-ptb, betterdiscord-core, betterdiscord-client, betterdiscord-editor diff --git a/other/deb/control/conffiles b/other/deb/control/conffiles new file mode 100644 index 00000000..ba51c5b5 --- /dev/null +++ b/other/deb/control/conffiles @@ -0,0 +1 @@ +/usr/share/discord/resources/app/bd.json diff --git a/other/deb/control/control b/other/deb/control/control new file mode 100644 index 00000000..aa4c66b8 --- /dev/null +++ b/other/deb/control/control @@ -0,0 +1,6 @@ +Package: betterdiscord +Version: 1.0.0 +Architecture: all +Maintainer: - +Description: BetterDiscord v2 +Depends: discord, betterdiscord-core, betterdiscord-client, betterdiscord-editor diff --git a/other/deb/injector/bd.json b/other/deb/injector/bd.json new file mode 100644 index 00000000..2cd85c2a --- /dev/null +++ b/other/deb/injector/bd.json @@ -0,0 +1,19 @@ +{ + "options": { + "autoInject": true, + "commonCore": true, + "commonData": true + }, + "paths": { + "core": "/usr/lib/betterdiscord/core", + "client": "/usr/lib/betterdiscord/client", + "editor": "/usr/lib/betterdiscord/editor", + "data": ".config/betterdiscord/data", + "userconfig": ".config/betterdiscord/bd" + }, + "disableUpdater": [ + "core", + "client", + "editor" + ] +} diff --git a/other/deb/injector/index.js b/other/deb/injector/index.js new file mode 100644 index 00000000..b0e0c530 --- /dev/null +++ b/other/deb/injector/index.js @@ -0,0 +1,23 @@ +const bdinfo = require('./bd'); +const { app } = require('electron'); +const path = require('path'); +const os = require('os'); +const Module = require('module'); + +const packagePath = path.join(__dirname, '..', 'app.asar'); +app.getAppPath = () => packagePath; + +function loadBd() { + const userconfig = (() => { + try { + return require(path.resolve(os.homedir(), bdinfo.paths.userconfig)); + } catch (err) {} + })() || {}; + + const { BetterDiscord } = require(path.resolve(os.homedir(), (userconfig.paths || {}).core || bdinfo.paths.core)); + const instance = new BetterDiscord(bdinfo, userconfig); +} + +app.on('ready', loadBd); + +Module._load(app.getAppPath(), null, true); diff --git a/other/deb/injector/package.json b/other/deb/injector/package.json new file mode 100644 index 00000000..8ff69de1 --- /dev/null +++ b/other/deb/injector/package.json @@ -0,0 +1,6 @@ +{ + "name": "discord", + "description": "Discord Client for Desktop - Bootstrapper", + "main": "index.js", + "private": true +} diff --git a/package-lock.json b/package-lock.json index e198080c..4cbd03c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "betterdiscord", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1216,6 +1216,12 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -2008,6 +2014,12 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, "cacache": { "version": "11.3.2", "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", @@ -5359,6 +5371,32 @@ } } }, + "gulp-gzip": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gulp-gzip/-/gulp-gzip-1.4.2.tgz", + "integrity": "sha512-ZIxfkUwk2XmZPTT9pPHrHUQlZMyp9nPhg2sfoeN27mBGpi7OaHnOD+WCN41NXjfJQ69lV1nQ9LLm1hYxx4h3UQ==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "bytes": "^3.0.0", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.0", + "stream-to-array": "^2.3.0", + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, "gulp-inject-string": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/gulp-inject-string/-/gulp-inject-string-1.1.2.tgz", @@ -5410,6 +5448,141 @@ "replacestream": "^4.0.0" } }, + "gulp-tar": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-tar/-/gulp-tar-2.1.0.tgz", + "integrity": "sha512-Yp/57bpiZPDVajUJix6QRCpL+XCNNFuaEcDVJ33LzenbGUkpJrH8j+8xJoMNlyi902uXV7rBy5sihwBnu5OfFw==", + "dev": true, + "requires": { + "archiver": "^1.0.0", + "plugin-error": "^0.1.2", + "through2": "^2.0.0", + "vinyl": "^2.1.0" + }, + "dependencies": { + "archiver": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", + "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=", + "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "walkdir": "^0.0.11", + "zip-stream": "^1.1.0" + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "dev": true, + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } + } + } + }, "gulp-watch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", @@ -7162,6 +7335,12 @@ } } }, + "merge2": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -8610,6 +8789,57 @@ "requires": { "speedometer": "~0.1.2", "through2": "~0.2.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "requires": { + "object-keys": "~0.4.0" + } + } } }, "promise-inflight": { @@ -10150,6 +10380,15 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, + "stream-to-array": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", + "integrity": "sha1-u/azn19D7DC8cbq8s3VXrOzzQ1M=", + "dev": true, + "requires": { + "any-promise": "^1.1.0" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -10499,54 +10738,12 @@ "dev": true }, "through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", "dev": true, "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "~0.4.0" - } - } + "readable-stream": "2 || 3" } }, "through2-filter": { @@ -11388,6 +11585,12 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "walkdir": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", + "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=", + "dev": true + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", diff --git a/package.json b/package.json index 6c3584c7..179a8b46 100644 --- a/package.json +++ b/package.json @@ -51,15 +51,18 @@ "gulp-babel": "^8.0.0", "gulp-copy": "^4.0.1", "gulp-file": "^0.4.0", + "gulp-gzip": "^1.4.2", "gulp-inject-string": "^1.1.2", "gulp-json-editor": "^2.5.1", "gulp-rename": "^1.4.0", "gulp-replace": "^1.0.0", + "gulp-tar": "^2.1.0", "gulp-watch": "^5.0.1", "hash-files": "^1.1.1", "html-webpack-plugin": "^3.2.0", "jquery": "^3.3.1", "lodash": "^4.17.11", + "merge2": "^1.2.3", "mkdirp": "^0.5.1", "node-gyp": "^3.8.0", "parallel-webpack": "^2.3.0", @@ -67,6 +70,7 @@ "request-promise-native": "1.0.5", "sass-lint": "^1.12.1", "sass-loader": "^7.1.0", + "through2": "^3.0.1", "v-tooltip": "^2.0.0-rc.33", "vue": "^2.6.8", "vue-color": "^2.7.0", @@ -100,6 +104,14 @@ "release": "npm run lint && npm run build_release && gulp release && npm run package_release", "release_test": "npm run build_release && gulp release", "update_release": "npm run build_release && gulp release", + "build_inject_deb": "gulp build-inject-deb", + "build_inject-ptb_deb": "gulp build-inject-deb-ptb", + "build_inject-canary_deb": "gulp build-inject-deb-canary", + "build_inject_debs": "gulp build-inject-debs", + "build_core_deb": "gulp build-core-deb", + "build_client_deb": "gulp build-client-deb", + "build_editor_deb": "gulp build-editor-deb", + "build_debs": "gulp build-debs", "inject": "node scripts/inject.js" } } diff --git a/scripts/dpkg.js b/scripts/dpkg.js new file mode 100644 index 00000000..ce7a1f3a --- /dev/null +++ b/scripts/dpkg.js @@ -0,0 +1,124 @@ +const path = require('path'); +const stream = require('stream'); +const through2 = require('through2'); +const gulp = require('gulp'); +const Vinyl = require('vinyl'); +const pump = require('pump'); +const merge = require('merge2'); +const tar = require('gulp-tar'); +const gzip = require('gulp-gzip'); +const file = require('gulp-file'); +const replace = require('gulp-replace'); +const rename = require('gulp-rename'); + +/** + * Return a transform stream that create a Debian package from debian-binary, control.tar and data.tar files. + * @param {string} name The name of the .deb file to create + * @return {stream.TransformStream} + */ +function deb(name) { + const files = []; + + return through2({objectMode: true}, (file, enc, callback) => { + files.push(file); + callback(null, file); + }, function (callback) { (async () => { + if (files.length !== 3) throw new Error('Must have three files'); + if (!files[0].path.match(/\/debian-binary$/)) throw new Error('Missing debian-binary file'); + if (!files[1].path.match(/\/control\.tar(\.gz)?$/)) throw new Error('Missing control archive'); + if (!files[2].path.match(/\/data\.tar(\.gz)?$/)) throw new Error('Missing data archive'); + + const contents = new stream.Readable(); + contents._read = () => {}; + + const debfile = new Vinyl({ + cwd: '/', + base: '/', + path: '/' + name, + contents + }); + + // console.log('Returning deb', debfile, files); + + contents.push('!' + String.fromCharCode(0x0A)); // Signature + + for (const [index, file] of files.entries()) { + // console.log(file, index, file.stat); + + const size = file.stat ? file.stat.size.toString() : file.contents && file.contents.length ? file.contents.length : 0; + + contents.push(rightPaddedWithSpaces(16, path.basename(file.path))); // Filename (ASCII, 16 bytes long) + contents.push(rightPaddedWithSpaces(12, (Math.floor(file.stat ? file.stat.mtime / 1000 : 0)).toString())); // File modification timestamp (Decimal, 12 bytes long) + contents.push(rightPaddedWithSpaces(6, '0')); // Owner ID (Decimal, 6 bytes long) + contents.push(rightPaddedWithSpaces(6, '0')); // Group ID (Decimal, 6 bytes long) + contents.push(rightPaddedWithSpaces(8, '100644')); // File mode (Octal, 8 bytes long) + contents.push(rightPaddedWithSpaces(10, size.toString())); // File size in bytes (Decimal, 10 bytes long) + contents.push(String.fromCharCode(0x60) + String.fromCharCode(0x0A)); // Ending characters ("0x60 0x0A") + + // stream.write(file.contents); + if (file.isStream()) await new Promise((resolve, reject) => { + file.contents.on('data', data => contents.push(data)); + // file.contents.pipe(contents); + file.contents.on('end', resolve); + file.contents.on('error', reject); + }); else contents.push(file.contents); + + // If the data for an archive member ends at an odd byte offset, then a padding byte with value 0x0A is + // used to position the next archive header on an even byte offset. + if (size % 2 === 1 && index !== 2) { + contents.push(String.fromCharCode(0x0A)); + } + } + + contents.push(null); + + this.push(debfile); + callback(); + })().catch(err => { + console.error(err); + callback(err); + }); }); +} + +function rightPaddedWithSpaces(n, string) { + if (!string) string = ''; + if (string.length > n) throw new Error('string is longer than n padding'); + return string + (new Array(n - string.length + 1)).join(String.fromCharCode(0x20)); +} + +/** + * Creates a Debian package. + * @param {string} name + * @param {string} datafiles Path to the data directory + * @param {string} dataprefix The directory the files in the data directory should be unpacked to when installing + * @param {string} controlfiles Path to the control directory + * @param {Object} [controlvars] Variables to replace in the control files + * @return {stream.TransformStream} + */ +function mkdeb(name, datafiles, dataprefix, controlfiles, controlvars) { + return pump([ + merge([ + file('debian-binary', '2.0\n', {src: true}), + pump([ + gulp.src(controlfiles), + ...Object.keys(controlvars || {}).map(k => replace(`\${${k}}`, controlvars[k])), + tar('control.tar'), + gzip() + ]), + pump([ + gulp.src(datafiles), + rename(p => p.dirname = dataprefix + '/' + p.dirname), + tar(name + '.tar'), + gzip(), + gulp.dest('release') + ]) + ]), + + rename(p => p.basename = p.basename === name ? 'data' : p.basename === name + '.tar' ? 'data.tar' : p.basename), + deb(name + '.deb'), + gulp.dest('release') + ]); +} + +exports.deb = deb; +exports.mkdeb = mkdeb;