Skip to content

Commit

Permalink
fix: Build failing when productName contains a slash
Browse files Browse the repository at this point in the history
Close #539
  • Loading branch information
develar committed Jun 27, 2016
1 parent bb71621 commit 726e574
Show file tree
Hide file tree
Showing 13 changed files with 57 additions and 58 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"debug": "^2.2.0",
"deep-assign": "^2.0.0",
"electron-osx-sign-tf": "0.6.0",
"electron-packager-tf": "~7.4.0",
"electron-packager-tf": "~7.5.1",
"electron-winstaller-fixed": "~2.11.5",
"fs-extra-p": "^1.0.3",
"hosted-git-info": "^2.1.5",
Expand Down
5 changes: 5 additions & 0 deletions src/appInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { warn } from "./util/log"
import { smarten } from "./platformPackager"
import { isEmptyOrSpaces } from "./util/util"
import { getRepositoryInfo } from "./repositoryInfo"
import sanitizeFileName = require("sanitize-filename")

//noinspection JSUnusedLocalSymbols
const __awaiter = require("./util/awaiter")
Expand All @@ -23,6 +24,8 @@ export class AppInfo {
readonly version: string
readonly buildVersion: string

readonly productFilename: string

constructor(public metadata: AppMetadata, private devMetadata: DevMetadata) {
let buildVersion = metadata.version
this.version = buildVersion
Expand All @@ -32,6 +35,8 @@ export class AppInfo {
buildVersion += `.${buildNumber}`
}
this.buildVersion = buildVersion

this.productFilename = sanitizeFileName(this.productName)
}

get companyName() {
Expand Down
4 changes: 2 additions & 2 deletions src/macPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default class MacPackager extends PlatformPackager<MacOptions> {
const identity = codeSigningInfo.name

const baseSignOptions: BaseSignOptions = {
app: path.join(appOutDir, `${this.appInfo.productName}.app`),
app: path.join(appOutDir, `${this.appInfo.productFilename}.app`),
platform: masOptions == null ? "darwin" : "mas",
keychain: <any>codeSigningInfo.keychainName,
version: this.info.electronVersion
Expand Down Expand Up @@ -202,7 +202,7 @@ export default class MacPackager extends PlatformPackager<MacOptions> {
await task(`Signing app (identity: ${identity})`, this.doSign(signOptions))

if (masOptions != null) {
const pkg = path.join(appOutDir, `${this.appInfo.productName}-${this.appInfo.version}.pkg`)
const pkg = path.join(appOutDir, `${this.appInfo.productFilename}-${this.appInfo.version}.pkg`)
await this.doFlat(Object.assign({
pkg: pkg,
identity: codeSigningInfo.installerName,
Expand Down
12 changes: 5 additions & 7 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
readonly projectDir: string
readonly buildResourcesDir: string

readonly metadata: AppMetadata
readonly devMetadata: DevMetadata

readonly platformSpecificBuildOptions: DC
Expand All @@ -96,7 +95,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
this.appInfo = info.appInfo
this.options = info.options
this.projectDir = info.projectDir
this.metadata = info.appInfo.metadata
this.devMetadata = info.devMetadata

this.buildResourcesDir = path.resolve(this.projectDir, this.relativeBuildResourcesDirname)
Expand Down Expand Up @@ -299,7 +297,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

private async doCopyExtraFiles(isResources: boolean, appOutDir: string, arch: Arch, customBuildOptions: DC): Promise<any> {
const base = isResources ? this.getResourcesDir(appOutDir) : this.platform === Platform.MAC ? path.join(appOutDir, `${this.appInfo.productName}.app`, "Contents") : appOutDir
const base = isResources ? this.getResourcesDir(appOutDir) : this.platform === Platform.MAC ? path.join(appOutDir, `${this.appInfo.productFilename}.app`, "Contents") : appOutDir
const patterns = this.getFilePatterns(isResources ? "extraResources" : "extraFiles", customBuildOptions)
return patterns == null || patterns.length === 0 ? null : copyFiltered(this.projectDir, base, createFilter(this.projectDir, this.getParsedPatterns(patterns, arch)))
}
Expand Down Expand Up @@ -334,7 +332,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

private getOSXResourcesDir(appOutDir: string): string {
return path.join(appOutDir, `${this.appInfo.productName}.app`, "Contents", "Resources")
return path.join(appOutDir, `${this.appInfo.productFilename}.app`, "Contents", "Resources")
}

private async checkFileInPackage(resourcesDir: string, file: string, isAsar: boolean) {
Expand Down Expand Up @@ -363,12 +361,12 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
throw new Error(`Output directory "${appOutDir}" is not a directory. Seems like a wrong configuration.`)
}

const mainFile = this.metadata.main || "index.js"
const mainFile = this.appInfo.metadata.main || "index.js"
await this.checkFileInPackage(this.getResourcesDir(appOutDir), mainFile, isAsar)
}

protected async archiveApp(format: string, appOutDir: string, outFile: string): Promise<any> {
return archiveApp(this.devMetadata.build.compression, format, outFile, this.platform === Platform.MAC ? path.join(appOutDir, `${this.appInfo.productName}.app`) : appOutDir)
return archiveApp(this.devMetadata.build.compression, format, outFile, this.platform === Platform.MAC ? path.join(appOutDir, `${this.appInfo.productFilename}.app`) : appOutDir)
}

generateName(ext: string, arch: Arch, deployment: boolean): string {
Expand All @@ -387,7 +385,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

generateName2(ext: string, classifier: string | n, deployment: boolean): string {
return `${deployment ? this.appInfo.name : this.appInfo.productName}-${this.metadata.version}${classifier == null ? "" : `-${classifier}`}.${ext}`
return `${deployment ? this.appInfo.name : this.appInfo.productFilename}-${this.appInfo.version}${classifier == null ? "" : `-${classifier}`}.${ext}`
}

protected async getDefaultIcon(ext: string) {
Expand Down
4 changes: 2 additions & 2 deletions src/targets/dmg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class DmgTarget extends Target {

async build(appOutDir: string) {
const appInfo = this.packager.appInfo
const artifactPath = path.join(appOutDir, `${appInfo.productName}-${appInfo.version}.dmg`)
const artifactPath = path.join(appOutDir, `${appInfo.productFilename}-${appInfo.version}.dmg`)
await new BluebirdPromise<any>(async(resolve, reject) => {
log("Creating DMG")
const dmgOptions = {
Expand Down Expand Up @@ -78,7 +78,7 @@ export class DmgTarget extends Target {
}
}

specification.contents[1].path = path.join(appOutDir, `${packager.appInfo.productName}.app`)
specification.contents[1].path = path.join(appOutDir, `${packager.appInfo.productFilename}.app`)
return specification
}
}
14 changes: 7 additions & 7 deletions src/targets/fpm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class FpmTarget extends Target {

const templateOptions = Object.assign({
// old API compatibility
executable: this.packager.appInfo.productName,
executable: this.packager.appInfo.productFilename,
}, this.packager.platformSpecificBuildOptions)

const afterInstallTemplate = this.packager.platformSpecificBuildOptions.afterInstall || path.join(defaultTemplatesDir, "after-install.tpl")
Expand All @@ -111,7 +111,7 @@ export class FpmTarget extends Target {
}

const options = this.options
const author = options.maintainer || `${packager.metadata.author.name} <${packager.metadata.author.email}>`
const author = options.maintainer || `${packager.appInfo.metadata.author.name} <${packager.appInfo.metadata.author.email}>`
const synopsis = options.synopsis
const args = [
"-s", "dir",
Expand Down Expand Up @@ -163,28 +163,28 @@ export class FpmTarget extends Target {
args.push("--depends", dep)
}

use(packager.metadata.license || packager.devMetadata.license, it => args.push("--license", it!))
use(packager.appInfo.metadata.license || packager.devMetadata.license, it => args.push("--license", it!))
use(appInfo.buildNumber, it => args.push("--iteration", it!))

use(options.fpm, it => args.push(...<any>it))

args.push(`${appOutDir}/=${installPrefix}/${appInfo.productName}`)
args.push(`${appOutDir}/=${installPrefix}/${appInfo.productFilename}`)
args.push(...<any>(await this.packageFiles)!)
await exec(await this.fpmPath, args)
}

private async computeDesktop(tempDir: string): Promise<Array<string>> {
const appInfo = this.packager.appInfo
const tempFile = path.join(tempDir, appInfo.productName + ".desktop")
const tempFile = path.join(tempDir, `${appInfo.productFilename}.desktop`)
await outputFile(tempFile, this.packager.platformSpecificBuildOptions.desktop || `[Desktop Entry]
Name=${appInfo.productName}
Comment=${this.packager.platformSpecificBuildOptions.description || appInfo.description}
Exec="${installPrefix}/${appInfo.productName}/${appInfo.productName}"
Exec="${installPrefix}/${appInfo.productFilename}/${appInfo.productFilename}"
Terminal=false
Type=Application
Icon=${appInfo.name}
`)
return [`${tempFile}=/usr/share/applications/${appInfo.productName}.desktop`]
return [`${tempFile}=/usr/share/applications/${appInfo.productFilename}.desktop`]
}

private async createFromIcns(tempDir: string): Promise<Array<string>> {
Expand Down
8 changes: 3 additions & 5 deletions src/targets/nsis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { Target } from "../platformPackager"
import { archiveApp } from "./archive"
import { subTask, task } from "../util/log"
import { unlink } from "fs-extra-p"
import sanitizeFileName = require("sanitize-filename")
import semver = require("semver")

//noinspection JSUnusedLocalSymbols
Expand Down Expand Up @@ -53,15 +52,14 @@ export default class NsisTarget extends Target {
const iconPath = await packager.getIconPath()
const appInfo = packager.appInfo
const version = appInfo.version
const installerPath = path.join(this.outDir, `${appInfo.productName} Setup ${version}.exe`)
const installerPath = path.join(this.outDir, `${appInfo.productFilename} Setup ${version}.exe`)

const guid = this.options.guid || await BluebirdPromise.promisify(uuid5)({namespace: ELECTRON_BUILDER_NS_UUID, name: appInfo.id})
const productName = appInfo.productName
const defines: any = {
APP_ID: appInfo.id,
APP_GUID: guid,
PRODUCT_NAME: productName,
INST_DIR_NAME: sanitizeFileName(productName),
PRODUCT_NAME: appInfo.productName,
INST_DIR_NAME: appInfo.productFilename,
APP_DESCRIPTION: appInfo.description,
VERSION: version,

Expand Down
6 changes: 3 additions & 3 deletions src/targets/squirrelWindows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default class SquirrelWindowsTarget extends Target {
const appInfo = this.packager.appInfo
const version = appInfo.version
const archSuffix = getArchSuffix(arch)
const setupFileName = `${appInfo.productName} Setup ${version}${archSuffix}.exe`
const setupFileName = `${appInfo.productFilename} Setup ${version}${archSuffix}.exe`

const installerOutDir = path.join(appOutDir, "..", `win${getArchSuffix(arch)}`)
await emptyDir(installerOutDir)
Expand All @@ -45,7 +45,7 @@ export default class SquirrelWindowsTarget extends Target {
const packager = this.packager
let iconUrl = packager.platformSpecificBuildOptions.iconUrl || packager.devMetadata.build.iconUrl
if (iconUrl == null) {
const info = await getRepositoryInfo(packager.metadata, packager.devMetadata)
const info = await getRepositoryInfo(packager.appInfo.metadata, packager.devMetadata)
if (info != null) {
iconUrl = `https://github.com/${info.user}/${info.project}/blob/master/${packager.relativeBuildResourcesDirname}/icon.ico?raw=true`
}
Expand All @@ -69,7 +69,7 @@ export default class SquirrelWindowsTarget extends Target {
const options: any = Object.assign({
name: appInfo.name,
productName: appInfo.productName,
exe: `${appInfo.productName}.exe`,
exe: `${appInfo.productFilename}.exe`,
setupExe: setupExeName,
msiExe: setupExeName.replace(".exe", ".msi"),
title: appInfo.productName,
Expand Down
2 changes: 1 addition & 1 deletion src/winPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
const packOptions = await this.computePackOptions(outDir, appOutDir, arch)

await this.doPack(packOptions, outDir, appOutDir, arch, this.platformSpecificBuildOptions)
await this.sign(path.join(appOutDir, `${this.appInfo.productName}.exe`))
await this.sign(path.join(appOutDir, `${this.appInfo.productFilename}.exe`))
this.packageInDistributableFormat(outDir, appOutDir, arch, targets, postAsyncTasks)
}

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
@@ -1,7 +1,7 @@
{
"private": true,
"name": "TestApp",
"productName": "Test App",
"productName": "Test App A/B",
"version": "1.1.0",
"homepage": "http://foo.example.com",
"description": "Test Application (test quite \" #378)",
Expand Down
2 changes: 1 addition & 1 deletion test/src/globTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ test("extraResources", async () => {
packed: async (projectDir) => {
const base = path.join(projectDir, outDirName, platform.buildConfigurationKey)
let resourcesDir = path.join(base, "resources")
if (platform === Platform.OSX) {
if (platform === Platform.MAC) {
resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources")
}
else if (platform === Platform.WINDOWS) {
Expand Down
26 changes: 12 additions & 14 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions
}

const nameToTarget = platformToTarget.get(platform)
if (platform === Platform.OSX) {
await checkOsXResult(packager, packagerOptions, checkOptions, artifacts.get(Platform.OSX))
if (platform === Platform.MAC) {
await checkOsXResult(packager, packagerOptions, checkOptions, artifacts.get(Platform.MAC))
}
else if (platform === Platform.LINUX) {
await checkLinuxResult(projectDir, packager, checkOptions, artifacts.get(Platform.LINUX), arch)
Expand Down Expand Up @@ -196,11 +196,10 @@ function parseDebControl(info: string): any {

async function checkOsXResult(packager: Packager, packagerOptions: PackagerOptions, checkOptions: AssertPackOptions, artifacts: Array<ArtifactCreated>) {
const appInfo = packager.appInfo
const productName = appInfo.productName
const packedAppDir = path.join(path.dirname(artifacts[0].file), (productName || packager.metadata.name) + ".app")
const packedAppDir = path.join(path.dirname(artifacts[0].file), `${appInfo.productFilename}.app`)
const info = parsePlist(await readFile(path.join(packedAppDir, "Contents", "Info.plist"), "utf8"))
assertThat2(info).has.properties({
CFBundleDisplayName: productName,
CFBundleDisplayName: appInfo.productName,
CFBundleIdentifier: "org.electron-builder.testApp",
LSApplicationCategoryType: "your.app.category.type",
CFBundleVersion: `${appInfo.version}.${(process.env.TRAVIS_BUILD_NUMBER || process.env.CIRCLE_BUILD_NUM)}`
Expand All @@ -217,8 +216,8 @@ async function checkOsXResult(packager: Packager, packagerOptions: PackagerOptio
}
else {
assertThat(actualFiles).isEqualTo([
`${productName}-${appInfo.version}-mac.zip`,
`${productName}-${appInfo.version}.dmg`,
`${appInfo.productFilename}-${appInfo.version}-mac.zip`,
`${appInfo.productFilename}-${appInfo.version}.dmg`,
].sort())

assertThat(artifacts.map(it => it.artifactName).sort()).isEqualTo([
Expand All @@ -234,7 +233,6 @@ function getFileNames(list: Array<ArtifactCreated>): Array<string> {

async function checkWindowsResult(packager: Packager, checkOptions: AssertPackOptions, artifacts: Array<ArtifactCreated>, arch: Arch, nameToTarget: Map<String, Target>) {
const appInfo = packager.appInfo
const productName = appInfo.productName
let squirrel = false

const artifactNames: Array<string> = []
Expand All @@ -244,7 +242,7 @@ async function checkWindowsResult(packager: Packager, checkOptions: AssertPackOp
for (let target of nameToTarget.keys()) {
if (target === "squirrel") {
squirrel = true
expectedFileNames.push("RELEASES", `${productName} Setup ${appInfo.version}${archSuffix}.exe`, `${appInfo.name}-${convertVersion(appInfo.version)}-full.nupkg`)
expectedFileNames.push("RELEASES", `${appInfo.productFilename} Setup ${appInfo.version}${archSuffix}.exe`, `${appInfo.name}-${convertVersion(appInfo.version)}-full.nupkg`)

if (buildOptions != null && buildOptions.remoteReleases != null) {
expectedFileNames.push(`${appInfo.name}-${convertVersion(appInfo.version)}-delta.nupkg`)
Expand All @@ -253,11 +251,11 @@ async function checkWindowsResult(packager: Packager, checkOptions: AssertPackOp
artifactNames.push(`${appInfo.name}-Setup-${appInfo.version}${archSuffix}.exe`)
}
else if (target === "nsis") {
expectedFileNames.push(`${productName} Setup ${appInfo.version}.exe`)
expectedFileNames.push(`${appInfo.productFilename} Setup ${appInfo.version}.exe`)
artifactNames.push(`${appInfo.name}-Setup-${appInfo.version}.exe`)
}
else {
expectedFileNames.push(`${productName}-${appInfo.version}${archSuffix}-win.${target}`)
expectedFileNames.push(`${appInfo.productFilename}-${appInfo.version}${archSuffix}-win.${target}`)
artifactNames.push(`${appInfo.name}-${appInfo.version}${archSuffix}-win.${target}`)
}
}
Expand All @@ -280,7 +278,7 @@ async function checkWindowsResult(packager: Packager, checkOptions: AssertPackOp
const expectedContents = checkOptions == null || checkOptions.expectedContents == null ? expectedWinContents : checkOptions.expectedContents
assertThat(files).isEqualTo(expectedContents.map(it => {
if (it === "lib/net45/TestApp.exe") {
return `lib/net45/${encodeURI(productName)}.exe`
return `lib/net45/${encodeURI(appInfo.productFilename)}.exe`
}
else {
return it
Expand All @@ -298,7 +296,7 @@ async function checkWindowsResult(packager: Packager, checkOptions: AssertPackOp
<metadata>
<id>TestApp</id>
<version>${convertVersion(appInfo.version)}</version>
<title>${productName}</title>
<title>${appInfo.productName}</title>
<authors>Foo Bar</authors>
<owners>Foo Bar</owners>
<iconUrl>https://raw.githubusercontent.com/szwacz/electron-boilerplate/master/resources/windows/icon.ico</iconUrl>
Expand Down Expand Up @@ -343,7 +341,7 @@ export function signed(packagerOptions: PackagerOptions): PackagerOptions {

export function getPossiblePlatforms(type?: string): Map<Platform, Map<Arch, string[]>> {
const platforms = [Platform.fromString(process.platform)]
if (process.platform === Platform.OSX.nodeName) {
if (process.platform === Platform.MAC.nodeName) {
if (process.env.LINUX_SKIP == null) {
platforms.push(Platform.LINUX)
}
Expand Down
Loading

0 comments on commit 726e574

Please sign in to comment.