diff --git a/.idea/dictionaries/develar.xml b/.idea/dictionaries/develar.xml index 68739d4e80f..f3868690f1c 100644 --- a/.idea/dictionaries/develar.xml +++ b/.idea/dictionaries/develar.xml @@ -66,6 +66,7 @@ makensis minimatch mkdirp + mkdtemp mpass multilib multiuser diff --git a/.idea/runConfigurations/BuildTest.xml b/.idea/runConfigurations/BuildTest.xml index a8e2d4f3070..84eb02dad06 100644 --- a/.idea/runConfigurations/BuildTest.xml +++ b/.idea/runConfigurations/BuildTest.xml @@ -3,6 +3,12 @@ - + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/CodeSignTest.xml b/.idea/runConfigurations/CodeSignTest.xml index f0946aeda3c..4322aa815c4 100644 --- a/.idea/runConfigurations/CodeSignTest.xml +++ b/.idea/runConfigurations/CodeSignTest.xml @@ -1,5 +1,5 @@ - + @@ -9,6 +9,8 @@ - + + \ No newline at end of file diff --git a/.idea/runConfigurations/linuxPackagerTest.xml b/.idea/runConfigurations/linuxPackagerTest.xml index 66f9cec4093..dc6fad857b3 100644 --- a/.idea/runConfigurations/linuxPackagerTest.xml +++ b/.idea/runConfigurations/linuxPackagerTest.xml @@ -1,5 +1,5 @@ - + @@ -7,6 +7,8 @@ - + + \ No newline at end of file diff --git a/.idea/runConfigurations/osxPackagerTest.xml b/.idea/runConfigurations/osxPackagerTest.xml deleted file mode 100644 index 4a823a86878..00000000000 --- a/.idea/runConfigurations/osxPackagerTest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b75ae864f8..7243f5716be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,6 +88,7 @@ Only IntelliJ Platform IDEs (IntelliJ IDEA, WebStorm) support debug. [Forked ver Use one of the shared run configurations as a template and: +* Ensure that `Before launch` contains `Compile TypeScript`. * Set `Node interpreter` to NodeJS 7. Yes — NodeJS 7 is required to debug. Download [nightly build](https://nodejs.org/download/nightly/). * Set `Node parameters` to `--inspect`. * Set `Application Parameters` to `--match="test name" relative-test-file-name` if you want to debug particular test. E.g. diff --git a/src/codeSign.ts b/src/codeSign.ts index 623f870239c..c804ce3aa7a 100644 --- a/src/codeSign.ts +++ b/src/codeSign.ts @@ -1,12 +1,12 @@ import { exec, getTempName, isEmptyOrSpaces } from "./util/util" import { deleteFile, outputFile, copy, rename } from "fs-extra-p" import { download } from "./util/httpRequest" -import { tmpdir } from "os" import * as path from "path" import { executeFinally, all } from "./util/promise" import { Promise as BluebirdPromise } from "bluebird" import { randomBytes } from "crypto" import { homedir } from "os" +import { TmpDir } from "./util/tmp" //noinspection JSUnusedLocalSymbols const __awaiter = require("./util/awaiter") @@ -19,23 +19,13 @@ export interface CodeSigningInfo { keychainName?: string | null } -export function generateKeychainName(): string { - return path.join(tmpdir(), getTempName("csc") + ".keychain") -} - -export function downloadCertificate(urlOrBase64: string): BluebirdPromise { - const tempFile = path.join(tmpdir(), `${getTempName()}.p12`) - if (urlOrBase64.startsWith("https://")) { - return download(urlOrBase64, tempFile) - .thenReturn(tempFile) - } - else if (urlOrBase64.startsWith("file://")) { +export function downloadCertificate(urlOrBase64: string, tmpDir: TmpDir): BluebirdPromise { + if (urlOrBase64.startsWith("file://")) { return BluebirdPromise.resolve(urlOrBase64.substring("file://".length)) } - else { - return outputFile(tempFile, new Buffer(urlOrBase64, "base64")) - .thenReturn(tempFile) - } + + return tmpDir.getTempFile(".p12") + .then(tempFile => (urlOrBase64.startsWith("https://") ? download(urlOrBase64, tempFile) : outputFile(tempFile, new Buffer(urlOrBase64, "base64"))).thenReturn(tempFile)) } let bundledCertKeychainAdded: Promise | null = null @@ -66,12 +56,14 @@ async function createCustomCertKeychain() { } } -export async function createKeychain(keychainName: string, cscLink: string, cscKeyPassword: string, cscILink?: string | null, cscIKeyPassword?: string | null): Promise { +export async function createKeychain(tmpDir: TmpDir, cscLink: string, cscKeyPassword: string, cscILink?: string | null, cscIKeyPassword?: string | null): Promise { if (bundledCertKeychainAdded == null) { bundledCertKeychainAdded = createCustomCertKeychain() } await bundledCertKeychainAdded + const keychainName = await tmpDir.getTempFile(".keychain") + const certLinks = [cscLink] if (cscILink != null) { certLinks.push(cscILink) @@ -80,7 +72,7 @@ export async function createKeychain(keychainName: string, cscLink: string, cscK const certPaths = new Array(certLinks.length) const keychainPassword = randomBytes(8).toString("hex") return await executeFinally(BluebirdPromise.all([ - BluebirdPromise.map(certLinks, (link, i) => downloadCertificate(link).then(it => certPaths[i] = it)), + BluebirdPromise.map(certLinks, (link, i) => downloadCertificate(link, tmpDir).then(it => certPaths[i] = it)), BluebirdPromise.mapSeries([ ["create-keychain", "-p", keychainPassword, keychainName], ["unlock-keychain", "-p", keychainPassword, keychainName], @@ -88,13 +80,7 @@ export async function createKeychain(keychainName: string, cscLink: string, cscK ], it => exec("security", it)) ]) .then(() => importCerts(keychainName, certPaths, >[cscKeyPassword, cscIKeyPassword].filter(it => it != null))), - errorOccurred => { - const tasks = certPaths.map((it, index) => certLinks[index].startsWith("https://") ? deleteFile(it, true) : BluebirdPromise.resolve()) - if (errorOccurred) { - tasks.push(deleteKeychain(keychainName)) - } - return all(tasks) - }) + () => all(certPaths.map((it, index) => certLinks[index].startsWith("https://") ? deleteFile(it, true) : BluebirdPromise.resolve()))) } async function importCerts(keychainName: string, paths: Array, keyPasswords: Array): Promise { @@ -115,20 +101,6 @@ export function sign(path: string, name: string, keychain: string): BluebirdProm return exec("codesign", args) } -export function deleteKeychain(keychainName: string, ignoreNotFound: boolean = true): BluebirdPromise { - const result = exec("security", ["delete-keychain", keychainName]) - if (ignoreNotFound) { - return result.catch(error => { - if (!error.message.includes("The specified keychain could not be found.")) { - throw error - } - }) - } - else { - return result - } -} - export let findIdentityRawResult: Promise> | null = null async function getValidIdentities(keychain?: string | null): Promise> { diff --git a/src/linuxPackager.ts b/src/linuxPackager.ts index 1d8bc4ec6d5..0c29b7ef03a 100755 --- a/src/linuxPackager.ts +++ b/src/linuxPackager.ts @@ -36,7 +36,7 @@ export class LinuxPackager extends PlatformPackager { let helper: LinuxTargetHelper | null const getHelper = () => { if (helper == null) { - helper = new LinuxTargetHelper(this, cleanupTasks) + helper = new LinuxTargetHelper(this) } return helper } diff --git a/src/macPackager.ts b/src/macPackager.ts index 11710908fb0..1b07ef2fea0 100644 --- a/src/macPackager.ts +++ b/src/macPackager.ts @@ -3,7 +3,7 @@ import { Platform, MasBuildOptions, Arch, MacOptions } from "./metadata" import * as path from "path" import { Promise as BluebirdPromise } from "bluebird" import { log, warn, task } from "./util/log" -import { createKeychain, deleteKeychain, CodeSigningInfo, generateKeychainName, findIdentity } from "./codeSign" +import { createKeychain, CodeSigningInfo, findIdentity } from "./codeSign" import { deepAssign } from "./util/deepAssign" import { signAsync, flatAsync, BaseSignOptions, SignOptions, FlatOptions } from "electron-osx-sign" import { DmgTarget } from "./targets/dmg" @@ -16,16 +16,14 @@ const __awaiter = require("./util/awaiter") export default class MacPackager extends PlatformPackager { codeSigningInfo: Promise - constructor(info: BuildInfo, cleanupTasks: Array<() => Promise>) { + constructor(info: BuildInfo) { super(info) if (this.options.cscLink == null) { this.codeSigningInfo = BluebirdPromise.resolve({}) } else { - const keychainName = generateKeychainName() - cleanupTasks.push(() => deleteKeychain(keychainName)) - this.codeSigningInfo = createKeychain(keychainName, this.options.cscLink, this.getCscPassword(), this.options.cscInstallerLink, this.options.cscInstallerKeyPassword) + this.codeSigningInfo = createKeychain(info.tempDirManager, this.options.cscLink!, this.getCscPassword(), this.options.cscInstallerLink, this.options.cscInstallerKeyPassword) } } diff --git a/src/packager.ts b/src/packager.ts index 3f65da5ce33..15b8be863ad 100644 --- a/src/packager.ts +++ b/src/packager.ts @@ -18,6 +18,7 @@ import { AppInfo } from "./appInfo" import MacPackager from "./macPackager" import { createTargets } from "./targets/targetFactory" import { readPackageJson } from "./util/readPackageJson" +import { TmpDir } from "./util/tmp" //noinspection JSUnusedLocalSymbols const __awaiter = require("./util/awaiter") @@ -41,6 +42,8 @@ export class Packager implements BuildInfo { appInfo: AppInfo + readonly tempDirManager = new TmpDir() + //noinspection JSUnusedGlobalSymbols constructor(public options: PackagerOptions) { this.projectDir = options.projectDir == null ? process.cwd() : path.resolve(options.projectDir) @@ -91,7 +94,7 @@ export class Packager implements BuildInfo { this.appInfo = new AppInfo(this.metadata, this.devMetadata) const cleanupTasks: Array<() => Promise> = [] - return executeFinally(this.doBuild(cleanupTasks), () => all(cleanupTasks.map(it => it()))) + return executeFinally(this.doBuild(cleanupTasks), () => all(cleanupTasks.map(it => it()).concat(this.tempDirManager.cleanup()))) } private async doBuild(cleanupTasks: Array<() => Promise>): Promise>> { @@ -144,13 +147,13 @@ export class Packager implements BuildInfo { case Platform.MAC: { const helperClass: typeof MacPackager = require("./macPackager").default - return new helperClass(this, cleanupTasks) + return new helperClass(this) } case Platform.WINDOWS: { const helperClass: typeof WinPackager = require("./winPackager").WinPackager - return new helperClass(this, cleanupTasks) + return new helperClass(this) } case Platform.LINUX: diff --git a/src/platformPackager.ts b/src/platformPackager.ts index 819a7af4fbb..5edb69688f1 100644 --- a/src/platformPackager.ts +++ b/src/platformPackager.ts @@ -2,7 +2,7 @@ import { AppMetadata, DevMetadata, Platform, PlatformSpecificBuildOptions, Arch import EventEmitter = NodeJS.EventEmitter import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" -import { readdir, remove, realpath } from "fs-extra-p" +import { readdir, remove } from "fs-extra-p" import { statOrNull, use, unlinkIfExists, isEmptyOrSpaces } from "./util/util" import { Packager } from "./packager" import { AsarOptions } from "asar-electron-builder" @@ -13,6 +13,7 @@ import { warn, log, task } from "./util/log" import { AppInfo } from "./appInfo" import { createFilter, copyFiltered, hasMagic, devDependencies } from "./util/filter" import { ElectronPackagerOptions, pack } from "./packager/dirPackager" +import { TmpDir } from "./util/tmp" //noinspection JSUnusedLocalSymbols const __awaiter = require("./util/awaiter") @@ -65,6 +66,8 @@ export interface BuildInfo { // computed final effective appId appInfo: AppInfo + + readonly tempDirManager: TmpDir } export class Target { @@ -165,18 +168,10 @@ export abstract class PlatformPackager const extraFilePatterns = this.getExtraFilePatterns(false, arch, platformSpecificBuildOptions) const p = pack(options, appOutDir, platformName, Arch[arch], this.info.electronVersion, async() => { - const ignoreFiles = new Set([path.relative(this.info.appDir, outDir), path.relative(this.info.appDir, this.buildResourcesDir)]) + const ignoreFiles = new Set([path.resolve(this.info.appDir, outDir), path.resolve(this.info.appDir, this.buildResourcesDir)]) if (!this.info.isTwoPackageJsonProjectLayoutUsed) { const result = await devDependencies(this.info.appDir) - // npm returns real path, so, we should use relative path to avoid any mismatch - const realAppDirPath = await realpath(this.info.appDir) for (let it of result) { - if (it.startsWith(realAppDirPath)) { - it = it.substring(realAppDirPath.length + 1) - } - else if (it.startsWith(this.info.appDir)) { - it = it.substring(this.info.appDir.length + 1) - } ignoreFiles.add(it) } } @@ -418,6 +413,10 @@ export abstract class PlatformPackager return null } } + + async getTempFile(suffix: string): Promise { + return this.info.tempDirManager.getTempFile(suffix) + } } export function getArchSuffix(arch: Arch): string { diff --git a/src/targets/LinuxTargetHelper.ts b/src/targets/LinuxTargetHelper.ts index ff7f3ab2944..b452f936aa6 100644 --- a/src/targets/LinuxTargetHelper.ts +++ b/src/targets/LinuxTargetHelper.ts @@ -1,7 +1,6 @@ -import { remove, emptyDir, readdir, outputFile } from "fs-extra-p" +import { readdir, outputFile, ensureDir } from "fs-extra-p" import * as path from "path" -import { tmpdir } from "os" -import { getTempName, exec, debug } from "../util/util" +import { exec, debug } from "../util/util" import { PlatformPackager } from "../platformPackager" import { Promise as BluebirdPromise } from "bluebird" import { LinuxBuildOptions } from "../metadata" @@ -13,15 +12,10 @@ export const installPrefix = "/opt" export class LinuxTargetHelper { readonly icons: Promise>> - readonly tempDirPromise: Promise maxIconPath: string | null = null - constructor(private packager: PlatformPackager, cleanupTasks: Array<() => Promise>) { - const tempDir = path.join(tmpdir(), getTempName("electron-builder-linux")) - this.tempDirPromise = emptyDir(tempDir).thenReturn(tempDir) - cleanupTasks.push(() => remove(tempDir)) - + constructor(private packager: PlatformPackager) { this.icons = this.computeDesktopIcons() } @@ -32,7 +26,7 @@ export class LinuxTargetHelper { return this.iconsFromDir(path.join(this.packager.buildResourcesDir, "icons")) } else { - return this.createFromIcns(await this.tempDirPromise) + return this.createFromIcns(await this.packager.getTempFile("electron-builder-linux").then(it => ensureDir(it).thenReturn(it))) } } @@ -81,7 +75,7 @@ export class LinuxTargetHelper { } const productFilename = appInfo.productFilename - const tempFile = path.join(await this.tempDirPromise, `${productFilename}.desktop`) + const tempFile = await this.packager.getTempFile(`${productFilename}.desktop`) await outputFile(tempFile, this.packager.platformSpecificBuildOptions.desktop || `[Desktop Entry] Name=${appInfo.productName} Comment=${this.packager.platformSpecificBuildOptions.description || appInfo.description} diff --git a/src/targets/fpm.ts b/src/targets/fpm.ts index d057ca3ada2..7b39ee21931 100644 --- a/src/targets/fpm.ts +++ b/src/targets/fpm.ts @@ -7,6 +7,7 @@ import { readFile, outputFile } from "fs-extra-p" import { Promise as BluebirdPromise } from "bluebird" import { LinuxTargetHelper, installPrefix } from "./LinuxTargetHelper" import * as errorMessages from "../errorMessages" +import { TmpDir } from "../util/tmp" const template = require("lodash.template") @@ -26,12 +27,11 @@ export default class FpmTarget extends TargetEx { constructor(name: string, private packager: PlatformPackager, private helper: LinuxTargetHelper, private outDir: string) { super(name) - this.scriptFiles = this.createScripts(helper.tempDirPromise) + this.scriptFiles = this.createScripts() this.desktopEntry = helper.computeDesktopEntry() } - private async createScripts(tempDirPromise: Promise): Promise> { - const tempDir = await tempDirPromise + private async createScripts(): Promise> { const defaultTemplatesDir = path.join(__dirname, "..", "..", "templates", "linux") const packager = this.packager @@ -47,8 +47,8 @@ export default class FpmTarget extends TargetEx { return path.resolve(packager.projectDir, value) } - const afterInstallFilePath = writeConfigFile(tempDir, getResource(packager.platformSpecificBuildOptions.afterInstall, "after-install.tpl"), templateOptions) - const afterRemoveFilePath = writeConfigFile(tempDir, getResource(packager.platformSpecificBuildOptions.afterRemove, "after-remove.tpl"), templateOptions) + const afterInstallFilePath = writeConfigFile(this.packager.info.tempDirManager, getResource(packager.platformSpecificBuildOptions.afterInstall, "after-install.tpl"), templateOptions) + const afterRemoveFilePath = writeConfigFile(this.packager.info.tempDirManager, getResource(packager.platformSpecificBuildOptions.afterRemove, "after-remove.tpl"), templateOptions) return await BluebirdPromise.all([afterInstallFilePath, afterRemoveFilePath]) } @@ -145,14 +145,14 @@ export default class FpmTarget extends TargetEx { } } -async function writeConfigFile(tempDir: string, templatePath: string, options: any): Promise { +async function writeConfigFile(tmpDir: TmpDir, templatePath: string, options: any): Promise { const config = template(await readFile(templatePath, "utf8"), { // set interpolate explicitly to avoid troubles with templating of installer.nsi.tpl interpolate: /<%=([\s\S]+?)%>/g })(options) - const outputPath = path.join(tempDir, path.basename(templatePath, ".tpl")) + const outputPath = await tmpDir.getTempFile(path.basename(templatePath, ".tpl")) await outputFile(outputPath, config) return outputPath } \ No newline at end of file diff --git a/src/targets/nsis.ts b/src/targets/nsis.ts index 33b067d5b11..c6abfd75ab0 100644 --- a/src/targets/nsis.ts +++ b/src/targets/nsis.ts @@ -1,6 +1,6 @@ import { WinPackager } from "../winPackager" import { Arch, NsisOptions } from "../metadata" -import { exec, debug, doSpawn, handleProcess, use, getTempName } from "../util/util" +import { exec, debug, doSpawn, handleProcess, use } from "../util/util" import * as path from "path" import { Promise as BluebirdPromise } from "bluebird" import { getBinFromBintray } from "../util/binDownload" @@ -8,9 +8,8 @@ import { v5 as uuid5 } from "uuid-1345" import { Target } from "../platformPackager" import { archiveApp } from "./archive" import { subTask, task, log } from "../util/log" -import { unlink, readFile, remove } from "fs-extra-p" +import { unlink, readFile } from "fs-extra-p" import semver = require("semver") -import { tmpdir } from "os" //noinspection JSUnusedLocalSymbols const __awaiter = require("../util/awaiter") @@ -31,7 +30,7 @@ export default class NsisTarget extends Target { private readonly nsisTemplatesDir = path.join(__dirname, "..", "..", "templates", "nsis") - constructor(private packager: WinPackager, private outDir: string, private cleanupTasks: Array<() => Promise>) { + constructor(private packager: WinPackager, private outDir: string) { super("nsis") this.options = packager.info.devMetadata.build.nsis || Object.create(null) @@ -156,13 +155,11 @@ export default class NsisTarget extends Target { const script = await readFile(customScriptPath || path.join(this.nsisTemplatesDir, "installer.nsi"), "utf8") if (customScriptPath == null) { - const uninstallerPath = path.join(tmpdir(), `${getTempName("electron-builder")}.exe`) - this.cleanupTasks.push(() => remove(uninstallerPath)) - + const uninstallerPath = await packager.getTempFile("uninstaller.exe") + const isWin = process.platform === "win32" defines.BUILD_UNINSTALLER = null - defines.UNINSTALLER_OUT_FILE = path.win32.join("Z:", uninstallerPath) + defines.UNINSTALLER_OUT_FILE = isWin ? uninstallerPath : path.win32.join("Z:", uninstallerPath) await subTask(`Executing makensis — uninstaller`, this.executeMakensis(defines, commands, false, script)) - const isWin = process.platform === "win32" await exec(isWin ? installerPath : "wine", isWin ? [] : [installerPath]) await packager.sign(uninstallerPath) diff --git a/src/targets/squirrelPack.ts b/src/targets/squirrelPack.ts index ca800349735..377e98c2b69 100644 --- a/src/targets/squirrelPack.ts +++ b/src/targets/squirrelPack.ts @@ -49,8 +49,8 @@ export interface SquirrelOptions { copyright?: string } -export async function buildInstaller(options: SquirrelOptions, outputDirectory: string, stageDir: string, setupExe: string, packager: WinPackager, appOutDir: string) { - const appUpdate = path.join(stageDir, "Update.exe") +export async function buildInstaller(options: SquirrelOptions, outputDirectory: string, setupExe: string, packager: WinPackager, appOutDir: string) { + const appUpdate = await packager.getTempFile("Update.exe") const promises = [ copy(path.join(options.vendorPath, "Update.exe"), appUpdate) .then(() => packager.sign(appUpdate)), @@ -62,7 +62,7 @@ export async function buildInstaller(options: SquirrelOptions, outputDirectory: } await BluebirdPromise.all(promises) - const embeddedArchiveFile = path.join(stageDir, "setup.zip") + const embeddedArchiveFile = await packager.getTempFile("setup.zip") const embeddedArchive = archiver("zip", {zlib: {level: options.packageCompressionLevel == null ? 6 : options.packageCompressionLevel}}) const embeddedArchiveOut = createWriteStream(embeddedArchiveFile) const embeddedArchivePromise = new BluebirdPromise(function (resolve, reject) { diff --git a/src/targets/squirrelWindows.ts b/src/targets/squirrelWindows.ts index 3e2f502579f..ce2a24f05f8 100644 --- a/src/targets/squirrelWindows.ts +++ b/src/targets/squirrelWindows.ts @@ -5,9 +5,6 @@ import * as path from "path" import { warn, log } from "../util/log" import { getRepositoryInfo } from "../repositoryInfo" import { getBinFromBintray } from "../util/binDownload" -import { tmpdir } from "os" -import { getTempName } from "../util/util" -import { emptyDir, remove } from "fs-extra-p" import { buildInstaller, convertVersion, SquirrelOptions } from "./squirrelPack" //noinspection JSUnusedLocalSymbols @@ -18,7 +15,7 @@ const SW_VERSION = "1.4.4" const SW_SHA2 = "98e1d81c80d7afc1bcfb37f3b224dc4f761088506b9c28ccd72d1cf8752853ba" export default class SquirrelWindowsTarget extends Target { - constructor(private packager: WinPackager, private cleanupTasks: Array<() => Promise>) { + constructor(private packager: WinPackager) { super("squirrel") } @@ -36,10 +33,7 @@ export default class SquirrelWindowsTarget extends Target { const distOptions = await this.computeEffectiveDistOptions() - const stageDir = path.join(tmpdir(), getTempName("squirrel-windows-builder")) - await emptyDir(stageDir) - this.cleanupTasks.push(() => remove(stageDir)) - await buildInstaller(distOptions, installerOutDir, stageDir, setupFileName, this.packager, appOutDir) + await buildInstaller(distOptions, installerOutDir, setupFileName, this.packager, appOutDir) this.packager.dispatchArtifactCreated(path.join(installerOutDir, setupFileName), `${appInfo.name}-Setup-${version}${archSuffix}.exe`) diff --git a/src/util/filter.ts b/src/util/filter.ts index 62370828253..ce8e75ed39c 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -40,13 +40,13 @@ export function createFilter(src: string, patterns: Array, ignoreFile return false } - let relative = it.substring(src.length + 1) - // yes, check before path sep normalization - if (ignoreFiles != null && ignoreFiles.has(relative)) { + if (ignoreFiles != null && ignoreFiles.has(it)) { return false } + let relative = it.substring(src.length + 1) + if (path.sep === "\\") { relative = relative.replace(/\\/g, "/") } diff --git a/src/util/tmp.ts b/src/util/tmp.ts new file mode 100644 index 00000000000..ca2ed2aafbe --- /dev/null +++ b/src/util/tmp.ts @@ -0,0 +1,67 @@ +import { tmpdir } from "os" +import { remove, mkdirs, removeSync } from "fs-extra-p" +import * as path from "path" +import { getTempName, use } from "./util" +import { Promise as BluebirdPromise } from "bluebird" +import { warn } from "./log" + +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") + +const mkdtemp: any | null = use(require("fs").mkdtemp, it => BluebirdPromise.promisify(it)) + +export class TmpDir { + private tmpFileCounter = 0 + private tempDirectoryPromise: BluebirdPromise + + private dir: string | null + + getTempFile(suffix: string): BluebirdPromise { + if (this.tempDirectoryPromise == null) { + let promise: BluebirdPromise + if (mkdtemp == null) { + const dir = path.join(tmpdir(), getTempName("electron-builder")) + promise = mkdirs(dir, {mode: 448}).thenReturn(dir) + } + else { + promise = mkdtemp(`${path.join(tmpdir(), "electron-builder")}-`) + } + + this.tempDirectoryPromise = promise + .then(dir => { + this.dir = dir + process.on("SIGINT", () => { + if (this.dir == null) { + return + } + + this.dir = null + try { + removeSync(dir) + } + catch (e) { + warn(`Cannot delete temporary dir "${dir}": ${(e.stack || e).toString()}`) + } + }) + return dir + }) + } + + return this.tempDirectoryPromise + .then(it => path.join(it, `${(this.tmpFileCounter++).toString(16)}${suffix.startsWith(".") ? suffix : `-${suffix}`}`)) + } + + cleanup(): Promise { + if (this.dir == null) { + return BluebirdPromise.resolve() + } + + return remove(this.dir) + .then(() => { + this.dir = null + }) + .catch(e => { + warn(`Cannot delete temporary dir "${this.dir}": ${(e.stack || e).toString()}`) + }) + } +} diff --git a/src/util/util.ts b/src/util/util.ts index 43fa999aa70..a34792fe807 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -256,10 +256,10 @@ export function debug7zArgs(command: "a" | "x"): Array { let tmpDirCounter = 0 // add date to avoid use stale temp dir -const tempDirPrefix = `${process.pid.toString(36)}-${Date.now().toString(36)}` +const tempDirPrefix = `${process.pid.toString(16)}-${Date.now().toString(16)}` export function getTempName(prefix?: string | n): string { - return `${prefix == null ? "" : `${prefix}-`}${tempDirPrefix}-${(tmpDirCounter++).toString(36)}` + return `${prefix == null ? "" : `${prefix}-`}${tempDirPrefix}-${(tmpDirCounter++).toString(16)}` } export function isEmptyOrSpaces(s: string | n) { diff --git a/src/winPackager.ts b/src/winPackager.ts index 5456324cd45..febe17bf0f1 100644 --- a/src/winPackager.ts +++ b/src/winPackager.ts @@ -5,7 +5,7 @@ import { Platform, WinBuildOptions, Arch } from "./metadata" import * as path from "path" import { log, task } from "./util/log" import { exec, use } from "./util/util" -import { deleteFile, open, close, read } from "fs-extra-p" +import { open, close, read } from "fs-extra-p" import { sign, SignOptions, getSignVendorPath } from "./windowsCodeSign" import SquirrelWindowsTarget from "./targets/squirrelWindows" import NsisTarget from "./targets/nsis" @@ -27,7 +27,7 @@ export class WinPackager extends PlatformPackager { private readonly iconPath: Promise - constructor(info: BuildInfo, cleanupTasks: Array<() => Promise>) { + constructor(info: BuildInfo) { super(info) const subjectName = this.platformSpecificBuildOptions.certificateSubjectName @@ -42,11 +42,8 @@ export class WinPackager extends PlatformPackager { }) } else if (cscLink != null) { - this.cscInfo = downloadCertificate(cscLink) + this.cscInfo = downloadCertificate(cscLink, info.tempDirManager) .then(path => { - if (cscLink.startsWith("https://")) { - cleanupTasks.push(() => deleteFile(path, true)) - } return { file: path, password: this.getCscPassword(), @@ -75,13 +72,13 @@ export class WinPackager extends PlatformPackager { if (name === DEFAULT_TARGET || name === "squirrel") { mapper("squirrel", () => { const targetClass: typeof SquirrelWindowsTarget = require("./targets/squirrelWindows").default - return new targetClass(this, cleanupTasks) + return new targetClass(this) }) } else if (name === "nsis") { mapper(name, outDir => { const targetClass: typeof NsisTarget = require("./targets/nsis").default - return new targetClass(this, outDir, cleanupTasks) + return new targetClass(this, outDir) }) } else { diff --git a/templates/nsis/multiUser.nsh b/templates/nsis/multiUser.nsh index 551a27f8b07..6d0c6559ee8 100644 --- a/templates/nsis/multiUser.nsh +++ b/templates/nsis/multiUser.nsh @@ -49,16 +49,13 @@ Var installMode !ifdef INSTALL_MODE_PER_ALL_USERS_REQUIRED Var perMachineInstallationFolder - # Sets install mode to "per-machine" (all users). !macro setInstallModePerAllUsers # Install mode initialization - per-machine StrCpy $installMode AllUsers SetShellVarContext all - !ifndef BUILD_UNINSTALLER - StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT_FILENAME}" - !endif + StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT_FILENAME}" # checks registry for previous installation path (both for upgrading, reinstall, or uninstall) ReadRegStr $perMachineInstallationFolder HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation diff --git a/test/fixtures/app-executable-deps/package.json b/test/fixtures/app-executable-deps/package.json index ae837904c92..cf386e17acf 100644 --- a/test/fixtures/app-executable-deps/package.json +++ b/test/fixtures/app-executable-deps/package.json @@ -1,9 +1,6 @@ { - "devDependencies": { - "electron-builder": "next", - "electron": "^1.3.2" - }, "build": { + "electronVersion": "1.3.2", "category": "public.app-category.business" } } diff --git a/test/src/BuildTest.ts b/test/src/BuildTest.ts index 24da7740502..1844ee1aa1f 100755 --- a/test/src/BuildTest.ts +++ b/test/src/BuildTest.ts @@ -1,5 +1,8 @@ import test from "./helpers/avaEx" -import { assertPack, modifyPackageJson, platform, getPossiblePlatforms, currentPlatform } from "./helpers/packTester" +import { + assertPack, modifyPackageJson, platform, getPossiblePlatforms, currentPlatform, + app, appThrows, packageJson +} from "./helpers/packTester" import { move, outputJson, readJson } from "fs-extra-p" import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" @@ -8,6 +11,7 @@ import { archFromString, BuildOptions, Platform, Arch, PackagerOptions, DIR_TARG import { normalizeOptions } from "out/builder" import { createYargs } from "out/cliOptions" import { extractFile } from "asar-electron-builder" +import { ELECTRON_VERSION } from "./helpers/config" //noinspection JSUnusedLocalSymbols const __awaiter = require("out/util/awaiter") @@ -61,8 +65,8 @@ test("cli", () => { }})) }) -test("custom buildResources dir", () => assertPack("test-app-one", allPlatforms(), { - tempDirCreated: projectDir => BluebirdPromise.all([ +test("custom buildResources dir", app(allPlatforms(), { + projectDirCreated: projectDir => BluebirdPromise.all([ modifyPackageJson(projectDir, data => { data.directories = { buildResources: "custom" @@ -72,9 +76,9 @@ test("custom buildResources dir", () => assertPack("test-app-one", allPlatforms( ]) })) -test("custom output dir", () => assertPack("test-app-one", allPlatforms(false), { - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { - data.directories = { +test("custom output dir", app(allPlatforms(false), { + projectDirCreated: packageJson(it => { + it.directories = { output: "customDist", // https://github.com/electron-userland/electron-builder/issues/601 app: ".", @@ -86,20 +90,14 @@ test("custom output dir", () => assertPack("test-app-one", allPlatforms(false), })) test("build in the app package.json", t => t.throws(assertPack("test-app", allPlatforms(), { - tempDirCreated: it => modifyPackageJson(it, data => { + projectDirCreated: it => modifyPackageJson(it, data => { data.build = { "iconUrl": "bar", } }, true) }), /'build' in the application package\.json .+/)) -test("name in the build", t => t.throws(assertPack("test-app-one", currentPlatform(), { - tempDirCreated: it => modifyPackageJson(it, data => { - data.build = { - "name": "Cool App", - } - }) -}), /'name' in the 'build' is forbidden/)) +test("name in the build", appThrows(/'name' in the 'build' is forbidden/, currentPlatform(), {projectDirCreated: packageJson(it => it.build = {"name": "Cool App"})})) // this test also test appMetadata, so, we must use test-app here test("empty description", t => t.throws(assertPack("test-app", { @@ -110,13 +108,13 @@ test("empty description", t => t.throws(assertPack("test-app", { }), /Please specify 'description'/)) test("invalid main in the app package.json", t => t.throws(assertPack("test-app", allPlatforms(false), { - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { + projectDirCreated: projectDir => modifyPackageJson(projectDir, data => { data.main = "main.js" }, true) }), /Application entry file "main.js" in the /)) test("invalid main in the app package.json (no asar)", t => t.throws(assertPack("test-app", allPlatforms(false), { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { return BluebirdPromise.all([ modifyPackageJson(projectDir, data => { data.main = "main.js" @@ -129,7 +127,7 @@ test("invalid main in the app package.json (no asar)", t => t.throws(assertPack( }), `Application entry file "main.js" does not exist. Seems like a wrong configuration.`)) test("main in the app package.json (no asar)", () => assertPack("test-app", allPlatforms(false), { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { return BluebirdPromise.all([ move(path.join(projectDir, "app", "index.js"), path.join(projectDir, "app", "main.js")), modifyPackageJson(projectDir, data => { @@ -143,19 +141,17 @@ test("main in the app package.json (no asar)", () => assertPack("test-app", allP })) test("relative index", () => assertPack("test-app", allPlatforms(false), { - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { + projectDirCreated: projectDir => modifyPackageJson(projectDir, data => { data.main = "./index.js" }, true) })) -const electronVersion = "1.3.2" - -test.ifDevOrLinuxCi("electron version from electron-prebuilt dependency", () => assertPack("test-app-one", { +test.ifDevOrLinuxCi("electron version from electron-prebuilt dependency", app({ targets: Platform.LINUX.createTarget(DIR_TARGET), }, { - tempDirCreated: projectDir => BluebirdPromise.all([ + projectDirCreated: projectDir => BluebirdPromise.all([ outputJson(path.join(projectDir, "node_modules", "electron-prebuilt", "package.json"), { - version: electronVersion + version: ELECTRON_VERSION }), modifyPackageJson(projectDir, data => { delete data.build.electronVersion @@ -164,12 +160,12 @@ test.ifDevOrLinuxCi("electron version from electron-prebuilt dependency", () => ]) })) -test.ifDevOrLinuxCi("electron version from electron dependency", () => assertPack("test-app-one", { +test.ifDevOrLinuxCi("electron version from electron dependency", app({ targets: Platform.LINUX.createTarget(DIR_TARGET), }, { - tempDirCreated: projectDir => BluebirdPromise.all([ + projectDirCreated: projectDir => BluebirdPromise.all([ outputJson(path.join(projectDir, "node_modules", "electron", "package.json"), { - version: electronVersion + version: ELECTRON_VERSION }), modifyPackageJson(projectDir, data => { delete data.build.electronVersion @@ -178,17 +174,17 @@ test.ifDevOrLinuxCi("electron version from electron dependency", () => assertPac ]) })) -test.ifDevOrLinuxCi("electron version from build", () => assertPack("test-app-one", { +test.ifDevOrLinuxCi("electron version from build", app({ targets: Platform.LINUX.createTarget(DIR_TARGET), }, { - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { + projectDirCreated: projectDir => modifyPackageJson(projectDir, data => { data.devDependencies = {} - data.build.electronVersion = electronVersion + data.build.electronVersion = ELECTRON_VERSION }) })) test("www as default dir", () => assertPack("test-app", currentPlatform(), { - tempDirCreated: projectDir => move(path.join(projectDir, "app"), path.join(projectDir, "www")) + projectDirCreated: projectDir => move(path.join(projectDir, "app"), path.join(projectDir, "www")) })) test("afterPack", t => { @@ -223,7 +219,7 @@ test.ifDevOrLinuxCi("extra metadata", () => { targets: Platform.LINUX.createTarget(DIR_TARGET), extraMetadata: extraMetadata, }, { - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { + projectDirCreated: projectDir => modifyPackageJson(projectDir, data => { data.foo = { bar: 42, existingProp: 22, @@ -250,8 +246,8 @@ test.ifDevOrLinuxCi("extra metadata - two", () => { targets: Platform.LINUX.createTarget(DIR_TARGET), extraMetadata: extraMetadata, }, { - packed: async (projectDir) => { - const out = path.join(projectDir, "dist", "linux") + packed: async (projectDir, outDir) => { + const out = path.join(outDir, "linux") await assertThat(path.join(out, "NewName")).isFile() } }) @@ -269,8 +265,8 @@ test.ifOsx("extra metadata - override icon", t => t.throws((() => { targets: Platform.OSX.createTarget(DIR_TARGET), extraMetadata: extraMetadata, }, { - packed: async (projectDir) => { - const out = path.join(projectDir, "dist", "linux") + packed: async (projectDir, outDir) => { + const out = path.join(outDir, "linux") await assertThat(path.join(out, "NewName")).isFile() } }) @@ -280,8 +276,9 @@ test.ifOsx("app-executable-deps", () => { return assertPack("app-executable-deps", { targets: Platform.current().createTarget(DIR_TARGET), }, { - packed: async (projectDir) => { - const data = await readJson(path.join(projectDir, "dist/mac/app-executable-deps.app/Contents/Resources/app.asar.unpacked", "node_modules", "node-notifier", "package.json")) + useTempDir: false, + packed: async (projectDir, outDir) => { + const data = await readJson(path.join(outDir, "mac/app-executable-deps.app/Contents/Resources/app.asar.unpacked", "node_modules", "node-notifier", "package.json")) for (let name of Object.getOwnPropertyNames(data)) { if (name[0] === "_") { throw new Error("Property name starts with _") @@ -296,14 +293,14 @@ test.ifDevOrLinuxCi("smart unpack", () => { targets: Platform.LINUX.createTarget(DIR_TARGET), }, { npmInstallBefore: true, - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { - data.dependencies = { + projectDirCreated: packageJson(it => { + it.dependencies = { "debug": "^2.2.0", "edge-cs": "^1.0.0" } }), - packed: projectDir => { - assertThat(JSON.parse(extractFile(path.join(projectDir, "dist", "linux", "resources", "app.asar"), "node_modules/debug/package.json").toString())).hasProperties({ + packed: (projectDir, outDir) => { + assertThat(JSON.parse(extractFile(path.join(outDir, "linux", "resources", "app.asar"), "node_modules/debug/package.json").toString())).hasProperties({ name: "debug" }) return BluebirdPromise.resolve() @@ -311,7 +308,7 @@ test.ifDevOrLinuxCi("smart unpack", () => { }) }) -test.ifWinCi("Build MacOS on Windows is not supported", t => t.throws(assertPack("test-app-one", platform(Platform.MAC)), /Build for MacOS is supported only on MacOS.+/)) +test.ifWinCi("Build MacOS on Windows is not supported", appThrows(/Build for MacOS is supported only on MacOS.+/, platform(Platform.MAC))) function allPlatforms(dist: boolean = true): PackagerOptions { return { diff --git a/test/src/CodeSignTest.ts b/test/src/CodeSignTest.ts index 393a47e011e..846fff49443 100644 --- a/test/src/CodeSignTest.ts +++ b/test/src/CodeSignTest.ts @@ -1,31 +1,27 @@ -import { createKeychain, deleteKeychain, generateKeychainName } from "out/codeSign" +import { createKeychain } from "out/codeSign" import { assertThat } from "./helpers/fileAssert" import test from "./helpers/avaEx" import { CSC_LINK } from "./helpers/codeSignData" -import { executeFinally, all } from "out/util/promise" import { removePassword } from "out/util/util" +import { TmpDir } from "out/util/tmp" //noinspection JSUnusedLocalSymbols const __awaiter = require("out/util/awaiter") +const tmpDir = new TmpDir() + if (process.env.CSC_KEY_PASSWORD == null) { console.warn("Skip keychain-specific tests because CSC_KEY_PASSWORD is not defined") } else { - test.ifOsx("create keychain", async() => { - const keychainName = generateKeychainName() - await executeFinally(createKeychain(keychainName, CSC_LINK, process.env.CSC_KEY_PASSWORD) - .then(result => { - assertThat(result.keychainName).isNotEmpty() - }), () => all([deleteKeychain(keychainName)])) + test.ifOsx("create keychain", async () => { + const result = await createKeychain(tmpDir, CSC_LINK, process.env.CSC_KEY_PASSWORD) + assertThat(result.keychainName).isNotEmpty() }) - test.ifOsx("create keychain with installers", async() => { - const keychainName = generateKeychainName() - await executeFinally(createKeychain(keychainName, CSC_LINK, process.env.CSC_KEY_PASSWORD) - .then(result => { - assertThat(result.keychainName).isNotEmpty() - }), () => all([deleteKeychain(keychainName)])) + test.ifOsx("create keychain with installers", async () => { + const result = await createKeychain(tmpDir, CSC_LINK, process.env.CSC_KEY_PASSWORD) + assertThat(result.keychainName).isNotEmpty() }) } diff --git a/test/src/globTest.ts b/test/src/globTest.ts index 33420d2f6e1..a1393364d93 100644 --- a/test/src/globTest.ts +++ b/test/src/globTest.ts @@ -1,78 +1,72 @@ import test from "./helpers/avaEx" import { expectedWinContents } from "./helpers/expectedContents" import { outputFile } from "fs-extra-p" -import { assertPack, modifyPackageJson, outDirName, getPossiblePlatforms } from "./helpers/packTester" +import { assertPack, modifyPackageJson, getPossiblePlatforms, app } from "./helpers/packTester" import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" import { assertThat } from "./helpers/fileAssert" -import { Platform, DIR_TARGET } from "out" +import { Platform, DIR_TARGET } from "out" import pathSorter = require("path-sort") //noinspection JSUnusedLocalSymbols const __awaiter = require("out/util/awaiter") -test.ifDevOrLinuxCi("ignore build resources", () => { - return assertPack("test-app-one", { - targets: Platform.LINUX.createTarget(DIR_TARGET), - devMetadata: { - build: { - asar: false - } +test.ifDevOrLinuxCi("ignore build resources", app({ + targets: Platform.LINUX.createTarget(DIR_TARGET), + devMetadata: { + build: { + asar: false } - }, { - tempDirCreated: projectDir => { - return outputFile(path.join(projectDir, "one/build/foo.txt"), "data") - }, - packed: projectDir => { - return assertThat(path.join(projectDir, outDirName, "linux", "resources", "app", "one", "build", "foo.txt")).isFile() - }, - }) -}) + } +}, { + projectDirCreated: projectDir => { + return outputFile(path.join(projectDir, "one/build/foo.txt"), "data") + }, + packed: (projectDir, outDir) => { + return assertThat(path.join(outDir, "linux", "resources", "app", "one", "build", "foo.txt")).isFile() + }, +})) -test.ifDevOrLinuxCi("files", () => { - return assertPack("test-app-one", { - targets: Platform.LINUX.createTarget(DIR_TARGET), - devMetadata: { - build: { - asar: false, - files: ["**/*", "!ignoreMe${/*}"] - } +test.ifDevOrLinuxCi("files", app({ + targets: Platform.LINUX.createTarget(DIR_TARGET), + devMetadata: { + build: { + asar: false, + files: ["**/*", "!ignoreMe${/*}"] } - }, { - tempDirCreated: projectDir => { - return outputFile(path.join(projectDir, "ignoreMe", "foo"), "data") - }, - packed: projectDir => { - return assertThat(path.join(projectDir, outDirName, "linux", "resources", "app", "ignoreMe")).doesNotExist() - }, - }) -}) + } +}, { + projectDirCreated: projectDir => { + return outputFile(path.join(projectDir, "ignoreMe", "foo"), "data") + }, + packed: (projectDir, outDir) => { + return assertThat(path.join(outDir, "linux", "resources", "app", "ignoreMe")).doesNotExist() + }, +})) -test.ifDevOrLinuxCi("unpackDir one", () => { - return assertPack("test-app-one", { - targets: Platform.LINUX.createTarget(DIR_TARGET), - devMetadata: { - build: { - asar: { - unpackDir: "{assets,b2}" - }, - } +test.ifDevOrLinuxCi("unpackDir one", app({ + targets: Platform.LINUX.createTarget(DIR_TARGET), + devMetadata: { + build: { + asar: { + unpackDir: "{assets,b2}" + }, } - }, { - tempDirCreated: projectDir => { - return BluebirdPromise.all([ - outputFile(path.join(projectDir, "assets", "file"), "data"), - outputFile(path.join(projectDir, "b2", "file"), "data"), - ]) - }, - packed: projectDir => { - return BluebirdPromise.all([ - assertThat(path.join(projectDir, outDirName, "linux", "resources", "app.asar.unpacked", "assets")).isDirectory(), - assertThat(path.join(projectDir, outDirName, "linux", "resources", "app.asar.unpacked", "b2")).isDirectory(), - ]) - }, - }) -}) + } +}, { + projectDirCreated: projectDir => { + return BluebirdPromise.all([ + outputFile(path.join(projectDir, "assets", "file"), "data"), + outputFile(path.join(projectDir, "b2", "file"), "data"), + ]) + }, + packed: (projectDir, outDir) => { + return BluebirdPromise.all([ + assertThat(path.join(outDir, "linux", "resources", "app.asar.unpacked", "assets")).isDirectory(), + assertThat(path.join(outDir, "linux", "resources", "app.asar.unpacked", "b2")).isDirectory(), + ]) + }, +})) test.ifDevOrLinuxCi("unpackDir", () => { return assertPack("test-app", { @@ -85,16 +79,16 @@ test.ifDevOrLinuxCi("unpackDir", () => { } } }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { return BluebirdPromise.all([ outputFile(path.join(projectDir, "app", "assets", "file"), "data"), outputFile(path.join(projectDir, "app", "b2", "file"), "data"), ]) }, - packed: projectDir => { + packed: (projectDir, outDir) => { return BluebirdPromise.all([ - assertThat(path.join(projectDir, outDirName, "linux", "resources", "app.asar.unpacked", "assets")).isDirectory(), - assertThat(path.join(projectDir, outDirName, "linux", "resources", "app.asar.unpacked", "b2")).isDirectory(), + assertThat(path.join(outDir, "linux", "resources", "app.asar.unpacked", "assets")).isDirectory(), + assertThat(path.join(outDir, "linux", "resources", "app.asar.unpacked", "b2")).isDirectory(), ]) }, }) @@ -115,7 +109,7 @@ test.ifNotCiOsx("ignore node_modules known dev dep", () => { build: build } }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { return BluebirdPromise.all([ modifyPackageJson(projectDir, data => { data.devDependencies = Object.assign({ @@ -126,10 +120,10 @@ test.ifNotCiOsx("ignore node_modules known dev dep", () => { outputFile(path.join(projectDir, "ignoreMe"), ""), ]) }, - packed: projectDir => { + packed: (projectDir, outDir) => { return BluebirdPromise.all([ - assertThat(path.join(projectDir, outDirName, "linux", "resources", "app", "node_modules", "electron-osx-sign")).doesNotExist(), - assertThat(path.join(projectDir, outDirName, "linux", "resources", "app", "ignoreMe")).doesNotExist(), + assertThat(path.join(outDir, "linux", "resources", "app", "node_modules", "electron-osx-sign")).doesNotExist(), + assertThat(path.join(outDir, "linux", "resources", "app", "ignoreMe")).doesNotExist(), ]) }, }) @@ -141,7 +135,8 @@ test.ifDevOrLinuxCi("failed peer dep", () => { targets: Platform.LINUX.createTarget(DIR_TARGET), }, { npmInstallBefore: true, - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { + projectDirCreated: projectDir => modifyPackageJson(projectDir, data => { + //noinspection SpellCheckingInspection data.dependencies = { "rc-datepicker": "4.0.0", "react": "15.2.1", @@ -162,7 +157,7 @@ test("extraResources", async () => { // to check NuGet package targets: platform.createTarget(platform === Platform.WINDOWS ? null : DIR_TARGET), }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { return BluebirdPromise.all([ modifyPackageJson(projectDir, data => { data.build.extraResources = [ @@ -190,8 +185,8 @@ test("extraResources", async () => { outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"), ]) }, - packed: async (projectDir) => { - const base = path.join(projectDir, outDirName, platform.buildConfigurationKey) + packed: async (projectDir, outDir) => { + const base = path.join(outDir, platform.buildConfigurationKey) let resourcesDir = path.join(base, "resources") if (platform === Platform.MAC) { resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources") @@ -235,7 +230,7 @@ test("extraResources - one-package", async () => { }, }, }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { return BluebirdPromise.all([ modifyPackageJson(projectDir, data => { data.build.extraResources = [ @@ -263,8 +258,8 @@ test("extraResources - one-package", async () => { outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"), ]) }, - packed: async (projectDir) => { - const base = path.join(projectDir, outDirName, platform.buildConfigurationKey) + packed: async (projectDir, outDir) => { + const base = path.join(outDir, platform.buildConfigurationKey) let resourcesDir = path.join(base, "resources") if (platform === Platform.MAC) { resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources") diff --git a/test/src/helpers/config.ts b/test/src/helpers/config.ts new file mode 100644 index 00000000000..c7905d0a14d --- /dev/null +++ b/test/src/helpers/config.ts @@ -0,0 +1,5 @@ +import * as path from "path" +import { tmpdir } from "os" + +export const TEST_DIR = path.join(tmpdir(), `electron-builder-test-${process.pid.toString(16)}`) +export const ELECTRON_VERSION = "1.3.2" \ No newline at end of file diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts index 1e32bdd80ff..bfb2043a303 100755 --- a/test/src/helpers/packTester.ts +++ b/test/src/helpers/packTester.ts @@ -4,16 +4,18 @@ import * as path from "path" import { parse as parsePlist } from "plist" import { CSC_LINK } from "./codeSignData" import { expectedLinuxContents, expectedWinContents } from "./expectedContents" -import { Packager, PackagerOptions, Platform, ArtifactCreated, Arch, DIR_TARGET, DEFAULT_TARGET } from "out" -import { exec, getTempName } from "out/util/util" +import { Packager, PackagerOptions, Platform, ArtifactCreated, Arch, DIR_TARGET } from "out" +import { exec } from "out/util/util" import { log, warn } from "out/util/log" import { createTargets } from "out" -import { tmpdir } from "os" import { getArchSuffix, Target } from "out/platformPackager" import pathSorter = require("path-sort") import DecompressZip = require("decompress-zip") import { convertVersion } from "out/targets/squirrelPack" import { spawnNpmProduction } from "out/util/util" +import { TEST_DIR } from "./config" +import { deepAssign } from "out/util/deepAssign" +import { AssertContext } from "ava-tf" //noinspection JSUnusedLocalSymbols const __awaiter = require("out/util/awaiter") @@ -23,11 +25,11 @@ if (process.env.TRAVIS !== "true") { process.env.CIRCLE_BUILD_NUM = 42 } -export const outDirName = "dist" +const OUT_DIR_NAME = "dist" interface AssertPackOptions { - readonly tempDirCreated?: (projectDir: string) => Promise - readonly packed?: (projectDir: string) => Promise + readonly projectDirCreated?: (projectDir: string) => Promise + readonly packed?: (projectDir: string, outDir: string) => Promise readonly expectedContents?: Array readonly expectedArtifacts?: Array @@ -39,6 +41,12 @@ interface AssertPackOptions { readonly npmInstallBefore?: boolean } +let tmpDirCounter = 0 + +export function appThrows(error: RegExp, packagerOptions: PackagerOptions, checkOptions: AssertPackOptions = {}) { + return (t: AssertContext) => t.throws(assertPack("test-app-one", packagerOptions, checkOptions), error) +} + export function app(packagerOptions: PackagerOptions, checkOptions: AssertPackOptions = {}) { return () => assertPack("test-app-one", packagerOptions, checkOptions) } @@ -48,51 +56,66 @@ export async function assertPack(fixtureName: string, packagerOptions: PackagerO packagerOptions = signed(packagerOptions) } - const tempDirCreated = checkOptions.tempDirCreated - const useTempDir = fixtureName !== "app-executable-deps" && (tempDirCreated != null || packagerOptions.devMetadata != null || checkOptions.useTempDir || packagerOptions.targets.values().next().value.values().next().value[0] !== DEFAULT_TARGET) + const projectDirCreated = checkOptions.projectDirCreated + const useTempDir = checkOptions.useTempDir !== false && (checkOptions.useTempDir || projectDirCreated != null || packagerOptions.devMetadata != null || checkOptions.npmInstallBefore) let projectDir = path.join(__dirname, "..", "..", "fixtures", fixtureName) // const isDoNotUseTempDir = platform === "darwin" const customTmpDir = process.env.TEST_APP_TMP_DIR + let dirToDelete: string | null = null if (useTempDir) { // non-osx test uses the same dir as osx test, but we cannot share node_modules (because tests executed in parallel) - const dir = customTmpDir == null ? path.join(tmpdir(), "electron-builder-test", `${getTempName()}`) : path.resolve(customTmpDir) - if (customTmpDir != null) { + const dir = customTmpDir == null ? path.join(TEST_DIR, `${(tmpDirCounter++).toString(16)}`) : path.resolve(customTmpDir) + if (customTmpDir == null) { + dirToDelete = dir + } + else { log(`Custom temp dir used: ${customTmpDir}`) } await emptyDir(dir) await copy(projectDir, dir, { filter: it => { const basename = path.basename(it) - return basename !== outDirName && basename !== "node_modules" && basename[0] !== "." + return basename !== OUT_DIR_NAME && basename !== "node_modules" && basename[0] !== "." } }) projectDir = dir } try { - if (tempDirCreated != null) { - await tempDirCreated(projectDir) + if (projectDirCreated != null) { + await projectDirCreated(projectDir) if (checkOptions.npmInstallBefore) { await spawnNpmProduction("install", projectDir) } } - await packAndCheck(projectDir, Object.assign({ + // never output to test fixture app + if (!useTempDir) { + dirToDelete = path.join(TEST_DIR, `${(tmpDirCounter++).toString(16)}`) + const devMetadata = packagerOptions.devMetadata + if (devMetadata != null && devMetadata.directories != null) { + throw new Error("unsupported") + } + packagerOptions = deepAssign({}, packagerOptions, {devMetadata: {directories: {output: dirToDelete}}}) + } + + const outDir = useTempDir ? path.join(projectDir, OUT_DIR_NAME) : dirToDelete + await packAndCheck(outDir, Object.assign({ projectDir: projectDir, }, packagerOptions), checkOptions) if (checkOptions.packed != null) { - await checkOptions.packed(projectDir) + await checkOptions.packed(projectDir, outDir) } } finally { - if (useTempDir && customTmpDir == null) { + if (dirToDelete != null) { try { - await remove(projectDir) + await remove(dirToDelete) } catch (e) { - console.warn(`Cannot delete temporary directory ${projectDir}: ${(e.stack || e)}`) + console.warn(`Cannot delete temporary directory ${dirToDelete}: ${(e.stack || e)}`) } } } @@ -102,7 +125,7 @@ export function getTestAsset(file: string) { return path.join(__dirname, "..", "..", "fixtures", file) } -async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions, checkOptions: AssertPackOptions): Promise { +async function packAndCheck(outDir: string, packagerOptions: PackagerOptions, checkOptions: AssertPackOptions): Promise { const packager = new Packager(packagerOptions) const artifacts: Map> = new Map() @@ -133,7 +156,7 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions await checkOsXResult(packager, packagerOptions, checkOptions, artifacts.get(Platform.MAC)) } else if (platform === Platform.LINUX) { - await checkLinuxResult(projectDir, packager, checkOptions, artifacts.get(Platform.LINUX), arch, nameToTarget) + await checkLinuxResult(outDir, packager, checkOptions, artifacts.get(Platform.LINUX), arch, nameToTarget) } else if (platform === Platform.WINDOWS) { await checkWindowsResult(packager, checkOptions, artifacts.get(Platform.WINDOWS), arch, nameToTarget) @@ -142,7 +165,7 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions } } -async function checkLinuxResult(projectDir: string, packager: Packager, checkOptions: AssertPackOptions, artifacts: Array, arch: Arch, nameToTarget: Map) { +async function checkLinuxResult(outDir: string, packager: Packager, checkOptions: AssertPackOptions, artifacts: Array, arch: Arch, nameToTarget: Map) { const appInfo = packager.appInfo function getExpected(): Array { @@ -177,13 +200,10 @@ async function checkLinuxResult(projectDir: string, packager: Packager, checkOpt } })) - // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb", productName), null, 2)) - // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName), null, 2)) - - const packageFile = `${projectDir}/${outDirName}/TestApp-${appInfo.version}.deb` + const packageFile = `${outDir}/TestApp-${appInfo.version}.deb` assertThat(await getContents(packageFile)).isEqualTo(expectedContents) if (arch === Arch.ia32) { - assertThat(await getContents(`${projectDir}/${outDirName}/TestApp-${appInfo.version}-i386.deb`)).isEqualTo(expectedContents) + assertThat(await getContents(`${outDir}/TestApp-${appInfo.version}-i386.deb`)).isEqualTo(expectedContents) } assertThat(parseDebControl(await exec("dpkg", ["--info", packageFile]))).hasProperties({ @@ -343,6 +363,10 @@ async function getContents(path: string) { ) } +export function packageJson(task: (data: any) => void, isApp: boolean = false) { + return (projectDir: string) => modifyPackageJson(projectDir, task, isApp) +} + export async function modifyPackageJson(projectDir: string, task: (data: any) => void, isApp: boolean = false): Promise { const file = isApp ? path.join(projectDir, "app", "package.json") : path.join(projectDir, "package.json") const data = await readJson(file) diff --git a/test/src/helpers/runTests.ts b/test/src/helpers/runTests.ts index 5df322c6c22..3586053721f 100755 --- a/test/src/helpers/runTests.ts +++ b/test/src/helpers/runTests.ts @@ -4,6 +4,7 @@ import { Promise as BluebirdPromise } from "bluebird" import { copy, emptyDir, outputFile, readdir, readFileSync, readJson, unlink, remove } from "fs-extra-p" import { Platform } from "out/metadata" import { cpus, homedir, tmpdir } from "os" +import { TEST_DIR, ELECTRON_VERSION } from "./config" // we set NODE_PATH in this file, so, we cannot use 'out/awaiter' path here //noinspection JSUnusedLocalSymbols @@ -20,14 +21,11 @@ const rootDir = path.join(__dirname, "..", "..", "..") const testPackageDir = path.join(tmpdir(), "electron_builder_published") const testNodeModules = path.join(testPackageDir, "node_modules") -const electronVersion = "1.3.2" - async function main() { - const tempTestBaseDir = path.join(tmpdir(), "electron-builder-test") await BluebirdPromise.all([ deleteOldElectronVersion(), downloadAllRequiredElectronVersions(), - emptyDir(tempTestBaseDir), + emptyDir(TEST_DIR), outputFile(path.join(testPackageDir, "package.json"), `{ "private": true, "version": "1.0.0", @@ -48,7 +46,7 @@ async function main() { await runTests() } finally { - await remove(tempTestBaseDir) + await remove(TEST_DIR) } } @@ -67,7 +65,7 @@ async function deleteOldElectronVersion(): Promise { try { const deletePromises: Array> = [] for (let file of (await readdir(cacheDir))) { - if (file.endsWith(".zip") && !file.includes(electronVersion)) { + if (file.endsWith(".zip") && !file.includes(ELECTRON_VERSION)) { console.log(`Remove old electron ${file}`) deletePromises.push(unlink(path.join(cacheDir, file))) } @@ -95,7 +93,7 @@ function downloadAllRequiredElectronVersions(): Promise { for (let platform of platforms) { for (let arch of (platform === "mas" || platform === "darwin" ? ["x64"] : ["ia32", "x64"])) { downloadPromises.push(downloadElectron({ - version: electronVersion, + version: ELECTRON_VERSION, arch: arch, platform: platform, })) diff --git a/test/src/linuxPackagerTest.ts b/test/src/linuxPackagerTest.ts index adf3f69d0bd..22d5595e8d5 100755 --- a/test/src/linuxPackagerTest.ts +++ b/test/src/linuxPackagerTest.ts @@ -1,5 +1,5 @@ import test from "./helpers/avaEx" -import { assertPack, platform, modifyPackageJson } from "./helpers/packTester" +import { assertPack, platform, modifyPackageJson, app } from "./helpers/packTester" import { remove } from "fs-extra-p" import * as path from "path" import { Platform } from "out" @@ -17,7 +17,7 @@ test.ifDevOrLinuxCi("AppImage", () => assertPack("test-app-one", { test.ifDevOrLinuxCi("AppImage - default icon", () => assertPack("test-app-one", { targets: Platform.LINUX.createTarget("appimage"), }, { - tempDirCreated: projectDir => remove(path.join(projectDir, "build")) + projectDirCreated: projectDir => remove(path.join(projectDir, "build")) }, )) @@ -26,20 +26,14 @@ test.ifDevOrLinuxCi("targets", () => assertPack("test-app-one", { targets: Platform.LINUX.createTarget(["sh", "freebsd", "pacman", "zip", "7z"]), })) -test.ifDevOrLinuxCi("tar", () => assertPack("test-app-one", { - targets: Platform.LINUX.createTarget(["tar.xz", "tar.lz", "tar.bz2"]), -})) +test.ifDevOrLinuxCi("tar", app({targets: Platform.LINUX.createTarget(["tar.xz", "tar.lz", "tar.bz2"])})) // https://github.com/electron-userland/electron-builder/issues/460 // for some reasons in parallel to fmp we cannot use tar -test.ifDevOrLinuxCi("rpm and tar.gz", () => assertPack("test-app-one", { - targets: Platform.LINUX.createTarget(["rpm", "tar.gz"]), -})) +test.ifDevOrLinuxCi("rpm and tar.gz", app({targets: Platform.LINUX.createTarget(["rpm", "tar.gz"])})) -test.ifNotWindows("icons from ICNS", () => assertPack("test-app-one", { - targets: Platform.LINUX.createTarget(), -}, { - tempDirCreated: it => remove(path.join(it, "build", "icons")) +test.ifNotWindows("icons from ICNS", app({targets: Platform.LINUX.createTarget()}, { + projectDirCreated: it => remove(path.join(it, "build", "icons")) })) test.ifNotWindows("custom depends", () => assertPack("test-app-one", { @@ -58,7 +52,7 @@ test.ifNotWindows("custom depends", () => assertPack("test-app-one", { test.ifNotWindows("no-author-email", t => { t.throws(assertPack("test-app-one", platform(Platform.LINUX), { - tempDirCreated: projectDir => modifyPackageJson(projectDir, data => { + projectDirCreated: projectDir => modifyPackageJson(projectDir, data => { data.author = "Foo" }) }), /Please specify author 'email' in .+/) diff --git a/test/src/macPackagerTest.ts b/test/src/macPackagerTest.ts index 3c43adf4988..3e4330fd54b 100644 --- a/test/src/macPackagerTest.ts +++ b/test/src/macPackagerTest.ts @@ -1,5 +1,5 @@ import test from "./helpers/avaEx" -import { assertPack, platform, modifyPackageJson, signed } from "./helpers/packTester" +import { assertPack, platform, modifyPackageJson, signed, app } from "./helpers/packTester" import OsXPackager from "out/macPackager" import { move, writeFile, deleteFile, remove } from "fs-extra-p" import * as path from "path" @@ -16,11 +16,9 @@ import { DmgTarget } from "out/targets/dmg" //noinspection JSUnusedLocalSymbols const __awaiter = require("out/util/awaiter") -test.ifOsx("two-package", () => assertPack("test-app", signed({ - targets: createTargets([Platform.MAC], null, "all"), -}))) +test.ifOsx("two-package", () => assertPack("test-app", {targets: createTargets([Platform.MAC], null, "all")}, {signed: true, useTempDir: true})) -test.ifOsx("one-package", () => assertPack("test-app-one", signed(platform(Platform.MAC)))) +test.ifOsx("one-package", app(platform(Platform.MAC), {signed: true})) function createTargetTest(target: Array, expectedContents: Array) { let options: PackagerOptions = { @@ -37,14 +35,12 @@ function createTargetTest(target: Array, expectedContents: Array options = signed(options) } - return () => assertPack("test-app-one", options, { - expectedContents: expectedContents - }) + return app(options, {expectedContents: expectedContents}) } test.ifOsx("only dmg", createTargetTest(["dmg"], ["Test App ßW-1.1.0.dmg"])) test.ifOsx("only zip", createTargetTest(["zip"], ["Test App ßW-1.1.0-mac.zip"])) -test.ifOsx("invalid target", (t: any) => t.throws(createTargetTest(["ttt"], [])(), "Unknown target: ttt")) +test.ifOsx("invalid target", t => t.throws(createTargetTest(["ttt"], [])(), "Unknown target: ttt")) if (process.env.CSC_KEY_PASSWORD == null) { console.warn("Skip mas tests because CSC_KEY_PASSWORD is not defined") @@ -57,7 +53,7 @@ else { let platformPackager: CheckingMacPackager = null return assertPack("test-app-one", signed({ targets: Platform.MAC.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager, cleanupTasks), + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager), devMetadata: { build: { mac: { @@ -84,7 +80,7 @@ else { let platformPackager: CheckingMacPackager = null return assertPack("test-app-one", signed({ targets: Platform.MAC.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager, cleanupTasks), + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager), devMetadata: { build: { mac: { @@ -108,9 +104,9 @@ else { let platformPackager: CheckingMacPackager = null return assertPack("test-app-one", signed({ targets: Platform.MAC.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager, cleanupTasks), + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager), }), { - tempDirCreated: projectDir => BluebirdPromise.all([ + projectDirCreated: projectDir => BluebirdPromise.all([ writeFile(path.join(projectDir, "build", "entitlements.mac.plist"), ""), writeFile(path.join(projectDir, "build", "entitlements.mac.inherit.plist"), ""), ]), @@ -125,12 +121,12 @@ else { }) } -test.ifOsx("no background", (t: any) => assertPack("test-app-one", platform(Platform.MAC), { - tempDirCreated: projectDir => deleteFile(path.join(projectDir, "build", "background.png")) +test.ifOsx("no background", app(platform(Platform.MAC), { + projectDirCreated: projectDir => deleteFile(path.join(projectDir, "build", "background.png")) })) -test.ifOsx("no build directory", (t: any) => assertPack("test-app-one", platform(Platform.MAC), { - tempDirCreated: projectDir => remove(path.join(projectDir, "build")) +test.ifOsx("no build directory", app(platform(Platform.MAC), { + projectDirCreated: projectDir => remove(path.join(projectDir, "build")) })) test.ifOsx("custom background - old way", () => { @@ -138,9 +134,9 @@ test.ifOsx("custom background - old way", () => { const customBackground = "customBackground.png" return assertPack("test-app-one", { targets: Platform.MAC.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager, cleanupTasks) + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager) }, { - tempDirCreated: projectDir => BluebirdPromise.all([ + projectDirCreated: projectDir => BluebirdPromise.all([ move(path.join(projectDir, "build", "background.png"), path.join(projectDir, customBackground)), modifyPackageJson(projectDir, data => { data.build.osx = { @@ -162,9 +158,9 @@ test.ifOsx("custom background - new way", () => { const customBackground = "customBackground.png" return assertPack("test-app-one", { targets: Platform.MAC.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager, cleanupTasks) + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager) }, { - tempDirCreated: projectDir => BluebirdPromise.all([ + projectDirCreated: projectDir => BluebirdPromise.all([ move(path.join(projectDir, "build", "background.png"), path.join(projectDir, customBackground)), modifyPackageJson(projectDir, data => { data.build.mac = { @@ -194,7 +190,7 @@ test.ifOsx("disable dmg icon, bundleVersion", () => { let platformPackager: CheckingMacPackager = null return assertPack("test-app-one", { targets: Platform.MAC.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager, cleanupTasks), + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingMacPackager(packager), devMetadata: { build: { dmg: { @@ -220,8 +216,8 @@ class CheckingMacPackager extends OsXPackager { effectiveSignOptions: SignOptions effectiveFlatOptions: FlatOptions - constructor(info: BuildInfo, cleanupTasks: Array<() => Promise>) { - super(info, cleanupTasks) + constructor(info: BuildInfo) { + super(info) } async pack(outDir: string, arch: Arch, targets: Array, postAsyncTasks: Array>): Promise { diff --git a/test/src/nsisTest.ts b/test/src/nsisTest.ts index 56940fccf9a..b80d1664822 100644 --- a/test/src/nsisTest.ts +++ b/test/src/nsisTest.ts @@ -51,7 +51,7 @@ test.ifNotCiOsx("installerHeaderIcon", () => { return false } }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { headerIconPath = path.join(projectDir, "build", "installerHeaderIcon.ico") return copy(getTestAsset("headerIcon.ico"), headerIconPath) } @@ -79,7 +79,7 @@ test.ifNotCiOsx("boring, MUI_HEADER", () => { return true } }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { installerHeaderPath = path.join(projectDir, "build", "installerHeader.bmp") return copy(getTestAsset("installerHeader.bmp"), installerHeaderPath) } @@ -108,7 +108,7 @@ test.ifNotCiOsx("boring, MUI_HEADER as option", () => { return false } }, { - tempDirCreated: projectDir => { + projectDirCreated: projectDir => { installerHeaderPath = path.join(projectDir, "foo.bmp") return copy(getTestAsset("installerHeader.bmp"), installerHeaderPath) }, @@ -117,7 +117,7 @@ test.ifNotCiOsx("boring, MUI_HEADER as option", () => { }) test.ifDevOrLinuxCi("custom include", () => assertPack("test-app-one", {targets: nsisTarget}, { - tempDirCreated: projectDir => copy(getTestAsset("installer.nsh"), path.join(projectDir, "build", "installer.nsh")), + projectDirCreated: projectDir => copy(getTestAsset("installer.nsh"), path.join(projectDir, "build", "installer.nsh")), packed: projectDir => BluebirdPromise.all([ assertThat(path.join(projectDir, "build", "customHeader")).isFile(), assertThat(path.join(projectDir, "build", "customInit")).isFile(), @@ -126,6 +126,6 @@ test.ifDevOrLinuxCi("custom include", () => assertPack("test-app-one", {targets: })) test.ifDevOrLinuxCi("custom script", app({targets: nsisTarget}, { - tempDirCreated: projectDir => copy(getTestAsset("installer.nsi"), path.join(projectDir, "build", "installer.nsi")), + projectDirCreated: projectDir => copy(getTestAsset("installer.nsi"), path.join(projectDir, "build", "installer.nsi")), packed: projectDir => assertThat(path.join(projectDir, "build", "customInstallerScript")).isFile(), })) \ No newline at end of file diff --git a/test/src/winPackagerTest.ts b/test/src/winPackagerTest.ts index 75be6abc410..979749b2b6f 100755 --- a/test/src/winPackagerTest.ts +++ b/test/src/winPackagerTest.ts @@ -29,8 +29,9 @@ test.skip("delta and msi", app({ }, })) -test.ifDevOrWinCi("beta version", () => { - const metadata: any = { +test.ifDevOrWinCi("beta version", app({ + targets: Platform.WINDOWS.createTarget(["squirrel", "nsis"]), + devMetadata: { version: "3.0.0-beta.2", build: { win: { @@ -38,15 +39,11 @@ test.ifDevOrWinCi("beta version", () => { }, }, } - return assertPack("test-app-one", { - targets: Platform.WINDOWS.createTarget(["squirrel", "nsis"]), - devMetadata: metadata - }) -}) +})) test.ifNotCiOsx("msi as string", t => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS), { - tempDirCreated: it => modifyPackageJson(it, data => { + projectDirCreated: it => modifyPackageJson(it, data => { data.build.win = { msi: "false", } @@ -60,7 +57,7 @@ test("detect install-spinner, certificateFile/password", () => { return assertPack("test-app-one", { targets: Platform.WINDOWS.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingWinPackager(packager, cleanupTasks), + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingWinPackager(packager), devMetadata: { build: { win: { @@ -69,7 +66,7 @@ test("detect install-spinner, certificateFile/password", () => { } } }, { - tempDirCreated: it => { + projectDirCreated: it => { loadingGifPath = path.join(it, "build", "install-spinner.gif") return BluebirdPromise.all([ copy(getTestAsset("install-spinner.gif"), loadingGifPath), @@ -90,20 +87,20 @@ test("detect install-spinner, certificateFile/password", () => { }) test.ifNotCiOsx("icon < 256", t => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS), { - tempDirCreated: projectDir => rename(path.join(projectDir, "build", "incorrect.ico"), path.join(projectDir, "build", "icon.ico")) + projectDirCreated: projectDir => rename(path.join(projectDir, "build", "incorrect.ico"), path.join(projectDir, "build", "icon.ico")) }), /Windows icon size must be at least 256x256, please fix ".+/)) test.ifNotCiOsx("icon not an image", t => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS), { - tempDirCreated: projectDir => outputFile(path.join(projectDir, "build", "icon.ico"), "foo") + projectDirCreated: projectDir => outputFile(path.join(projectDir, "build", "icon.ico"), "foo") }), /Windows icon is not valid ico file, please fix ".+/)) test.ifOsx("custom icon", () => { let platformPackager: CheckingWinPackager = null return assertPack("test-app-one", { targets: Platform.WINDOWS.createTarget(), - platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingWinPackager(packager, cleanupTasks) + platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingWinPackager(packager) }, { - tempDirCreated: projectDir => BluebirdPromise.all([ + projectDirCreated: projectDir => BluebirdPromise.all([ rename(path.join(projectDir, "build", "icon.ico"), path.join(projectDir, "customIcon.ico")), modifyPackageJson(projectDir, data => { data.build.win = { @@ -135,8 +132,8 @@ class CheckingWinPackager extends WinPackager { effectivePackOptions: ElectronPackagerOptions - constructor(info: BuildInfo, cleanupTasks: Array<() => Promise>) { - super(info, cleanupTasks) + constructor(info: BuildInfo) { + super(info) } async pack(outDir: string, arch: Arch, targets: Array, postAsyncTasks: Array>): Promise { @@ -144,7 +141,7 @@ class CheckingWinPackager extends WinPackager { this.effectivePackOptions = await this.computePackOptions() const helperClass: typeof SquirrelWindowsTarget = require("out/targets/squirrelWindows").default - this.effectiveDistOptions = await (new helperClass(this, []).computeEffectiveDistOptions()) + this.effectiveDistOptions = await (new helperClass(this).computeEffectiveDistOptions()) await this.sign(this.computeAppOutDir(outDir, arch)) }