diff options
-rw-r--r-- | .SRCINFO | 8 | ||||
-rw-r--r-- | 1928.patch | 967 | ||||
-rw-r--r-- | PKGBUILD | 19 |
3 files changed, 981 insertions, 13 deletions
@@ -1,6 +1,6 @@ pkgbase = tutanota-desktop pkgdesc = Official Tutanota email client - pkgver = 3.70.1 + pkgver = 3.71.4 pkgrel = 1 url = https://tutanota.com arch = x86_64 @@ -11,10 +11,12 @@ pkgbase = tutanota-desktop depends = libxtst depends = libappindicator-gtk3 depends = libnotify - source = https://github.com/tutao/tutanota/archive/tutanota-release-3.70.1.tar.gz + source = https://github.com/tutao/tutanota/archive/tutanota-release-3.71.4.tar.gz + source = 1928.patch source = tutanota-desktop source = tutanota-desktop.desktop - sha256sums = 37cc07bb49836e58ab9e72067fff9e48da48eeecd4ce216dc464f8ae6761f74d + sha256sums = e4fbf7a8876433dc1ffdd9e24d6dc980e7b2ff2e4da389169aec72588babd41e + sha256sums = 614755f15fe792caf617829b19198d6a74b480436fea45568b315773c60a9ae6 sha256sums = 4f91e842bd92a3312943854383e4929f9baf6cb684a7027aa55edcce1bf4ca16 sha256sums = 1215678e2fc23cfbeb73063f68dc440891e5b2e10734fa7f402e06860c292e31 diff --git a/1928.patch b/1928.patch new file mode 100644 index 000000000000..3d3d8ec5c5e9 --- /dev/null +++ b/1928.patch @@ -0,0 +1,967 @@ +From 4aed9bd33e5230b0c1e496c3ba75b41a2a74b231 Mon Sep 17 00:00:00 2001 +From: nig <nig@tutao.de> +Date: Thu, 26 Mar 2020 17:10:42 +0100 +Subject: [PATCH 1/4] [desktop] add builds w/o auto-updates and unpacked + builds, close #1857 + +adds some options to the dist.js build script: +--unpacked +disables the building of installers (dir target for all platforms) + +--out-dir <outDir> +move the built installers (or dirs) into the path outDir after building. +Defaults to build/desktop and build/desktop-test + +--custom-release +disable autoUpdate in the release target by not including an update url. +--- + buildSrc/DesktopBuilder.js | 45 ++++++++++++---------- + buildSrc/electron-package-json-template.js | 42 +++++++++++--------- + dist.js | 25 ++++++++---- + doc/BUILDING.md | 28 +++++++++++++- + src/desktop/ElectronUpdater.js | 10 +++++ + test/client/desktop/ElectronUpdaterTest.js | 42 ++++++++++++++++++++ + 6 files changed, 142 insertions(+), 50 deletions(-) + +diff --git a/buildSrc/DesktopBuilder.js b/buildSrc/DesktopBuilder.js +index 819fc78a1..9e144c836 100644 +--- a/buildSrc/DesktopBuilder.js ++++ b/buildSrc/DesktopBuilder.js +@@ -3,15 +3,14 @@ const babel = Promise.promisifyAll(require("babel-core")) + const fs = Promise.promisifyAll(require("fs-extra")) + const path = require("path") + +- +-function build(dirname, version, targets, updateUrl, nameSuffix, notarize) { ++function build(dirname, version, targets, updateUrl, nameSuffix, notarize, outDir, unpacked) { + const targetString = Object.keys(targets) + .filter(k => typeof targets[k] !== "undefined") + .join(" ") + console.log("Building desktop client for v" + version + " (" + targetString + ")...") +- const updateSubDir = "desktop" + nameSuffix + const distDir = path.join(dirname, '/build/dist/') +- ++ outDir = path.join(outDir || path.join(distDir, ".."), 'desktop' + nameSuffix) ++ console.log("artifacts will be moved to", outDir) + const requiredEntities = fs.readdirSync(path.join(dirname, './src/api/entities/sys/')) + .map(fn => path.join(dirname, './src/api/entities/sys', fn)) + const languageFiles = fs.readdirSync(path.join(dirname, './src/translations/')) +@@ -24,14 +23,14 @@ function build(dirname, version, targets, updateUrl, nameSuffix, notarize) { + updateUrl, + path.join(dirname, "/resources/desktop-icons/logo-solo-red.png"), + nameSuffix !== "-snapshot", +- notarize ++ notarize, ++ unpacked + ) +- console.log("updateUrl is", updateUrl) + let writeConfig = fs.writeFileAsync("./build/dist/package.json", JSON.stringify(content), 'utf-8') + + //prepare files + return writeConfig +- .then(() => fs.removeAsync(path.join(distDir, "..", updateSubDir))) ++ .then(() => fs.removeAsync(outDir)) + .then(() => { + console.log("Tracing dependencies...") + transpile(['./src/desktop/DesktopMain.js', './src/desktop/preload.js'] +@@ -52,24 +51,28 @@ function build(dirname, version, targets, updateUrl, nameSuffix, notarize) { + }) + }) + .then(() => { +- console.log("Move output to /build/" + updateSubDir + "/...") ++ const installerDir = path.join(distDir, 'installers') ++ console.log("Move artifacts to", outDir) ++ const unpackedFilter = file => file.endsWith("-unpacked") || file === "mac" ++ const packedFilter = file => file.startsWith(content.name) || file.endsWith('.yml') ++ + return Promise.all( +- fs.readdirSync(path.join(distDir, '/installers')) +- .filter((file => file.startsWith(content.name) || file.endsWith('.yml'))) ++ fs.readdirSync(installerDir) ++ .filter(unpacked ? unpackedFilter : packedFilter) + .map(file => fs.moveAsync( +- path.join(distDir, '/installers/', file), +- path.join(distDir, `../${updateSubDir}`, file) ++ path.join(installerDir, file), ++ path.join(outDir, file) + ) + ) +- ).then(() => Promise.all([ +- fs.removeAsync(path.join(distDir, '/installers/')), +- fs.removeAsync(path.join(distDir, '/node_modules/')), +- fs.removeAsync(path.join(distDir, '/cache.json')), +- fs.removeAsync(path.join(distDir, '/package.json')), +- fs.removeAsync(path.join(distDir, '/package-lock.json')), +- fs.removeAsync(path.join(distDir, '/src/')), +- ])) +- }) ++ ) ++ }).then(() => Promise.all([ ++ fs.removeAsync(path.join(distDir, '/installers/')), ++ fs.removeAsync(path.join(distDir, '/node_modules/')), ++ fs.removeAsync(path.join(distDir, '/cache.json')), ++ fs.removeAsync(path.join(distDir, '/package.json')), ++ fs.removeAsync(path.join(distDir, '/package-lock.json')), ++ fs.removeAsync(path.join(distDir, '/src/')), ++ ])) + } + + /** +diff --git a/buildSrc/electron-package-json-template.js b/buildSrc/electron-package-json-template.js +index 3243f06d1..a24067fb3 100644 +--- a/buildSrc/electron-package-json-template.js ++++ b/buildSrc/electron-package-json-template.js +@@ -6,7 +6,7 @@ const pj = require('../package.json') + * 2. copied to app-desktop/build/dist from dist.js (DesktopBuilder) + */ + +-module.exports = function (nameSuffix, version, targetUrl, iconPath, sign, notarize) { ++module.exports = function (nameSuffix, version, updateUrl, iconPath, sign, notarize, unpacked) { + return { + "name": "tutanota-desktop" + nameSuffix, + "main": "./src/desktop/DesktopMain.js", +@@ -88,12 +88,14 @@ module.exports = function (nameSuffix, version, targetUrl, iconPath, sign, notar + } + ], + "forceCodeSigning": sign || !!process.env.JENKINS, +- "publish": { +- "provider": "generic", +- "url": targetUrl, +- "channel": "latest", +- "publishAutoUpdate": true +- }, ++ "publish": updateUrl ++ ? { ++ "provider": "generic", ++ "url": updateUrl, ++ "channel": "latest", ++ "publishAutoUpdate": true ++ } ++ : undefined, + "directories": { + "output": "installers" + }, +@@ -112,7 +114,7 @@ module.exports = function (nameSuffix, version, targetUrl, iconPath, sign, notar + : undefined, + "target": [ + { +- "target": "nsis", ++ "target": unpacked ? "dir" : "nsis", + "arch": "x64" + } + ] +@@ -134,16 +136,18 @@ module.exports = function (nameSuffix, version, targetUrl, iconPath, sign, notar + "extendInfo": { + "LSUIElement": 1 //hide dock icon on startup + }, +- "target": [ +- { +- "target": "zip", +- "arch": "x64" +- }, +- { +- "target": "dmg", +- "arch": "x64" +- } +- ] ++ "target": unpacked ++ ? [{"target": "dir", "arch": "x64"}] ++ : [ ++ { ++ "target": "zip", ++ "arch": "x64" ++ }, ++ { ++ "target": "dmg", ++ "arch": "x64" ++ } ++ ] + }, + "linux": { + "icon": path.join(path.dirname(iconPath), "icon/"), +@@ -154,7 +158,7 @@ module.exports = function (nameSuffix, version, targetUrl, iconPath, sign, notar + }, + "target": [ + { +- "target": "AppImage", ++ "target": unpacked ? "dir" : "AppImage", + "arch": "x64" + } + ] +diff --git a/dist.js b/dist.js +index fce9a681d..ca1f54f09 100644 +--- a/dist.js ++++ b/dist.js +@@ -49,6 +49,9 @@ options + .option('-m --mac', 'Build desktop client for mac') + .option('-d, --deb', 'Build .deb package. Requires -wlm to be set or installers to be present') + .option('-p, --publish', 'Git tag and upload package, only allowed in release stage. Implies -d.') ++ .option('--custom-release', "use if manually building from source. doesn't install autoupdates, but may still notify about new releases") ++ .option('--unpacked', "don't pack the app into an installer") ++ .option('--out-dir <outDir>', "where to copy the client",) + .action((stage, host) => { + if (!["test", "prod", "local", "host", "release", undefined].includes(stage) + || (stage !== "host" && host) +@@ -177,26 +180,32 @@ function buildDesktopClient() { + if (options.desktop) { + const desktopBuilder = require('./buildSrc/DesktopBuilder.js') + if (options.stage === "release") { +- return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://mail.tutanota.com", version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, version, options.desktop, "https://mail.tutanota.com/desktop", "", /*notarize*/true)) +- .then(() => createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://test.tutanota.com", version, "Desktop", true), bundles)) +- .then(() => desktopBuilder.build(__dirname, version, options.desktop, "https://test.tutanota.com/desktop", "-test", /*notarize*/true)) ++ const updateUrl = options.customRelease ++ ? "" ++ : "https://mail.tutanota.com/desktop" ++ const buildPromise = createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://mail.tutanota.com", version, "Desktop", true), bundles) ++ .then(() => desktopBuilder.build(__dirname, version, options.desktop, updateUrl, "", /*notarize*/true, options.outDir, options.unpacked)) ++ if (!options.customRelease) { // don't build the test version for manual/custom builds ++ buildPromise.then(() => createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://test.tutanota.com", version, "Desktop", true), bundles)) ++ .then(() => desktopBuilder.build(__dirname, version, options.desktop, "https://test.tutanota.com/desktop", "-test", /*notarize*/true, options.outDir, options.unpacked)) ++ } ++ return buildPromise + } else if (options.stage === "local") { + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "http://localhost:9000", version, "Desktop", true), bundles) + .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "http://localhost:9000", "-snapshot")) ++ options.desktop, "http://localhost:9000", "-snapshot", options.outDir, options.unpacked)) + } else if (options.stage === "test") { + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://test.tutanota.com", version, "Desktop", true), bundles) + .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "https://test.tutanota.com/desktop", "-test")) ++ options.desktop, "https://test.tutanota.com/desktop", "-test", options.outDir, options.unpacked)) + } else if (options.stage === "prod") { + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://mail.tutanota.com", version, "Desktop", true), bundles) + .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "http://localhost:9000/desktop", "")) ++ options.desktop, "http://localhost:9000/desktop", "", options.outDir, options.unpacked)) + } else { // stage = host + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), options.host, version, "Desktop", true), bundles) + .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "http://localhost:9000/desktop-snapshot", "-snapshot")) ++ options.desktop, "http://localhost:9000/desktop-snapshot", "-snapshot", options.outDir, options.unpacked)) + } + } + } +diff --git a/doc/BUILDING.md b/doc/BUILDING.md +index 75bf18373..b43010f65 100644 +--- a/doc/BUILDING.md ++++ b/doc/BUILDING.md +@@ -12,7 +12,7 @@ your own. If you prefer the auto-update feature, you can use the official [mail] + 1. Clone the repository: `git clone https://github.com/tutao/tutanota.git` + 2. Switch into the repository directory: `cd tutanota` + 3. Checkout the latest web release tag: `git checkout tutanota-release-xxx` +-4. Do `npm install` ++4. run `npm install` to install dependencies. + 5. Build the web part: `node dist prod` + 6. Switch into the build directory: `cd build/dist` + 7. Run local server. Either use `node server` or `python -m SimpleHTTPServer 9000`. +@@ -21,7 +21,7 @@ your own. If you prefer the auto-update feature, you can use the official [mail] + ## Building and running your own Tutanota Android app + + If you build and install the Tutanota Android app by yourself, keep in mind that you will not get updates automatically. +-If you prefer the auto-update feature, use the Google Play Store or F-Droid in the future. ++If you prefer the auto-update feature, download the app from the Google Play Store or F-Droid. + + #### Pre-requisites: + * An up-to-date version of Git is installed +@@ -37,3 +37,27 @@ If you prefer the auto-update feature, use the Google Play Store or F-Droid in t + 5. Create a keystore if you don't have one: `keytool -genkey -noprompt -keystore MyKeystore.jks -alias tutaKey -keyalg RSA -keysize 2048 -validity 10000 -deststoretype pkcs12 -storepass CHANGEME -keypass CHANGEME -dname "CN=com.example"` + 6. run `APK_SIGN_ALIAS="tutaKey" APK_SIGN_STORE='MyKeystore.jks' APK_SIGN_STORE_PASS="CHANGEME" APK_SIGN_KEY_PASS="CHANGEME" node android` + 7. Install the app on your device: `adb install -r <path-to-apk>` (path as printed by the build script) ++ ++## Building and running your own Tutanota Desktop client ++ ++Keep in mind that your own build of Tutanota Desktop will not update automatically. ++ ++### Pre-requisites: ++* An up-to-date version of Git is installed. ++* An up-to-date version of Node.js is installed ++ ++### Preparations: ++0. Open a terminal. ++1. Clone the repository: `git clone https://github.com/tutao/tutanota.git`. ++2. Switch into the Tutanota directory: `cd tutanota` ++3. Checkout the latest web release tag: `git checkout tutanota-release-xxx` ++4. Run `npm install` to install dependencies. ++ ++### Build: ++Linux: `node dist -l --custom-release` ++Windows: `node dist -w --custom-release` ++MacOs: `node dist -m --custom-release` ++ ++The client will be in `build/desktop/` ++Note that you can add `--unpacked` to the build command to skip the packaging of the installer. ++This will yield a directory containing the client that can be run without installation. +\ No newline at end of file +diff --git a/src/desktop/ElectronUpdater.js b/src/desktop/ElectronUpdater.js +index 6c8c61ccd..29269ca9b 100644 +--- a/src/desktop/ElectronUpdater.js ++++ b/src/desktop/ElectronUpdater.js +@@ -9,6 +9,8 @@ import type {DesktopConfigHandler} from './config/DesktopConfigHandler' + import {neverNull} from "../api/common/utils/Utils" + import {UpdateError} from "../api/common/error/UpdateError" + import {DesktopTray} from "./tray/DesktopTray" ++import fs from 'fs-extra' ++import path from 'path' + + export class ElectronUpdater { + _conf: DesktopConfigHandler; +@@ -91,6 +93,14 @@ export class ElectronUpdater { + +_enableAutoUpdateListener = () => this.start() + + start() { ++ try { ++ const appUpdateYmlPath = path.join(path.dirname(app.getPath('exe')), 'resources', 'app-update.yml') ++ fs.accessSync(appUpdateYmlPath, fs.constants.R_OK) ++ } catch (e) { ++ console.log("no update info on disk, disabling updater.") ++ return ++ } ++ + // if user changes auto update setting, we want to know + this._conf.removeListener('enableAutoUpdate', this._enableAutoUpdateListener) + .on('enableAutoUpdate', this._enableAutoUpdateListener) +diff --git a/test/client/desktop/ElectronUpdaterTest.js b/test/client/desktop/ElectronUpdaterTest.js +index 43580cec6..d5b4194db 100644 +--- a/test/client/desktop/ElectronUpdaterTest.js ++++ b/test/client/desktop/ElectronUpdaterTest.js +@@ -98,6 +98,13 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + } + } + ++ const fs = { ++ accessSync: () => {}, ++ constants: { ++ "R_OK": 1 ++ } ++ } ++ + const lang = { + lang: { + get: (key: string) => { +@@ -142,6 +149,7 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + + o("update is available", done => { + //mock node modules ++ const fsMock = n.mock('fs-extra', fs).set() + const forgeMock = n.mock('node-forge', nodeForge).set() + const autoUpdaterMock = n.mock('electron-updater', autoUpdater).set().autoUpdater + const electronMock = n.mock('electron', electron).set() +@@ -201,6 +209,7 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + + o("update is not available", done => { + //mock node modules ++ const fsMock = n.mock('fs-extra', fs).set() + const forgeMock = n.mock('node-forge', nodeForge).set() + const electronMock = n.mock('electron', electron).set() + const autoUpdaterMock = n.mock('electron-updater', autoUpdater) +@@ -242,6 +251,7 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + + o("enable autoUpdate while running", done => { + //mock node modules ++ const fsMock = n.mock('fs-extra', fs).set() + const forgeMock = n.mock('node-forge', nodeForge).set() + const electronMock = n.mock('electron', electron).set() + const autoUpdaterMock = n.mock('electron-updater', autoUpdater).set().autoUpdater +@@ -317,6 +327,7 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + + o("retry after autoUpdater reports an error", done => { + //mock node modules ++ const fsMock = n.mock('fs-extra', fs).set() + const forgeMock = n.mock('node-forge', nodeForge).set() + const electronMock = n.mock('electron', electron).set() + const autoUpdaterMock = n.mock('electron-updater', autoUpdater) +@@ -388,6 +399,7 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + const MAX_NUM_ERRORS = 5 + let threw = false + //mock node modules ++ const fsMock = n.mock('fs-extra', fs).set() + const forgeMock = n.mock('node-forge', nodeForge).set() + const electronMock = n.mock('electron', electron).set() + const autoUpdaterMock = n.mock('electron-updater', autoUpdater) +@@ -432,6 +444,7 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + o("works if second key is right one", done => { + + //mock node modules ++ const fsMock = n.mock('fs-extra', fs).set() + const forgeMock = n.mock('node-forge', nodeForge).with({ + publicKeyFromPem: (pem: string) => n.spyify(pem === "no" ? rightKey : wrongKey) + }).set() +@@ -492,4 +505,33 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + done() + }, 190) + }) ++ ++ o("updater disables itself if accessSync throws", function () { ++ //mock node modules ++ const fsMock = n.mock('fs-extra', fs).with({ ++ accessSync: undefined ++ }).set() ++ const forgeMock = n.mock('node-forge', nodeForge).set() ++ const autoUpdaterMock = n.mock('electron-updater', autoUpdater).set().autoUpdater ++ const electronMock = n.mock('electron', electron).set() ++ ++ //mock our modules ++ n.mock('./tray/DesktopTray', desktopTray).set() ++ n.mock('../misc/LanguageViewModel', lang).set() ++ ++ //mock instances ++ const confMock = n.mock('__conf', conf).set() ++ const notifierMock = n.mock('__notifier', notifier).set() ++ ++ const {ElectronUpdater} = n.subject('../../src/desktop/ElectronUpdater.js') ++ const upd = new ElectronUpdater(confMock, notifierMock) ++ ++ o(autoUpdaterMock.on.callCount).equals(5) ++ o(autoUpdaterMock.logger).equals(null) ++ ++ upd.start() ++ ++ o(confMock.removeListener.callCount).equals(0) ++ } ++ ) + }) + +From 9b5a5eee1bfbdaa6e45fdc49dc176a333989b88a Mon Sep 17 00:00:00 2001 +From: nig <nig@tutao.de> +Date: Tue, 31 Mar 2020 15:55:11 +0200 +Subject: [PATCH 2/4] [desktop] improve custom desktop builds + +- automatically build for current platform if no platform flag is given +- disable notarization on mac +- disable code signing for custom builds without updates +--- + buildSrc/DesktopBuilder.js | 2 +- + dist.js | 19 +++++++++++++------ + doc/BUILDING.md | 6 ++---- + 3 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/buildSrc/DesktopBuilder.js b/buildSrc/DesktopBuilder.js +index 9e144c836..8449c5923 100644 +--- a/buildSrc/DesktopBuilder.js ++++ b/buildSrc/DesktopBuilder.js +@@ -22,7 +22,7 @@ function build(dirname, version, targets, updateUrl, nameSuffix, notarize, outDi + version, + updateUrl, + path.join(dirname, "/resources/desktop-icons/logo-solo-red.png"), +- nameSuffix !== "-snapshot", ++ nameSuffix !== '-snapshot' && updateUrl !== "", // don't sign if it's a test build or if we don't download updates + notarize, + unpacked + ) +diff --git a/dist.js b/dist.js +index ca1f54f09..2731f8bf9 100644 +--- a/dist.js ++++ b/dist.js +@@ -49,7 +49,7 @@ options + .option('-m --mac', 'Build desktop client for mac') + .option('-d, --deb', 'Build .deb package. Requires -wlm to be set or installers to be present') + .option('-p, --publish', 'Git tag and upload package, only allowed in release stage. Implies -d.') +- .option('--custom-release', "use if manually building from source. doesn't install autoupdates, but may still notify about new releases") ++ .option('--custom-desktop-release', "use if manually building desktop client from source. doesn't install auto updates, but may still notify about new releases.") + .option('--unpacked', "don't pack the app into an installer") + .option('--out-dir <outDir>', "where to copy the client",) + .action((stage, host) => { +@@ -63,15 +63,21 @@ options + options.stage = stage || "release" + options.host = host + options.deb = options.deb || options.publish +- + options.desktop = { + win: options.win ? [] : undefined, + linux: options.linux ? [] : undefined, + mac: options.mac ? [] : undefined + } ++ + options.desktop = Object.values(options.desktop).some(Boolean) + ? options.desktop +- : undefined ++ : !!options.customDesktopRelease // no platform flags given, build desktop for current platform if customDesktopBuild flag is set. ++ ? { ++ win: process.platform === "win32" ? [] : undefined, ++ linux: process.platform === "linux" ? [] : undefined, ++ mac: process.platform === "darwin" ? [] : undefined ++ } ++ : undefined + }) + .parse(process.argv) + +@@ -180,12 +186,13 @@ function buildDesktopClient() { + if (options.desktop) { + const desktopBuilder = require('./buildSrc/DesktopBuilder.js') + if (options.stage === "release") { +- const updateUrl = options.customRelease ++ const updateUrl = options.customDesktopRelease + ? "" + : "https://mail.tutanota.com/desktop" ++ const notarize = !!options.customDesktopRelease + const buildPromise = createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://mail.tutanota.com", version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, version, options.desktop, updateUrl, "", /*notarize*/true, options.outDir, options.unpacked)) +- if (!options.customRelease) { // don't build the test version for manual/custom builds ++ .then(() => desktopBuilder.build(__dirname, version, options.desktop, updateUrl, "", notarize, options.outDir, options.unpacked)) ++ if (!options.customDesktopRelease) { // don't build the test version for manual/custom builds + buildPromise.then(() => createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://test.tutanota.com", version, "Desktop", true), bundles)) + .then(() => desktopBuilder.build(__dirname, version, options.desktop, "https://test.tutanota.com/desktop", "-test", /*notarize*/true, options.outDir, options.unpacked)) + } +diff --git a/doc/BUILDING.md b/doc/BUILDING.md +index b43010f65..2e6994817 100644 +--- a/doc/BUILDING.md ++++ b/doc/BUILDING.md +@@ -54,10 +54,8 @@ Keep in mind that your own build of Tutanota Desktop will not update automatical + 4. Run `npm install` to install dependencies. + + ### Build: +-Linux: `node dist -l --custom-release` +-Windows: `node dist -w --custom-release` +-MacOs: `node dist -m --custom-release` ++Run `node dist --custom-desktop-release`. + +-The client will be in `build/desktop/` ++The client for your platform will be in `build/desktop/`. + Note that you can add `--unpacked` to the build command to skip the packaging of the installer. + This will yield a directory containing the client that can be run without installation. +\ No newline at end of file + +From 20d3255a294de040747d67103a375f0061035426 Mon Sep 17 00:00:00 2001 +From: nig <nig@tutao.de> +Date: Fri, 3 Apr 2020 08:10:16 +0200 +Subject: [PATCH 3/4] [desktop] hide auto update option for custom desktop + builds + +--- + src/desktop/ElectronUpdater.js | 5 +++++ + src/desktop/config/DesktopConfigHandler.js | 1 + + src/desktop/config/migrations/DesktopConfigMigrator.js | 2 ++ + src/desktop/config/migrations/migration-0001.js | 7 +++++++ + src/settings/DesktopSettingsViewer.js | 5 ++++- + test/client/desktop/ElectronUpdaterTest.js | 10 ++++++++++ + .../config/migrations/DesktopConfigMigratorTest.js | 6 ++++-- + 7 files changed, 33 insertions(+), 3 deletions(-) + create mode 100644 src/desktop/config/migrations/migration-0001.js + +diff --git a/src/desktop/ElectronUpdater.js b/src/desktop/ElectronUpdater.js +index 29269ca9b..e7e6009fd 100644 +--- a/src/desktop/ElectronUpdater.js ++++ b/src/desktop/ElectronUpdater.js +@@ -98,9 +98,14 @@ export class ElectronUpdater { + fs.accessSync(appUpdateYmlPath, fs.constants.R_OK) + } catch (e) { + console.log("no update info on disk, disabling updater.") ++ this._conf.setDesktopConfig('showAutoUpdateOption', false) + return + } + ++ // if we got here, we could theoretically download updates. ++ // show the option in the settings menu ++ this._conf.setDesktopConfig('showAutoUpdateOption', true) ++ + // if user changes auto update setting, we want to know + this._conf.removeListener('enableAutoUpdate', this._enableAutoUpdateListener) + .on('enableAutoUpdate', this._enableAutoUpdateListener) +diff --git a/src/desktop/config/DesktopConfigHandler.js b/src/desktop/config/DesktopConfigHandler.js +index ae753a1c1..d907968a6 100644 +--- a/src/desktop/config/DesktopConfigHandler.js ++++ b/src/desktop/config/DesktopConfigHandler.js +@@ -11,6 +11,7 @@ export const DesktopConfigKey = { + heartbeatTimeoutInSeconds: 'heartbeatTimeoutInSeconds', + defaultDownloadPath: 'defaultDownloadPath', + enableAutoUpdate: 'enableAutoUpdate', ++ showAutoUpdateOption: 'showAutoUpdateOption', + pushIdentifier: 'pushIdentifier', + runAsTrayApp: 'runAsTrayApp', + lastBounds: 'lastBounds', +diff --git a/src/desktop/config/migrations/DesktopConfigMigrator.js b/src/desktop/config/migrations/DesktopConfigMigrator.js +index 5914bc235..e23e22981 100644 +--- a/src/desktop/config/migrations/DesktopConfigMigrator.js ++++ b/src/desktop/config/migrations/DesktopConfigMigrator.js +@@ -15,6 +15,8 @@ export default function applyMigrations(migrationFunction: "migrateClient" | "mi + oldConfig = applyMigration(require('./migration-0000')[migrationFunction], oldConfig) + // no break, fallthrough applies all migrations in sequence + case 0: ++ oldConfig = applyMigration(require('./migration-0001')[migrationFunction], oldConfig) ++ case 1: + console.log("config up to date") + /* add new migrations as needed */ + break; +diff --git a/src/desktop/config/migrations/migration-0001.js b/src/desktop/config/migrations/migration-0001.js +new file mode 100644 +index 000000000..c46c19bf3 +--- /dev/null ++++ b/src/desktop/config/migrations/migration-0001.js +@@ -0,0 +1,7 @@ ++// @flow ++function migrate(oldConfig: any) { ++ return Object.assign(oldConfig, {"desktopConfigVersion": 1, "showAutoUpdateOption": true}) ++} ++ ++export const migrateClient = migrate ++export const migrateAdmin = migrate +\ No newline at end of file +diff --git a/src/settings/DesktopSettingsViewer.js b/src/settings/DesktopSettingsViewer.js +index 4591adcce..a27e03134 100644 +--- a/src/settings/DesktopSettingsViewer.js ++++ b/src/settings/DesktopSettingsViewer.js +@@ -32,6 +32,7 @@ export class DesktopSettingsViewer implements UpdatableSettingsViewer { + _runOnStartup: Stream<?boolean>; + _isIntegrated: Stream<?boolean>; + _isAutoUpdateEnabled: Stream<?boolean>; ++ _showAutoUpdateOption: Stream<?boolean>; + _isPathDialogOpen: boolean; + + constructor() { +@@ -40,6 +41,7 @@ export class DesktopSettingsViewer implements UpdatableSettingsViewer { + this._runOnStartup = stream(false) + this._isIntegrated = stream(false) + this._isAutoUpdateEnabled = stream(false) ++ this._showAutoUpdateOption = stream(true) + this._requestDesktopConfig() + } + +@@ -157,7 +159,7 @@ export class DesktopSettingsViewer implements UpdatableSettingsViewer { + m(DropDownSelectorN, setRunOnStartupAttrs), + m(TextFieldN, defaultDownloadPathAttrs), + env.platformId === 'linux' ? m(DropDownSelectorN, setDesktopIntegrationAttrs) : null, +- m(DropDownSelectorN, setAutoUpdateAttrs) ++ this._showAutoUpdateOption() ? m(DropDownSelectorN, setAutoUpdateAttrs) : null, + ]) + ] + } +@@ -190,6 +192,7 @@ export class DesktopSettingsViewer implements UpdatableSettingsViewer { + this._runAsTrayApp(desktopConfig.runAsTrayApp) + this._runOnStartup(desktopConfig.runOnStartup) + this._isIntegrated(desktopConfig.isIntegrated) ++ this._showAutoUpdateOption(desktopConfig.showAutoUpdateOption) + this._isAutoUpdateEnabled(desktopConfig.enableAutoUpdate) + m.redraw() + }) +diff --git a/test/client/desktop/ElectronUpdaterTest.js b/test/client/desktop/ElectronUpdaterTest.js +index d5b4194db..c686f1c39 100644 +--- a/test/client/desktop/ElectronUpdaterTest.js ++++ b/test/client/desktop/ElectronUpdaterTest.js +@@ -123,10 +123,13 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + const conf = { + removeListener: (key: string, cb: ()=>void) => n.spyify(conf), + on: (key: string) => n.spyify(conf), ++ setDesktopConfig: (key, value) => {}, + getDesktopConfig: (key: string) => { + switch (key) { + case 'enableAutoUpdate': + return true ++ case 'showAutoUpdateOption': ++ return true + default: + throw new Error(`unexpected getDesktopConfig key ${key}`) + } +@@ -170,6 +173,9 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + + upd.start() + ++ o(confMock.setDesktopConfig.callCount).equals(1) ++ o(confMock.setDesktopConfig.args).deepEquals(['showAutoUpdateOption', true]) ++ + // there is only one enableAutoUpdate listener + o(confMock.removeListener.callCount).equals(1) + o(confMock.removeListener.args[0]).equals('enableAutoUpdate') +@@ -278,6 +284,8 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + switch (key) { + case 'enableAutoUpdate': + return enabled ++ case 'showAutoUpdateOption': ++ return true + default: + throw new Error(`unexpected getDesktopConfig key ${key}`) + } +@@ -531,6 +539,8 @@ o.spec("ElectronUpdater Test", function (done, timeout) { + + upd.start() + ++ o(confMock.setDesktopConfig.callCount).equals(1) ++ o(confMock.setDesktopConfig.args).deepEquals(['showAutoUpdateOption', false]) + o(confMock.removeListener.callCount).equals(0) + } + ) +diff --git a/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js b/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js +index 47e3c943a..2f15ea616 100644 +--- a/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js ++++ b/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js +@@ -15,7 +15,8 @@ o.spec('desktop config migrator test', function () { + "defaultDownloadPath": null, + "enableAutoUpdate": true, + "runAsTrayApp": true, +- "desktopConfigVersion": 0 ++ "desktopConfigVersion": 1, ++ "showAutoUpdateOption": true, + } + + o(migrator("migrateClient", oldConfig, oldConfig)).deepEquals(requiredResult) +@@ -28,7 +29,8 @@ o.spec('desktop config migrator test', function () { + } + const requiredResult = { + "runAsTrayApp": true, +- "desktopConfigVersion": 0 ++ "desktopConfigVersion": 1, ++ "showAutoUpdateOption": true, + } + + o(migrator("migrateAdmin", oldConfig, oldConfig)).deepEquals(requiredResult) + +From 75330e12c0019db586c4cb91f3dbe0afa8a744b7 Mon Sep 17 00:00:00 2001 +From: nig <nig@tutao.de> +Date: Tue, 7 Apr 2020 10:32:03 +0200 +Subject: [PATCH 4/4] [desktop] define options object for desktopBuilder + +--- + buildSrc/DesktopBuilder.js | 58 ++++++++++++------ + buildSrc/electron-package-json-template.js | 4 +- + dist.js | 60 ++++++++++++++----- + make.js | 14 ++--- + src/desktop/ElectronUpdater.js | 2 + + .../migrations/DesktopConfigMigratorTest.js | 11 +++- + 6 files changed, 105 insertions(+), 44 deletions(-) + +diff --git a/buildSrc/DesktopBuilder.js b/buildSrc/DesktopBuilder.js +index 8449c5923..45fbaaa5f 100644 +--- a/buildSrc/DesktopBuilder.js ++++ b/buildSrc/DesktopBuilder.js +@@ -3,7 +3,17 @@ const babel = Promise.promisifyAll(require("babel-core")) + const fs = Promise.promisifyAll(require("fs-extra")) + const path = require("path") + +-function build(dirname, version, targets, updateUrl, nameSuffix, notarize, outDir, unpacked) { ++function build(opts) { ++ let { ++ dirname, // directory this was called from ++ version, // application version that gets built ++ targets, // which desktop targets to build and how to package them ++ updateUrl, // where the client should pull its updates from, if any ++ nameSuffix, // suffix used to distinguish test-, prod- or snapshot builds on the same machine ++ notarize, // for the MacOs notarization feature ++ outDir, // where to copy the finished artifacts ++ unpacked // output desktop client without packing it into an installer ++ } = opts + const targetString = Object.keys(targets) + .filter(k => typeof targets[k] !== "undefined") + .join(" ") +@@ -17,15 +27,16 @@ function build(dirname, version, targets, updateUrl, nameSuffix, notarize, outDi + .map(fn => path.join(dirname, './src/translations', fn)) + + console.log("Updating electron-builder config...") +- const content = require('./electron-package-json-template')( +- nameSuffix, +- version, +- updateUrl, +- path.join(dirname, "/resources/desktop-icons/logo-solo-red.png"), +- nameSuffix !== '-snapshot' && updateUrl !== "", // don't sign if it's a test build or if we don't download updates +- notarize, +- unpacked +- ) ++ const content = require('./electron-package-json-template')({ ++ nameSuffix: nameSuffix, ++ version: version, ++ updateUrl: updateUrl, ++ iconPath: path.join(dirname, "/resources/desktop-icons/logo-solo-red.png"), ++ sign: nameSuffix !== '-snapshot' && updateUrl !== "", ++ nameSuffix: nameSuffix, ++ notarize: notarize, ++ unpacked: unpacked ++ }) + let writeConfig = fs.writeFileAsync("./build/dist/package.json", JSON.stringify(content), 'utf-8') + + //prepare files +@@ -53,17 +64,26 @@ function build(dirname, version, targets, updateUrl, nameSuffix, notarize, outDi + .then(() => { + const installerDir = path.join(distDir, 'installers') + console.log("Move artifacts to", outDir) +- const unpackedFilter = file => file.endsWith("-unpacked") || file === "mac" +- const packedFilter = file => file.startsWith(content.name) || file.endsWith('.yml') ++ const outFiles = fs.readdirSync(installerDir) ++ let filesToCopy ++ // the output of the builder is very inconsistently named and contains ++ // files that are irrelevant to us. these filters enable us to copy them ++ // without naming every possible file name explicitly ++ if (unpacked) { ++ // when the unpacked option is set, output is a directory for each platform, with ++ // the mac directory missing the "-unpacked" suffix. ++ filesToCopy = outFiles.filter(file => file.endsWith("-unpacked") || file === "mac") ++ } else { ++ // the installers start with the application name + suffix. the update manifests end in yml. ++ filesToCopy = outFiles.filter(file => file.startsWith(content.name) || file.endsWith('.yml')) ++ } + + return Promise.all( +- fs.readdirSync(installerDir) +- .filter(unpacked ? unpackedFilter : packedFilter) +- .map(file => fs.moveAsync( +- path.join(installerDir, file), +- path.join(outDir, file) +- ) +- ) ++ filesToCopy.map(file => fs.moveAsync( ++ path.join(installerDir, file), ++ path.join(outDir, file) ++ ) ++ ) + ) + }).then(() => Promise.all([ + fs.removeAsync(path.join(distDir, '/installers/')), +diff --git a/buildSrc/electron-package-json-template.js b/buildSrc/electron-package-json-template.js +index a24067fb3..5fc9e2706 100644 +--- a/buildSrc/electron-package-json-template.js ++++ b/buildSrc/electron-package-json-template.js +@@ -6,7 +6,9 @@ const pj = require('../package.json') + * 2. copied to app-desktop/build/dist from dist.js (DesktopBuilder) + */ + +-module.exports = function (nameSuffix, version, updateUrl, iconPath, sign, notarize, unpacked) { ++module.exports = function (opts) { ++ const {nameSuffix, version, updateUrl, iconPath, sign, notarize, unpacked} = opts ++ + return { + "name": "tutanota-desktop" + nameSuffix, + "main": "./src/desktop/DesktopMain.js", +diff --git a/dist.js b/dist.js +index 2731f8bf9..c7dc6f993 100644 +--- a/dist.js ++++ b/dist.js +@@ -185,34 +185,66 @@ function buildWebapp() { + function buildDesktopClient() { + if (options.desktop) { + const desktopBuilder = require('./buildSrc/DesktopBuilder.js') +- if (options.stage === "release") { +- const updateUrl = options.customDesktopRelease ++ const desktopBaseOpts = { ++ dirname: __dirname, ++ version: version, ++ targets: options.desktop, ++ updateUrl: options.customDesktopRelease + ? "" +- : "https://mail.tutanota.com/desktop" +- const notarize = !!options.customDesktopRelease ++ : "https://mail.tutanota.com/desktop", ++ nameSuffix: "", ++ notarize: !!options.customDesktopRelease, ++ outDir: options.outDir, ++ unpacked: options.unpacked ++ } ++ if (options.stage === "release") { + const buildPromise = createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://mail.tutanota.com", version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, version, options.desktop, updateUrl, "", notarize, options.outDir, options.unpacked)) ++ .then(() => desktopBuilder.build(desktopBaseOpts)) + if (!options.customDesktopRelease) { // don't build the test version for manual/custom builds ++ const desktopTestOpts = Object.assign({}, desktopBaseOpts, { ++ updateUrl: "https://test.tutanota.com", ++ nameSuffix: "-test", ++ notarize: true ++ }) + buildPromise.then(() => createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://test.tutanota.com", version, "Desktop", true), bundles)) +- .then(() => desktopBuilder.build(__dirname, version, options.desktop, "https://test.tutanota.com/desktop", "-test", /*notarize*/true, options.outDir, options.unpacked)) ++ .then(() => desktopBuilder.build(desktopTestOpts)) + } + return buildPromise + } else if (options.stage === "local") { ++ const desktopLocalOpts = Object.assign({}, desktopBaseOpts, { ++ version: `${new Date().getTime()}.0.0`, ++ updateUrl: "http://localhost:9000", ++ nameSuffix: "-snapshot", ++ notarize: false ++ }) + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "http://localhost:9000", version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "http://localhost:9000", "-snapshot", options.outDir, options.unpacked)) ++ .then(() => desktopBuilder.build(desktopLocalOpts)) + } else if (options.stage === "test") { ++ const desktopTestOpts = Object.assign({}, desktopBaseOpts, { ++ version: `${new Date().getTime()}.0.0`, ++ updateUrl: "https://test.tutanota.com/desktop", ++ nameSuffix: "-test", ++ notarize: false ++ }) + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://test.tutanota.com", version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "https://test.tutanota.com/desktop", "-test", options.outDir, options.unpacked)) ++ .then(() => desktopBuilder.build(desktopTestOpts)) + } else if (options.stage === "prod") { ++ const desktopProdOpts = Object.assign({}, desktopBaseOpts, { ++ version: `${new Date().getTime()}.0.0`, ++ updateUrl: "http://localhost:9000/desktop", ++ notarize: false ++ }) + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), "https://mail.tutanota.com", version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "http://localhost:9000/desktop", "", options.outDir, options.unpacked)) ++ .then(() => desktopBuilder.build(desktopProdOpts)) + } else { // stage = host ++ const desktopHostOpts = Object.assign({}, desktopBaseOpts, { ++ version: `${new Date().getTime()}.0.0`, ++ updateUrl: "http://localhost:9000/desktop-snapshot", ++ nameSuffix: "-snapshot", ++ notarize: false ++ }) + return createHtml(env.create(SystemConfig.distRuntimeConfig(bundles), options.host, version, "Desktop", true), bundles) +- .then(() => desktopBuilder.build(__dirname, `${new Date().getTime()}.0.0`, +- options.desktop, "http://localhost:9000/desktop-snapshot", "-snapshot", options.outDir, options.unpacked)) ++ .then(() => desktopBuilder.build(desktopHostOpts)) + } + } + } +diff --git a/make.js b/make.js +index 14ea97356..1530125fe 100644 +--- a/make.js ++++ b/make.js +@@ -87,13 +87,13 @@ function startDesktop() { + if (options.desktop) { + console.log("Trying to start desktop client...") + const version = require('./package.json').version +- const packageJSON = require('./buildSrc/electron-package-json-template.js')( +- "-debug", +- version, +- "http://localhost:9000", +- path.join(__dirname, "/resources/desktop-icons/logo-solo-red.png"), +- false +- ) ++ const packageJSON = require('./buildSrc/electron-package-json-template.js')({ ++ nameSuffix: "-debug", ++ version: version, ++ updateUrl: "http://localhost:9000", ++ iconPath: path.join(__dirname, "/resources/desktop-icons/logo-solo-red.png"), ++ sign: false ++ }) + const content = JSON.stringify(packageJSON) + return fs.writeFileAsync("./build/package.json", content, 'utf-8') + .then(() => { +diff --git a/src/desktop/ElectronUpdater.js b/src/desktop/ElectronUpdater.js +index e7e6009fd..efcdeef3c 100644 +--- a/src/desktop/ElectronUpdater.js ++++ b/src/desktop/ElectronUpdater.js +@@ -36,6 +36,8 @@ export class ElectronUpdater { + error: (m: string, ...args: any) => console.error.apply(console, ["autoUpdater error:\n", m].concat(args)), + } + autoUpdater.logger = null ++ // default behaviour is to just dl the update as soon as found, but we want to check the signature ++ // before doing telling the updater to get the file. + autoUpdater.autoDownload = false + autoUpdater.autoInstallOnAppQuit = false + autoUpdater.on('update-available', updateInfo => { +diff --git a/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js b/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js +index 2f15ea616..228808869 100644 +--- a/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js ++++ b/test/client/desktop/config/migrations/DesktopConfigMigratorTest.js +@@ -7,9 +7,14 @@ o.spec('desktop config migrator test', function () { + o("migrations result in correct default config, client", function () { + const migrator = n.subject('../../src/desktop/config/migrations/DesktopConfigMigrator.js').default + const configPath = "../../../../../../buildSrc/electron-package-json-template.js" +- const oldConfig = require(configPath)( +- "", "0.0.0", "", "", "", false, false +- )["tutao-config"]["defaultDesktopConfig"] ++ const oldConfig = require(configPath)({ ++ nameSuffix: "", ++ version: "0.0.0", ++ updateUrl: "", ++ iconPath: "", ++ sign: false, ++ notarize: false ++ })["tutao-config"]["defaultDesktopConfig"] + const requiredResult = { + "heartbeatTimeoutInSeconds": 30, + "defaultDownloadPath": null, @@ -1,7 +1,8 @@ # Maintainer: Mark Wagie <mark dot wagie at tutanota dot com> # Co-Maintainer: Aaron J. Graves <linux@ajgraves.com> +# Contributor: ganthern <https://github.com/ganthern> pkgname=tutanota-desktop -pkgver=3.70.1 +pkgver=3.71.4 pkgrel=1 pkgdesc="Official Tutanota email client" arch=('x86_64') @@ -10,34 +11,32 @@ license=('GPL3') depends=('nss' 'libxss' 'libxtst' 'libappindicator-gtk3' 'libnotify') makedepends=('npm') source=("https://github.com/tutao/tutanota/archive/tutanota-release-$pkgver.tar.gz" + '1928.patch' "$pkgname" "$pkgname.desktop") -sha256sums=('37cc07bb49836e58ab9e72067fff9e48da48eeecd4ce216dc464f8ae6761f74d' +sha256sums=('e4fbf7a8876433dc1ffdd9e24d6dc980e7b2ff2e4da389169aec72588babd41e' + '614755f15fe792caf617829b19198d6a74b480436fea45568b315773c60a9ae6' '4f91e842bd92a3312943854383e4929f9baf6cb684a7027aa55edcce1bf4ca16' '1215678e2fc23cfbeb73063f68dc440891e5b2e10734fa7f402e06860c292e31') prepare() { cd "${pkgname%-*}-${pkgname%-*}-release-$pkgver" - # Change target to dir instead of AppImage - sed -i 's/"target": "AppImage"/"target": "dir"/g' \ - buildSrc/electron-package-json-template.js - - # Disable removing distDir - sed -i '65d' buildSrc/DesktopBuilder.js + # add builds w/o auto-updates and unpacked builds, close #1857 + patch -p1 -i "$srcdir/1928.patch" } build() { cd "${pkgname%-*}-${pkgname%-*}-release-$pkgver" npm install --cache "$srcdir/npm-cache" - node dist -l prod + node dist -l --custom-desktop-release --unpacked } package() { cd "${pkgname%-*}-${pkgname%-*}-release-$pkgver" install -d "$pkgdir/opt/$pkgname" - cp -r build/dist/installers/linux-unpacked/* \ + cp -r build/desktop/linux-unpacked/* \ "$pkgdir/opt/$pkgname" install -Dm755 "$srcdir/$pkgname" -t "$pkgdir/usr/bin" |