diff --git a/.idea/dictionaries/develar.xml b/.idea/dictionaries/develar.xml index 9a59bac7321..d939896b614 100644 --- a/.idea/dictionaries/develar.xml +++ b/.idea/dictionaries/develar.xml @@ -16,6 +16,7 @@ appdmg appimage appimagekit + appimagetool appleid appveyor appx @@ -92,6 +93,8 @@ eperm epipe evolvehq + exdev + extname faroese fcopy ffmpeg @@ -221,6 +224,7 @@ nokeys nomacver noninteractive + noupdate npmrc nsis nsisdir diff --git a/docker/appImage.sh b/docker/appImage.sh deleted file mode 100755 index 5a767be54f8..00000000000 --- a/docker/appImage.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -e - -dir=${PWD##*/} -rm -rf ~/AppImage-09-07-16.7z -7za a -m0=lzma2 -mx=9 -mfb=64 -md=64m -ms=on ~/AppImage-09-07-16.7z . \ No newline at end of file diff --git a/docs/icons.md b/docs/icons.md index 9dddf487df6..dffa11ac4b1 100644 --- a/docs/icons.md +++ b/docs/icons.md @@ -1,4 +1,5 @@ -Recommended tools: [MakeAppIcon](https://makeappicon.com/), [AppIcon Generator](http://www.tweaknow.com/appicongenerator.php). +Recommended tools: [AppIcon Generator](http://www.tweaknow.com/appicongenerator.php), [MakeAppIcon](https://makeappicon.com/) +. ## macOS @@ -20,7 +21,7 @@ need to be placed in the [build](/configuration/configuration.md#MetadataDirecto Linux icon set will be generated automatically based on the macOS `icns` file. Or you can put them into the `build/icons` directory if you want to specify them yourself. -The filename must contain the size (e.g. `32x32.png`) of the icon). Recommended sizes: 16, 24, 32, 48, 64, 96, 128, 512, 1024 (or just 512). +The filename must contain the size (e.g. `32x32.png`) of the icon). Recommended sizes: 16, 24, 32, 48, 64, 96, 128, 256. (or just 512). ## AppX diff --git a/packages/builder-util/src/fs.ts b/packages/builder-util/src/fs.ts index ab44b66e17a..0a2c3d0841f 100644 --- a/packages/builder-util/src/fs.ts +++ b/packages/builder-util/src/fs.ts @@ -137,7 +137,7 @@ export function copyFile(src: string, dest: string, isEnsureDir = true) { * * ensureDir is not called, dest parent dir must exists */ -export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, isUseHardLink = _isUseHardLink): Promise { +export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, isUseHardLink = _isUseHardLink, exDevErrorHandler?: (() => boolean) | null): Promise { if (stats != null) { const originalModeNumber = stats.mode const mode = new Mode(stats) @@ -167,8 +167,23 @@ export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, if (isUseHardLink) { return link(src, dest) + .catch(e => { + if (e.code === "EXDEV") { + const isLog = exDevErrorHandler == null ? true : exDevErrorHandler() + if (isLog && debug.enabled) { + debug(`Cannot copy using hard link: ${e.message}`) + } + return doCopyFile(src, dest, stats) + } + else { + throw e + } + }) } + return doCopyFile(src, dest, stats) +} +function doCopyFile(src: string, dest: string, stats: Stats | null | undefined): Promise { if (_nodeCopyFile == null) { return new BluebirdPromise((resolve, reject) => { const reader = createReadStream(src) @@ -181,16 +196,15 @@ export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, writer.once("close", resolve) }) } - else { - // node 8.5.0 - return _nodeCopyFile(src, dest) - .then((): any => { - if (stats != null) { - return chmod(dest, stats.mode) - } - return null - }) + + // node 8.5.0+ + const promise = _nodeCopyFile(src, dest) + if (stats == null) { + return promise } + + return promise + .then(() => chmod(dest, stats.mode)) } export class FileCopier { @@ -201,37 +215,29 @@ export class FileCopier { } async copy(src: string, dest: string, stat: Stats | undefined) { - try { - if (this.transformer != null && stat != null && stat.isFile()) { - let data = this.transformer(src) - if (data != null) { - if (typeof (data as any).then === "function") { - data = await data - } + if (this.transformer != null && stat != null && stat.isFile()) { + let data = this.transformer(src) + if (data != null) { + if (typeof (data as any).then === "function") { + data = await data + } - if (data != null) { - await writeFile(dest, data) - return - } + if (data != null) { + await writeFile(dest, data) + return } } - await copyOrLinkFile(src, dest, stat, (!this.isUseHardLink || this.isUseHardLinkFunction == null) ? this.isUseHardLink : this.isUseHardLinkFunction(dest)) } - catch (e) { + await copyOrLinkFile(src, dest, stat, (!this.isUseHardLink || this.isUseHardLinkFunction == null) ? this.isUseHardLink : this.isUseHardLinkFunction(dest), this.isUseHardLink ? () => { // files are copied concurrently, so, we must not check here currentIsUseHardLink — our code can be executed after that other handler will set currentIsUseHardLink to false - if (e.code === "EXDEV") { - // ...but here we want to avoid excess debug log message - if (this.isUseHardLink) { - debug(`Cannot copy using hard link: ${e}`) - this.isUseHardLink = false - } - - await copyOrLinkFile(src, dest, stat, false) + if (this.isUseHardLink) { + this.isUseHardLink = false + return true } else { - throw e + return false } - } + } : null) } } diff --git a/packages/electron-builder/src/targets/LinuxTargetHelper.ts b/packages/electron-builder/src/targets/LinuxTargetHelper.ts index 5212cf3eb46..da467d6633b 100644 --- a/packages/electron-builder/src/targets/LinuxTargetHelper.ts +++ b/packages/electron-builder/src/targets/LinuxTargetHelper.ts @@ -9,8 +9,13 @@ import { getTemplatePath } from "../util/pathManager" export const installPrefix = "/opt" +export interface IconInfo { + file: string + size: number +} + export class LinuxTargetHelper { - readonly icons: Promise>> + readonly icons: Promise> maxIconPath: string | null = null @@ -19,7 +24,7 @@ export class LinuxTargetHelper { } // must be name without spaces and other special characters, but not product name used - private async computeDesktopIcons(): Promise>> { + private async computeDesktopIcons(): Promise> { const packager = this.packager const customIconSetDir = packager.platformSpecificBuildOptions.icon if (customIconSetDir != null) { @@ -55,7 +60,7 @@ export class LinuxTargetHelper { } private async iconsFromDir(iconDir: string) { - const mappings: Array> = [] + const mappings: Array = [] let maxSize = 0 for (const file of (await readdir(iconDir))) { if (file.endsWith(".png") || file.endsWith(".PNG")) { @@ -66,7 +71,10 @@ export class LinuxTargetHelper { const size = sizeString == null ? 0 : parseInt(sizeString[0], 10) if (size > 0) { const iconPath = `${iconDir}/${file}` - mappings.push([iconPath, `${size}x${size}/apps/${this.packager.executableName}.png`]) + mappings.push({ + file: iconPath, + size, + }) if (size > maxSize) { maxSize = size @@ -100,7 +108,14 @@ export class LinuxTargetHelper { return options.description || this.packager.appInfo.description } - async computeDesktopEntry(targetSpecificOptions: LinuxTargetSpecificOptions, exec?: string, destination?: string | null, extra?: { [key: string]: string; }): Promise { + async writeDesktopEntry(targetSpecificOptions: LinuxTargetSpecificOptions, exec?: string, destination?: string | null, extra?: { [key: string]: string; }): Promise { + const data = await this.computeDesktopEntry(targetSpecificOptions, exec, extra) + const tempFile = destination || await this.packager.getTempFile(`${this.packager.appInfo.productFilename}.desktop`) + await outputFile(tempFile, data) + return tempFile + } + + async computeDesktopEntry(targetSpecificOptions: LinuxTargetSpecificOptions, exec?: string, extra?: { [key: string]: string; }): Promise { if (exec != null && exec.length === 0) { throw new Error("Specified exec is emptyd") } @@ -115,7 +130,9 @@ export class LinuxTargetHelper { Exec: exec == null ? `"${installPrefix}/${productFilename}/${this.packager.executableName}" %U` : exec, Terminal: "false", Type: "Application", - Icon: this.packager.executableName, ...extra, ...targetSpecificOptions.desktop + Icon: this.packager.executableName, + ...extra, + ...targetSpecificOptions.desktop, } let category = targetSpecificOptions.category @@ -143,13 +160,10 @@ export class LinuxTargetHelper { data += `\n${name}=${value}` } data += "\n" - - const tempFile = destination || await this.packager.getTempFile(`${productFilename}.desktop`) - await outputFile(tempFile, data) - return tempFile + return data } - private async createFromIcns(tempDir: string): Promise>> { + private async createFromIcns(tempDir: string): Promise> { const iconPath = await this.getIcns() if (iconPath == null) { return await this.iconsFromDir(path.join(getTemplatePath("linux"), "electron-icons")) @@ -210,22 +224,23 @@ export class LinuxTargetHelper { } private createMappings(tempDir: string) { - const name = this.packager.executableName - - function createMapping(size: string) { - return [process.platform === "darwin" ? `${tempDir}/icon_${size}x${size}.png` : `${tempDir}/icon_${size}x${size}x32.png`, `${size}x${size}/apps/${name}.png`] + function createMapping(size: number): IconInfo { + return { + file: process.platform === "darwin" ? `${tempDir}/icon_${size}x${size}.png` : `${tempDir}/icon_${size}x${size}x32.png`, + size, + } } return [ - createMapping("16"), - createMapping("24"), - createMapping("32"), - createMapping("48"), - createMapping("64"), - createMapping("96"), - createMapping("128"), - createMapping("256"), - createMapping("512"), + createMapping(16), + createMapping(24), + createMapping(32), + createMapping(48), + createMapping(64), + createMapping(96), + createMapping(128), + createMapping(256), + createMapping(512), ] } } diff --git a/packages/electron-builder/src/targets/appImage.ts b/packages/electron-builder/src/targets/appImage.ts index 9b837bbf5cc..5d3831cc594 100644 --- a/packages/electron-builder/src/targets/appImage.ts +++ b/packages/electron-builder/src/targets/appImage.ts @@ -1,10 +1,10 @@ import BluebirdPromise from "bluebird-lst" -import { Arch, exec, log } from "builder-util" +import { Arch, exec, log, debug } from "builder-util" import { UUID } from "builder-util-runtime" -import { getBin, getBinFromGithub } from "builder-util/out/binDownload" -import { unlinkIfExists } from "builder-util/out/fs" +import { getBinFromGithub } from "builder-util/out/binDownload" +import { unlinkIfExists, copyFile, copyOrLinkFile } from "builder-util/out/fs" import * as ejs from "ejs" -import { chmod, close, createReadStream, createWriteStream, open, outputFile, readFile, write } from "fs-extra-p" +import { emptyDir, readFile, remove, writeFile } from "fs-extra-p" import { Lazy } from "lazy-val" import * as path from "path" import { Target } from "../core" @@ -13,28 +13,22 @@ import { AppImageOptions } from "../options/linuxOptions" import { getTemplatePath } from "../util/pathManager" import { LinuxTargetHelper } from "./LinuxTargetHelper" -const appImageVersion = process.platform === "darwin" ? "AppImage-17-06-17-mac" : "AppImage-09-07-16-linux" -//noinspection SpellCheckingInspection -const appImagePathPromise = process.platform === "darwin" ? - getBinFromGithub("AppImage", "17-06-17-mac", "vIaikS8Z2dEnZXKSgtcTn4gimPHCclp+v62KV2Eh9EhxvOvpDFgR3FCgdOsON4EqP8PvnfifNtxgBixCfuQU0A==") : - getBin("AppImage", appImageVersion, `https://dl.bintray.com/electron-userland/bin/${appImageVersion}.7z`, "ac324e90b502f4e995f6a169451dbfc911bb55c0077e897d746838e720ae0221") - const appRunTemplate = new Lazy<(data: any) => string>(async () => { return ejs.compile(await readFile(path.join(getTemplatePath("linux"), "AppRun.sh"), "utf-8")) }) export default class AppImageTarget extends Target { readonly options: AppImageOptions = {...this.packager.platformSpecificBuildOptions, ...(this.packager.config as any)[this.name]} - private readonly desktopEntry: Promise + private readonly desktopEntry: Lazy constructor(ignored: string, private readonly packager: LinuxPackager, private readonly helper: LinuxTargetHelper, readonly outDir: string) { super("appImage") // we add X-AppImage-BuildId to ensure that new desktop file will be installed - this.desktopEntry = helper.computeDesktopEntry(this.options, "AppRun", null, { + this.desktopEntry = new Lazy(() => helper.computeDesktopEntry(this.options, "AppRun", { "X-AppImage-Version": `${packager.appInfo.buildVersion}`, "X-AppImage-BuildId": UUID.v1(), - }) + })) } async build(appOutDir: string, arch: Arch): Promise { @@ -46,78 +40,96 @@ export default class AppImageTarget extends Target { // https://github.com/electron-userland/electron-builder/issues/1726 const artifactName = this.options.artifactName == null ? packager.computeSafeArtifactName(null, "AppImage", arch, false)!! : packager.expandArtifactNamePattern(this.options, "AppImage", arch) const resultFile = path.join(this.outDir, artifactName) - await unlinkIfExists(resultFile) - const finalDesktopFilename = `${this.packager.executableName}.desktop` + // pax doesn't like dir with leading dot (e.g. `.__appimage`) + const stageDir = path.join(this.outDir, `__appimage-${Arch[arch]}`) + const appInStageDir = path.join(stageDir, "app") + await emptyDir(stageDir) + await copyDirUsingHardLinks(appOutDir, appInStageDir) - const appRunData = (await appRunTemplate.value)({ - systemIntegration: this.options.systemIntegration || "ask", - desktopFileName: finalDesktopFilename, - executableName: this.packager.executableName, - resourceName: `appimagekit-${this.packager.executableName}`, - }) - const appRunFile = await packager.getTempFile(".sh") - await outputFile(appRunFile, appRunData, { - mode: "0755", + const iconNames = await BluebirdPromise.map(this.helper.icons, it => { + const filename = `icon-${it.size}.png` + return copyOrLinkFile(it.file, path.join(stageDir, filename), null, true) + .then(() => ({filename, size: it.size})) }) - const desktopFile = await this.desktopEntry - const appImagePath = await appImagePathPromise - const args = [ - "-joliet", "on", - "-volid", "AppImage", - "-dev", resultFile, - "-padding", "0", - "-map", appOutDir, "/usr/bin", - "-map", appRunFile, "/AppRun", - // we get executable name in the AppRun by desktop file name, so, must be named as executable - "-map", desktopFile, `/${finalDesktopFilename}`, - ] - for (const [from, to] of (await this.helper.icons)) { - args.push("-map", from, `/usr/share/icons/default/${to}`) + const resourceName = `appimagekit-${this.packager.executableName}` + + let installIcons = "" + for (const icon of iconNames) { + installIcons += `xdg-icon-resource install --noupdate --context apps --size ${icon.size} "$APPDIR/${icon.filename}" "${resourceName}"\n` } + const finalDesktopFilename = `${this.packager.executableName}.desktop` + await BluebirdPromise.all([ + unlinkIfExists(resultFile), + writeFile(path.join(stageDir, "/AppRun"), (await appRunTemplate.value)({ + systemIntegration: this.options.systemIntegration || "ask", + desktopFileName: finalDesktopFilename, + executableName: this.packager.executableName, + resourceName, + installIcons, + }), { + mode: "0755", + }), + writeFile(path.join(stageDir, finalDesktopFilename), await this.desktopEntry.value), + ]) + // must be after this.helper.icons call if (this.helper.maxIconPath == null) { throw new Error("Icon is not provided") } - args.push("-map", this.helper.maxIconPath, "/.DirIcon") + await copyFile(this.helper.maxIconPath, path.join(stageDir, `${this.packager.executableName}${path.extname(this.helper.maxIconPath)}`)) + + //noinspection SpellCheckingInspection + const vendorDir = await getBinFromGithub("appimage", "9", "5ilKGGAc9eQOJTxnUsYHVppFBxQJCaVVDFYrTGsabtgqxcPsnHc+t2Ilc6PeDiszietMtkdUPjNYKWL2nAS67Q==") if (arch === Arch.x64 || arch === Arch.ia32) { - // noinspection SpellCheckingInspection - args.push("-map", path.join(await getBinFromGithub("appimage-packages", "29-09-17", "sMMu1L1tL4QbzvGDxh1pNiIFC+ARnIOVvVdM0d6FBRtSDl0rHXgZMVLiuIAEz6+bJ+daHvYfLlPo1Y8zS6FXaQ=="), arch === Arch.x64 ? "x86_64-linux-gnu" : "i386-linux-gnu"), "/usr/lib") + await copyDirUsingHardLinks(path.join(vendorDir, "lib", arch === Arch.x64 ? "x86_64-linux-gnu" : "i386-linux-gnu"), path.join(stageDir, "usr/lib")) } - args.push("-chown_r", "0", "/", "--") - args.push("-zisofs", `level=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL || (packager.config.compression === "store" ? "0" : "9")}:block_size=128k:by_magic=off`) - args.push("set_filter_r", "--zisofs", "/") - - if (this.packager.packagerOptions.effectiveOptionComputed != null && await this.packager.packagerOptions.effectiveOptionComputed([args, desktopFile])) { + if (this.packager.packagerOptions.effectiveOptionComputed != null && await this.packager.packagerOptions.effectiveOptionComputed({desktop: await this.desktopEntry.value})) { return } - await exec(process.arch !== "x64" || (process.env.USE_SYSTEM_XORRISO === "true" || process.env.USE_SYSTEM_XORRISO === "") ? "xorriso" : path.join(appImagePath, "xorriso"), args) - - await new BluebirdPromise((resolve, reject) => { - const rd = createReadStream(path.join(appImagePath, arch === Arch.ia32 ? "32" : "64", "runtime")) - rd.on("error", reject) - const wr = createWriteStream(resultFile, {flags: "r+"}) - wr.on("error", reject) - wr.on("close", resolve) - rd.pipe(wr) - }) - - const fd = await open(resultFile, "r+") - try { - const magicData = Buffer.from([0x41, 0x49, 0x01]) - await write(fd, magicData, 0, magicData.length, 8) + const env = { + ...process.env, } - finally { - await close(fd) + let toolPath: string + if (process.platform === "darwin") { + const vendorToolDir = path.join(vendorDir, "darwin") + env.PATH = `${vendorToolDir}:${env.PATH}` + toolPath = path.join(vendorToolDir, "appimagetool") + } + else { + toolPath = path.join(vendorDir, `appimagetool-i686${arch === Arch.ia32 ? "i686" : "x86_64.AppImage"}`) } - await chmod(resultFile, "0755") - + // default gzip compression - 51.9, xz - 50.4 difference is negligible, start time - well, it seems, a little bit longer (but on Parallels VM on external SSD disk) + // so, to be decided later, is it worth to use xz by default + const args = ["--runtime-file", path.join(vendorDir, `runtime-${arch === Arch.ia32 ? "i686" : (arch === Arch.x64 ? "x86_64" : "armv7l")}`)] + if (debug.enabled) { + args.push("--verbose") + } + args.push(stageDir, resultFile) + await exec(toolPath, args, {env}) + if (!debug.enabled) { + await remove(stageDir) + } packager.dispatchArtifactCreated(resultFile, this, arch, packager.computeSafeArtifactName(artifactName, "AppImage", arch, false)) } } + +// https://unix.stackexchange.com/questions/202430/how-to-copy-a-directory-recursively-using-hardlinks-for-each-file +function copyDirUsingHardLinks(source: string, destination: string) { + // pax and cp requires created dir + const promise = emptyDir(destination) + if (process.platform !== "darwin") { + return promise.then(() => exec("cp", ["-d", "--recursive", "--preserve=mode", source, destination])) + } + + return promise + .then(() => exec("pax", ["-rwl", "-p", "amp" /* Do not preserve file access times, Do not preserve file modification times, Preserve the file mode bits */, ".", destination], { + cwd: source, + })) +} \ No newline at end of file diff --git a/packages/electron-builder/src/targets/fpm.ts b/packages/electron-builder/src/targets/fpm.ts index aba86cd4191..edb523ef5a8 100644 --- a/packages/electron-builder/src/targets/fpm.ts +++ b/packages/electron-builder/src/targets/fpm.ts @@ -184,11 +184,11 @@ export default class FpmTarget extends Target { use(options.fpm, it => args.push(...it as any)) args.push(`${appOutDir}/=${installPrefix}/${appInfo.productFilename}`) - for (const mapping of (await this.helper.icons)) { - args.push(mapping.join("=/usr/share/icons/hicolor/")) + for (const icon of (await this.helper.icons)) { + args.push(`${icon.file}=/usr/share/icons/hicolor/${icon.size}x${icon.size}/apps/${packager.executableName}.png`) } - const desktopFilePath = await this.helper.computeDesktopEntry(this.options) + const desktopFilePath = await this.helper.writeDesktopEntry(this.options) args.push(`${desktopFilePath}=/usr/share/applications/${this.packager.executableName}.desktop`) if (this.packager.packagerOptions.effectiveOptionComputed != null && await this.packager.packagerOptions.effectiveOptionComputed([args, desktopFilePath])) { diff --git a/packages/electron-builder/src/targets/snap.ts b/packages/electron-builder/src/targets/snap.ts index f5507c1be85..27ba995207f 100644 --- a/packages/electron-builder/src/targets/snap.ts +++ b/packages/electron-builder/src/targets/snap.ts @@ -48,7 +48,7 @@ export default class SnapTarget extends Target { await copyFile(this.helper.maxIconPath, path.join(snapDir, "gui", "icon.png")) } - const desktopFile = await this.helper.computeDesktopEntry(this.options, packager.executableName, path.join(snapDir, "gui", `${snap.name}.desktop`), { + const desktopFile = await this.helper.writeDesktopEntry(this.options, packager.executableName, path.join(snapDir, "gui", `${snap.name}.desktop`), { // tslint:disable:no-invalid-template-strings Icon: "${SNAP}/meta/gui/icon.png" }) diff --git a/packages/electron-builder/templates/linux/AppRun.sh b/packages/electron-builder/templates/linux/AppRun.sh index 2aae8ed470d..1d6c36a7e75 100755 --- a/packages/electron-builder/templates/linux/AppRun.sh +++ b/packages/electron-builder/templates/linux/AppRun.sh @@ -33,14 +33,14 @@ if [ -z $APPDIR ] ; then APPDIR=$(find-up "AppRun") fi -export PATH="${APPDIR}/usr/bin:${APPDIR}/usr/sbin:${PATH}" +export PATH="${APPDIR}/app:${APPDIR}/usr/sbin:${PATH}" export XDG_DATA_DIRS="./share/:/usr/share/gnome:/usr/local/share/:/usr/share/:${XDG_DATA_DIRS}" export LD_LIBRARY_PATH="${APPDIR}/usr/lib:${LD_LIBRARY_PATH}" export XDG_DATA_DIRS="${APPDIR}"/usr/share/:"${XDG_DATA_DIRS}":/usr/share/gnome/:/usr/local/share/:/usr/share/ export GSETTINGS_SCHEMA_DIR="${APPDIR}/usr/share/glib-2.0/schemas:${GSETTINGS_SCHEMA_DIR}" DESKTOP_FILE="$APPDIR/<%= desktopFileName %>" -BIN="$APPDIR/usr/bin/<%= executableName %>" +BIN="$APPDIR/app/<%= executableName %>" trap atexit EXIT @@ -194,11 +194,7 @@ if [ -z "$SKIP" ] ; then xdg-icon-resource uninstall --noupdate --size 1024 "<%= resourceName %>" # Install the icon files for the application - ICONS=$(find "${APPDIR}/usr/share/icons/" -wholename "*/apps/<%= executableName %>.png" 2>/dev/null || true) - for ICON in $ICONS ; do - ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1) - xdg-icon-resource install --context apps --size ${ICON_SIZE} "${ICON}" "<%= resourceName %>" - done + <%- installIcons %> xdg-icon-resource forceupdate diff --git a/test/fixtures/test-app-one/index.js b/test/fixtures/test-app-one/index.js index 2ea1c3e3de1..c3f858036c9 100644 --- a/test/fixtures/test-app-one/index.js +++ b/test/fixtures/test-app-one/index.js @@ -81,8 +81,8 @@ let mainWindow; let tray = null function createWindow () { - if (process.platform === "linux") { - tray = new Tray(path.join(process.resourcesPath, "32x32.png")) + if (process.platform === "linux" && process.env.APPDIR != null) { + tray = new Tray(path.join(process.env.APPDIR, "testapp.png")) const contextMenu = Menu.buildFromTemplate([ {label: 'Item1', type: 'radio'}, {label: 'Item2', type: 'radio'}, diff --git a/test/out/__snapshots__/BuildTest.js.snap b/test/out/__snapshots__/BuildTest.js.snap index af9c4aeeb88..d23cf898425 100644 --- a/test/out/__snapshots__/BuildTest.js.snap +++ b/test/out/__snapshots__/BuildTest.js.snap @@ -297,7 +297,7 @@ Object { "size": 841, }, "index.js": Object { - "size": 4342, + "size": 4371, }, "node_modules": Object { "files": Object { @@ -3808,7 +3808,7 @@ Object { "size": 841, }, "index.js": Object { - "size": 4342, + "size": 4371, }, "node_modules": Object { "files": Object { diff --git a/test/out/__snapshots__/globTest.js.snap b/test/out/__snapshots__/globTest.js.snap index e11c2ff8975..917042ca9b4 100644 --- a/test/out/__snapshots__/globTest.js.snap +++ b/test/out/__snapshots__/globTest.js.snap @@ -32,7 +32,7 @@ Object { exports[`outside link 2`] = ` Object { - "offset": "5439", + "offset": "5468", "size": 4, } `; diff --git a/test/out/linux/__snapshots__/linuxPackagerTest.js.snap b/test/out/linux/__snapshots__/linuxPackagerTest.js.snap index b903a2a8985..43615f26212 100644 --- a/test/out/linux/__snapshots__/linuxPackagerTest.js.snap +++ b/test/out/linux/__snapshots__/linuxPackagerTest.js.snap @@ -8,7 +8,7 @@ Exec=AppRun Terminal=true Type=Application Icon=Foo -Foo=bar +X-Foo=bar Categories=Development; " `; diff --git a/test/src/PublishManagerTest.ts b/test/src/PublishManagerTest.ts index fd92719051e..27f7c09a679 100644 --- a/test/src/PublishManagerTest.ts +++ b/test/src/PublishManagerTest.ts @@ -1,6 +1,7 @@ import { createTargets, Platform } from "electron-builder" import * as path from "path" import { app, checkDirContents } from "./helpers/packTester" +import { assertThat } from "./helpers/fileAssert" const target = Platform.MAC.createTarget("zip") @@ -31,7 +32,7 @@ test.ifAll.ifNotWindows("os macro", app({ publish: { provider: "s3", bucket: "my bucket", - // tslint:disable:no-invalid-template-strings + // tslint:disable-next-line:no-invalid-template-strings path: "${channel}/${os}" } }, @@ -40,8 +41,9 @@ test.ifAll.ifNotWindows("os macro", app({ projectDirCreated: async projectDir => { process.env.__TEST_S3_PUBLISHER__ = path.join(projectDir, "dist/s3") }, - packed: context => { + packed: async context => { const dir = path.join(context.projectDir, "dist/s3") - return checkDirContents(dir) + await assertThat(dir).isDirectory() + await checkDirContents(dir) } })) \ No newline at end of file diff --git a/test/src/linux/linuxPackagerTest.ts b/test/src/linux/linuxPackagerTest.ts index 63a14005504..cc28c47f506 100644 --- a/test/src/linux/linuxPackagerTest.ts +++ b/test/src/linux/linuxPackagerTest.ts @@ -1,5 +1,5 @@ import { Arch, build, Platform } from "electron-builder" -import { readFile, remove, rename } from "fs-extra-p" +import { remove, rename } from "fs-extra-p" import * as path from "path" import { assertThat } from "../helpers/fileAssert" import { app, appThrows, modifyPackageJson } from "../helpers/packTester" @@ -27,17 +27,17 @@ test.ifNotWindows.ifNotCiMac("AppImage - default icon, custom executable and cus linux: { executableName: "Foo", desktop: { - Foo: "bar", + "X-Foo": "bar", Terminal: "true", }, }, appImage: { - // tslint:disable:no-invalid-template-strings + // tslint:disable-next-line:no-invalid-template-strings artifactName: "boo-${productName}", } }, effectiveOptionComputed: async it => { - const content = await readFile(it[1], "utf-8") + const content: string = it.desktop expect(content.split("\n").filter(it => !it.includes("X-AppImage-BuildId") && !it.includes("X-AppImage-Version")).join("\n")).toMatchSnapshot() return false },