Skip to content

Commit

Permalink
feat: Squirrel.Windows doesn't escape " in the description
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed May 12, 2016
1 parent b71d2f3 commit aaa9eba
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 80 deletions.
5 changes: 5 additions & 0 deletions docs/Multi Platform Build.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ To build app in distributable format for Windows on Linux:
sudo apt-get install mono-devel -y
```

* Install zip.
```
apt-get install zip
```

To build app in 32 bit from a machine with 64 bit:

```
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"deep-assign": "^2.0.0",
"electron-osx-sign-tf": "0.4.0-beta.0",
"electron-packager-tf": "^7.0.2-beta.0",
"electron-winstaller-fixed": "~2.6.2",
"electron-winstaller-fixed": "~2.7.0",
"fs-extra-p": "^1.0.1",
"globby": "^4.0.0",
"hosted-git-info": "^2.1.4",
Expand Down Expand Up @@ -106,7 +106,7 @@
"should": "^8.3.1",
"ts-babel": "^0.8.6",
"tsconfig-glob": "^0.4.3",
"tslint": "^3.9.0-dev.0",
"tslint": "^3.10.0-dev.1",
"typescript": "1.9.0-dev.20160511",
"whitespace": "^2.0.0"
},
Expand Down
2 changes: 1 addition & 1 deletion src/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async function main() {
async function isRecentlyUsed(dir: string) {
try {
const lastUsed = parseInt(await readFile(path.join(dir, ".lastUsed"), "utf8"), 10)
if (!isNaN(lastUsed) && (Date.now() - lastUsed) < 3600000) {
if (!isNaN(lastUsed) && (Date.now() - lastUsed) < (3600000 * 2)) {
return true
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/linuxPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ export class LinuxPackager extends PlatformPackager<LinuxBuildOptions> {
return [].concat(...await BluebirdPromise.all(promises))
}

async pack(outDir: string, arch: string, postAsyncTasks: Array<Promise<any>>): Promise<any> {
const appOutDir = this.computeAppOutDir(outDir, arch)
await this.doPack(this.computePackOptions(outDir, arch), outDir, appOutDir, arch, this.customBuildOptions)

if (this.options.dist) {
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch))
}
}

private async computeDesktop(tempDir: string): Promise<Array<string>> {
const tempFile = path.join(tempDir, this.appName + ".desktop")
await outputFile(tempFile, this.debOptions.desktop || `[Desktop Entry]
Expand Down
13 changes: 3 additions & 10 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,11 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
})
}

pack(outDir: string, arch: string, postAsyncTasks: Array<Promise<any>>): Promise<any> {
const appOutDir = this.computeAppOutDir(outDir, arch)
return this.doPack(this.computePackOptions(outDir, arch), outDir, appOutDir, arch, this.customBuildOptions, postAsyncTasks)
}
abstract pack(outDir: string, arch: string, postAsyncTasks: Array<Promise<any>>): Promise<any>

protected async doPack(options: ElectronPackagerOptions, outDir: string, appOutDir: string, arch: string, customBuildOptions: DC, postAsyncTasks: Array<Promise<any>> | null = null) {
protected async doPack(options: ElectronPackagerOptions, outDir: string, appOutDir: string, arch: string, customBuildOptions: DC) {
await this.packApp(options, appOutDir)
await this.copyExtraResources(appOutDir, arch, customBuildOptions)
if (postAsyncTasks != null && this.options.dist) {
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch))
}
}

protected computePackOptions(outDir: string, arch: string): ElectronPackagerOptions {
Expand All @@ -137,6 +131,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
asar: true,
overwrite: true,
"app-version": version,
"app-copyright": `Copyright © ${new Date().getFullYear()} ${this.metadata.author.name || this.appName}`,
"build-version": buildVersion,
tmpdir: false,
"version-string": {
Expand Down Expand Up @@ -187,8 +182,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
return await BluebirdPromise.map(await this.getExtraResources(arch, customBuildOptions), it => copy(path.join(this.projectDir, it), path.join(resourcesDir, it)))
}

protected abstract packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any>

protected async computePackageUrl(): Promise<string | null> {
const url = this.metadata.homepage || this.devMetadata.homepage
if (url != null) {
Expand Down
61 changes: 34 additions & 27 deletions src/winPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ import { PlatformPackager, BuildInfo } from "./platformPackager"
import { Platform, WinBuildOptions } from "./metadata"
import * as path from "path"
import { log, statOrNull } from "./util"
import { readFile, deleteFile, stat, rename, copy, emptyDir, writeFile, open, close, read } from "fs-extra-p"
import { readFile, deleteFile, rename, copy, emptyDir, writeFile, open, close, read, ensureDir } from "fs-extra-p"
import { sign } from "signcode-tf"
import ElectronPackagerOptions = ElectronPackager.ElectronPackagerOptions

//noinspection JSUnusedLocalSymbols
const __awaiter = require("./awaiter")

export class WinPackager extends PlatformPackager<WinBuildOptions> {
certFilePromise: Promise<string | null>

extraNuGetFileSources: Promise<Array<string>> | null

loadingGifStat: Promise<string> | null

readonly iconPath: Promise<string>
Expand Down Expand Up @@ -56,32 +55,32 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
// we must check icon before pack because electron-packager uses icon and it leads to cryptic error message "spawn wine ENOENT"
await this.iconPath

let appOutDir = this.computeAppOutDir(outDir, arch)
const packOptions = this.computePackOptions(outDir, arch)

if (!this.options.dist) {
return await super.pack(outDir, arch, postAsyncTasks)
await this.doPack(packOptions, outDir, appOutDir, arch, this.customBuildOptions)
return
}

const appOutDir = this.computeAppOutDir(outDir, arch)
const unpackedDir = path.join(outDir, `win${arch === "x64" ? "" : `-${arch}`}-unpacked`)
const finalAppOut = path.join(outDir, `win${arch === "x64" ? "" : `-${arch}`}-unpacked`, "lib", "net45")
const installerOut = computeDistOut(outDir, arch)
log("Removing %s", installerOut)
await BluebirdPromise.all([
this.packApp(this.computePackOptions(outDir, arch), appOutDir),
emptyDir(installerOut)
this.packApp(packOptions, appOutDir),
emptyDir(installerOut),
emptyDir(unpackedDir)
// must be otherwise rename doesn't work
.then(() => ensureDir(finalAppOut))
])

const extraResources = await this.copyExtraResources(appOutDir, arch, this.customBuildOptions)
if (extraResources.length > 0) {
this.extraNuGetFileSources = BluebirdPromise.map(extraResources, file => {
return stat(file)
.then(it => {
const relativePath = path.relative(appOutDir, file)
const src = it.isDirectory() ? `${relativePath}${path.sep}**` : relativePath
return `<file src="${src}" target="lib\\net45\\${relativePath.replace(/\//g, "\\")}"/>`
})
})
}
await rename(appOutDir, finalAppOut)
appOutDir = finalAppOut

await this.copyExtraResources(appOutDir, arch, this.customBuildOptions)
if (this.options.dist) {
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch))
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, arch, packOptions))
}
}

Expand All @@ -102,7 +101,7 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
}
}

protected async computeEffectiveDistOptions(appOutDir: string, installerOutDir: string): Promise<any> {
protected async computeEffectiveDistOptions(appOutDir: string, installerOutDir: string, packOptions: ElectronPackagerOptions): Promise<any> {
let iconUrl = this.customBuildOptions.iconUrl || this.devMetadata.build.iconUrl
if (iconUrl == null) {
if (this.info.repositoryInfo != null) {
Expand All @@ -120,6 +119,13 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
checkConflictingOptions(this.customBuildOptions)

const projectUrl = await this.computePackageUrl()
const rceditOptions = {
"version-string": packOptions["version-string"],
"file-version": packOptions["build-version"],
"product-version": packOptions["app-version"],
}
rceditOptions["version-string"]!.LegalCopyright = packOptions["app-copyright"]

const options: any = Object.assign({
name: this.metadata.name,
productName: this.appName,
Expand All @@ -138,13 +144,14 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
skipUpdateIcon: true,
usePackageJson: false,
noMsi: true,
extraFileSpecs: this.extraNuGetFileSources == null ? null : ("\n" + (await this.extraNuGetFileSources).join("\n")),
extraMetadataSpecs: projectUrl == null ? null : `\n <projectUrl>${projectUrl}</projectUrl>`,
copyright: packOptions["app-copyright"],
sign: {
name: this.appName,
site: projectUrl,
overwrite: true,
}
},
rcedit: rceditOptions,
}, this.customBuildOptions)

if (this.loadingGifStat != null) {
Expand All @@ -154,9 +161,9 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
return options
}

async packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any> {
async packageInDistributableFormat(outDir: string, appOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
const installerOutDir = computeDistOut(outDir, arch)
await require("electron-winstaller-fixed").createWindowsInstaller(await this.computeEffectiveDistOptions(appOutDir, installerOutDir))
await require("electron-winstaller-fixed").createWindowsInstaller(await this.computeEffectiveDistOptions(appOutDir, installerOutDir, packOptions))

const version = this.metadata.version
const archSuffix = arch === "x64" ? "" : ("-" + arch)
Expand All @@ -170,8 +177,8 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
}

const promises: Array<Promise<any>> = [
rename(path.join(installerOutDir, "Setup.exe"), path.join(installerOutDir, `${this.appName}Setup-${version}${archSuffix}.exe`))
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}Setup-${version}${archSuffix}.exe`)),
rename(path.join(installerOutDir, "Setup.exe"), path.join(installerOutDir, `${this.appName} Setup ${version}${archSuffix}.exe`))
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-Setup-${version}${archSuffix}.exe`)),
]

if (archSuffix === "") {
Expand Down Expand Up @@ -244,7 +251,7 @@ function isIco(buffer: Buffer): boolean {
}

export function computeDistOut(outDir: string, arch: string): string {
return path.join(outDir, "win" + (arch === "x64" ? "-x64" : ""))
return path.join(outDir, "win" + (arch === "x64" ? "" : "-arch"))
}

function checkConflictingOptions(options: any) {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/test-app-one/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "TestApp",
"version": "1.1.0",
"homepage": "http://foo.example.com",
"description": "Test Application",
"description": "Test Application (test quite \" #378)",
"scripts": {
"start": "electron ."
},
Expand Down
45 changes: 13 additions & 32 deletions test/src/BuildTest.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import test from "./helpers/avaEx"
import { assertPack, modifyPackageJson, outDirName } from "./helpers/packTester"
import { expectedWinContents } from "./helpers/expectedContents"
import { move, outputFile, outputJson } from "fs-extra-p"
import { Promise as BluebirdPromise } from "bluebird"
import * as path from "path"
import { assertThat } from "./helpers/fileAssert"
import { Platform, PackagerOptions } from "out"
import pathSorter = require("path-sort")

//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")
Expand Down Expand Up @@ -105,14 +107,16 @@ test("www as default dir", () => assertPack("test-app", {
}))

test("copy extra resource", async () => {
for (let platform of getPossiblePlatforms()) {
for (let platform of [Platform.WINDOWS]) {
const osName = platform.buildConfigurationKey

//noinspection SpellCheckingInspection
await assertPack("test-app", {
platform: [platform],
// to check NuGet package
dist: platform === Platform.WINDOWS
dist: platform === Platform.WINDOWS,
cscLink: null,
cscInstallerLink: null,
}, {
tempDirCreated: (projectDir) => {
return BluebirdPromise.all([
Expand Down Expand Up @@ -146,6 +150,9 @@ test("copy extra resource", async () => {
if (platform === Platform.OSX) {
resourcesDir = path.join(resourcesDir, "TestApp.app", "Contents", "Resources")
}
else if (platform === Platform.WINDOWS) {
resourcesDir = path.join(projectDir, outDirName, "win-unpacked", "lib", "net45")
}
await assertThat(path.join(resourcesDir, "foo")).isDirectory()
await assertThat(path.join(resourcesDir, "foo", "nameWithoutDot")).isFile()
await assertThat(path.join(resourcesDir, "bar", "hello.txt")).isFile()
Expand All @@ -154,39 +161,13 @@ test("copy extra resource", async () => {
await assertThat(path.join(resourcesDir, "platformSpecific")).isFile()
await assertThat(path.join(resourcesDir, "ignoreMe.txt")).doesNotExist()
},
expectedContents: platform === Platform.WINDOWS ? [
"lib/net45/content_resources_200_percent.pak",
"lib/net45/content_shell.pak",
"lib/net45/d3dcompiler_47.dll",
"lib/net45/ffmpeg.dll",
"lib/net45/icudtl.dat",
"lib/net45/libEGL.dll",
"lib/net45/libGLESv2.dll",
"lib/net45/LICENSE",
"lib/net45/LICENSES.chromium.html",
"lib/net45/msvcp120.dll",
"lib/net45/msvcr120.dll",
"lib/net45/natives_blob.bin",
"lib/net45/node.dll",
"lib/net45/platformSpecific",
"lib/net45/snapshot_blob.bin",
"lib/net45/TestApp.exe",
"lib/net45/ui_resources_200_percent.pak",
"lib/net45/Update.exe",
"lib/net45/vccorlib120.dll",
"lib/net45/version",
"lib/net45/xinput1_3.dll",
expectedContents: platform === Platform.WINDOWS ? pathSorter(expectedWinContents.concat(
"lib/net45/bar/hello.txt",
"lib/net45/bar/x64.txt",
"lib/net45/foo/nameWithoutDot",
"lib/net45/locales/en-US.pak",
"lib/net45/resources/app.asar",
"lib/net45/resources/electron.asar",
"lib/net45/win/x64.txt",
"TestApp.nuspec",
"[Content_Types].xml",
"_rels/.rels"
] : null,
"lib/net45/platformSpecific",
"lib/net45/win/x64.txt"
)) : null,
})
}
})
Expand Down
10 changes: 5 additions & 5 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ async function checkLinuxResult(projectDir: string, packager: Packager, packager
Maintainer: "Foo Bar <[email protected]>",
Vendor: "Foo Bar <[email protected]>",
Package: "testapp",
Description: " \n Test Application",
Description: " \n Test Application (test quite \" #378)",
})
}

Expand Down Expand Up @@ -206,7 +206,7 @@ async function checkWindowsResult(packager: Packager, packagerOptions: PackagerO
function getWinExpected(archSuffix: string) {
return [
`RELEASES${archSuffix}`,
`${productName}Setup-1.1.0${archSuffix}.exe`,
`${productName} Setup 1.1.0${archSuffix}.exe`,
`TestApp-1.1.0${archSuffix}-full.nupkg`,
]
}
Expand All @@ -225,7 +225,7 @@ async function checkWindowsResult(packager: Packager, packagerOptions: PackagerO
if (archSuffix == "") {
const expectedArtifactNames = expected.slice()
expectedArtifactNames[1] = `TestAppSetup-1.1.0${archSuffix}.exe`
assertThat(artifacts.map(it => it.artifactName).filter(it => it != null)).deepEqual([`TestAppSetup-1.1.0${archSuffix}.exe`])
assertThat(artifacts.map(it => it.artifactName).filter(it => it != null)).deepEqual([`TestApp-Setup-1.1.0${archSuffix}.exe`])
}

const packageFile = path.join(path.dirname(artifacts[0].file), `TestApp-1.1.0${archSuffix}-full.nupkg`)
Expand All @@ -238,7 +238,7 @@ async function checkWindowsResult(packager: Packager, packagerOptions: PackagerO
const expectedContents = checkOptions == null || checkOptions.expectedContents == null ? expectedWinContents : checkOptions.expectedContents
assertThat(files).deepEqual(expectedContents.map(it => {
if (it === "lib/net45/TestApp.exe") {
return `lib/net45/${productName.replace(/ /g, "%20")}.exe`
return `lib/net45/${productName}.exe`
}
else {
return it
Expand All @@ -260,7 +260,7 @@ async function checkWindowsResult(packager: Packager, packagerOptions: PackagerO
<owners>Foo Bar</owners>
<iconUrl>https://raw.githubusercontent.com/szwacz/electron-boilerplate/master/resources/windows/icon.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Test Application</description>
<description>Test Application (test quite \" #378)</description>
<copyright>Copyright © ${new Date().getFullYear()} Foo Bar</copyright>
<projectUrl>http://foo.example.com</projectUrl>
</metadata>
Expand Down
6 changes: 4 additions & 2 deletions test/src/winPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { WinPackager, computeDistOut } from "out/winPackager"
import { BuildInfo } from "out/platformPackager"
import { Promise as BluebirdPromise } from "bluebird"
import * as assertThat from "should/as-function"
import ElectronPackagerOptions = ElectronPackager.ElectronPackagerOptions

//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")
Expand Down Expand Up @@ -85,10 +86,11 @@ class CheckingWinPackager extends WinPackager {
async pack(outDir: string, arch: string): Promise<any> {
// skip pack
const installerOutDir = computeDistOut(outDir, arch)
this.effectiveDistOptions = await this.computeEffectiveDistOptions(this.computeAppOutDir(outDir, arch), installerOutDir)
const packOptions = this.computePackOptions(outDir, arch)
this.effectiveDistOptions = await this.computeEffectiveDistOptions(this.computeAppOutDir(outDir, arch), installerOutDir, packOptions)
}

async packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any> {
async packageInDistributableFormat(outDir: string, appOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
// skip
}
}
Loading

0 comments on commit aaa9eba

Please sign in to comment.