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
},