Skip to content

Commit

Permalink
fix: zip, dmg and exe filenames do not use productName as intended
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Mar 23, 2016
1 parent 5eea750 commit bfca0a7
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 77 deletions.
4 changes: 2 additions & 2 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ export async function build(options: BuildOptions = {}): Promise<void> {
const packager = new Packager(options, repositoryInfo)
if (options.publish != null && options.publish !== "never") {
let publisher: BluebirdPromise<Publisher> = null
packager.artifactCreated((file, platform) => {
packager.artifactCreated(event => {
if (publisher == null) {
publisher = <BluebirdPromise<Publisher>>createPublisher(packager, options, repositoryInfo, isPublishOptionGuessed)
}

if (publisher != null) {
publisher.then(it => publishTasks.push(<BluebirdPromise<any>>it.upload(file)))
publisher.then(it => publishTasks.push(<BluebirdPromise<any>>it.upload(event.file, event.artifactName)))
}
})
}
Expand Down
10 changes: 5 additions & 5 deletions src/gitHubPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import ProgressBar = require("progress")
const __awaiter = require("./awaiter")

export interface Publisher {
upload(path: string): Promise<any>
upload(file: string, artifactName?: string): Promise<any>
}

export interface PublishOptions {
Expand Down Expand Up @@ -66,15 +66,15 @@ export class GitHubPublisher implements Publisher {
}
}

async upload(path: string): Promise<void> {
const fileName = basename(path)
async upload(file: string, artifactName?: string): Promise<void> {
const fileName = artifactName || basename(file)
const release = await this.releasePromise
if (release == null) {
return null
}

const parsedUrl = parseUrl(release.upload_url.substring(0, release.upload_url.indexOf("{")) + "?name=" + fileName)
const fileStat = await stat(path)
const fileStat = await stat(file)
let badGatewayCount = 0
uploadAttempt: for (let i = 0; i < 3; i++) {
const progressBar = (<ReadStream>process.stdin).isTTY ? new ProgressBar(`Uploading ${fileName} [:bar] :percent :etas`, {
Expand All @@ -96,7 +96,7 @@ export class GitHubPublisher implements Publisher {
"Content-Length": fileStat.size
}
}, this.token, (request, reject) => {
const fileInputStream = createReadStream(path)
const fileInputStream = createReadStream(file)
fileInputStream.on("error", reject)
fileInputStream
.pipe(progressStream({
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { Packager } from "./packager"
export { PackagerOptions } from "./platformPackager"
export { PackagerOptions, ArtifactCreated } from "./platformPackager"
export { AppMetadata, DevMetadata, Platform, getProductName } from "./metadata"
9 changes: 5 additions & 4 deletions src/macPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default class MacPackager extends PlatformPackager<OsXBuildOptions> {
}

packageInDistributableFormat(outDir: string, appOutDir: string): Promise<any> {
const artifactPath = path.join(appOutDir, this.metadata.name + "-" + this.metadata.version + ".dmg")
const artifactPath = path.join(appOutDir, `${this.appName}-${this.metadata.version}.dmg`)
return BluebirdPromise.all([
new BluebirdPromise<any>((resolve, reject) => {
log("Creating DMG")
Expand Down Expand Up @@ -83,17 +83,18 @@ export default class MacPackager extends PlatformPackager<OsXBuildOptions> {
emitter.on("error", reject)
emitter.on("finish", () => resolve())
})
.then(() => this.dispatchArtifactCreated(artifactPath)),
.then(() => this.dispatchArtifactCreated(artifactPath, `${this.metadata.name}-${this.metadata.version}.dmg`)),

this.zipMacApp(appOutDir)
.then(it => this.dispatchArtifactCreated(it))
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-${this.metadata.version}-mac.zip`))
])
}

private zipMacApp(outDir: string): Promise<string> {
log("Creating ZIP for Squirrel.Mac")
// we use app name here - see https://github.com/electron-userland/electron-builder/pull/204
const resultPath = `${this.appName}-${this.metadata.version}-mac.zip`
// -y param is important - "store symbolic links as the link instead of the referenced file"
const resultPath = `${this.metadata.name}-${this.metadata.version}-mac.zip`
const args = ["-ryXq", resultPath, this.appName + ".app"]

// todo move to options
Expand Down
6 changes: 3 additions & 3 deletions src/packager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { all, executeFinally } from "./promise"
import { EventEmitter } from "events"
import { Promise as BluebirdPromise } from "bluebird"
import { InfoRetriever } from "./repositoryInfo"
import { AppMetadata, Platform, DevMetadata } from "./metadata"
import { PackagerOptions, PlatformPackager, BuildInfo } from "./platformPackager"
import { AppMetadata, DevMetadata } from "./metadata"
import { PackagerOptions, PlatformPackager, BuildInfo, ArtifactCreated } from "./platformPackager"
import MacPackager from "./macPackager"
import WinPackager from "./winPackager"
import * as errorMessages from "./errorMessages"
Expand Down Expand Up @@ -38,7 +38,7 @@ export class Packager implements BuildInfo {
this.appDir = this.computeAppDirectory()
}

artifactCreated(handler: (file: string, platform: Platform) => void): Packager {
artifactCreated(handler: (event: ArtifactCreated) => void): Packager {
addHandler(this.eventEmitter, "artifactCreated", handler)
return this
}
Expand Down
15 changes: 13 additions & 2 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
return (directories == null ? null : directories.buildResources) || "build"
}

protected dispatchArtifactCreated(file: string) {
this.info.eventEmitter.emit("artifactCreated", file, this.platform)
protected dispatchArtifactCreated(file: string, artifactName?: string) {
this.info.eventEmitter.emit("artifactCreated", {
file: file,
artifactName: artifactName,
platform: this.platform,
})
}

async pack(platform: string, outDir: string, appOutDir: string, arch: string): Promise<any> {
Expand Down Expand Up @@ -155,4 +159,11 @@ function checkConflictingOptions(options: any): void {
throw new Error(`Option ${name} is ignored, do not specify it.`)
}
}
}

export interface ArtifactCreated {
readonly file: string
readonly artifactName?: string

readonly platform: Platform
}
6 changes: 2 additions & 4 deletions src/winPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ export default class WinPackager extends PlatformPackager<WinBuildOptions> {
noMsi: true,
}, this.customBuildOptions)

// we use metadata.name instead of appName because appName can contains unsafe chars
const installerExePath = path.join(installerOutDir, this.metadata.name + "Setup-" + version + archSuffix + ".exe")
try {
await require("electron-winstaller-fixed").createWindowsInstaller(options)
}
Expand Down Expand Up @@ -141,8 +139,8 @@ export default class WinPackager extends PlatformPackager<WinBuildOptions> {
}

const promises: Array<Promise<any>> = [
rename(path.join(installerOutDir, "Setup.exe"), installerExePath)
.then(it => this.dispatchArtifactCreated(it)),
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
122 changes: 66 additions & 56 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { parse as parsePlist } from "plist"
import { CSC_LINK, CSC_KEY_PASSWORD } from "./codeSignData"
import { expectedLinuxContents } from "./expectedContents"
import { readText } from "out/promisifed-fs"
import { Packager, PackagerOptions, Platform, getProductName } from "out"
import { Packager, PackagerOptions, Platform, getProductName, ArtifactCreated } from "out"
import { normalizePlatforms } from "out/packager"
import { exec } from "out/util"
import pathSorter = require("path-sort")
Expand Down Expand Up @@ -73,15 +73,15 @@ export async function assertPack(fixtureName: string,
async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions): Promise<void> {
const packager = new Packager(packagerOptions)

const artifacts: Map<Platform, Array<string>> = new Map()
packager.artifactCreated((file, platform) => {
assertThat(path.isAbsolute(file)).true()
let list = artifacts.get(platform)
const artifacts: Map<Platform, Array<ArtifactCreated>> = new Map()
packager.artifactCreated(event => {
assertThat(path.isAbsolute(event.file)).true()
let list = artifacts.get(event.platform)
if (list == null) {
list = []
artifacts.set(platform, list)
artifacts.set(event.platform, list)
}
list.push(file)
list.push(event)
})

await packager.build()
Expand All @@ -90,44 +90,41 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions
return
}

for (let key of artifacts.keys()) {
artifacts.set(key, pathSorter(artifacts.get(key)))
}

const expandedPlatforms = normalizePlatforms(packagerOptions.platform)
if (expandedPlatforms.includes("darwin")) {
await checkOsXResult(packager, artifacts.get(Platform.OSX))
}
else if (expandedPlatforms.includes("linux")) {
const productName = getProductName(packager.metadata, packager.devMetadata)
const expectedContents = expectedLinuxContents.map(it => {
if (it === "/opt/TestApp/TestApp") {
return "/opt/" + productName + "/" + productName
}
else if (it === "/usr/share/applications/TestApp.desktop") {
return `/usr/share/applications/${productName}.desktop`
}
else {
return it.replace(new RegExp("/opt/TestApp/", "g"), `/opt/${productName}/`)
for (let platform of normalizePlatforms(packagerOptions.platform)) {
if (platform === "darwin") {
await checkOsXResult(packager, artifacts.get(Platform.OSX))
}
else if (platform === "linux") {
const productName = getProductName(packager.metadata, packager.devMetadata)
const expectedContents = expectedLinuxContents.map(it => {
if (it === "/opt/TestApp/TestApp") {
return "/opt/" + productName + "/" + productName
}
else if (it === "/usr/share/applications/TestApp.desktop") {
return `/usr/share/applications/${productName}.desktop`
}
else {
return it.replace(new RegExp("/opt/TestApp/", "g"), `/opt/${productName}/`)
}
})

// 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))

assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb", productName)).deepEqual(expectedContents)
if (packagerOptions == null || packagerOptions.arch === null || packagerOptions.arch === "ia32") {
assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName)).deepEqual(expectedContents)
}
})

// 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))

assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb", productName)).deepEqual(expectedContents)
if (packagerOptions == null || packagerOptions.arch === null || packagerOptions.arch === "ia32") {
assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName)).deepEqual(expectedContents)
}
}
else if (expandedPlatforms.includes("win32") && (packagerOptions == null || packagerOptions.target == null)) {
await checkWindowsResult(packagerOptions, artifacts.get(Platform.WINDOWS))
else if (platform === "win32" && (packagerOptions == null || packagerOptions.target == null)) {
await checkWindowsResult(packager, packagerOptions, artifacts.get(Platform.WINDOWS))
}
}
}

async function checkOsXResult(packager: Packager, artifacts: Array<string>) {
async function checkOsXResult(packager: Packager, artifacts: Array<ArtifactCreated>) {
const productName = getProductName(packager.metadata, packager.devMetadata)
const packedAppDir = path.join(path.dirname(artifacts[0]), (productName || packager.metadata.name) + ".app")
const packedAppDir = path.join(path.dirname(artifacts[0].file), (productName || packager.metadata.name) + ".app")
const info = parsePlist(await readText(path.join(packedAppDir, "Contents", "Info.plist")))
assertThat(info).has.properties({
CFBundleDisplayName: productName,
Expand All @@ -139,30 +136,43 @@ async function checkOsXResult(packager: Packager, artifacts: Array<string>) {
const result = await exec("codesign", ["--verify", packedAppDir])
assertThat(result[0].toString()).not.match(/is not signed at all/)

assertThat(artifacts.map(it => path.basename((it))).sort()).deepEqual([
assertThat(artifacts.map(it => path.basename(it.file)).sort()).deepEqual([
`${productName}-1.0.0-mac.zip`,
`${productName}-1.0.0.dmg`,
].sort())

assertThat(artifacts.map(it => it.artifactName).sort()).deepEqual([
"TestApp-1.0.0-mac.zip",
"TestApp-1.0.0.dmg"
"TestApp-1.0.0.dmg",
].sort())
}

async function checkWindowsResult(packagerOptions: PackagerOptions, artifacts: Array<string>) {
const expected32 = [
"RELEASES-ia32",
"TestAppSetup-1.0.0-ia32.exe",
"TestApp-1.0.0-ia32-full.nupkg",
]
const expected64 = [
"RELEASES",
"TestAppSetup-1.0.0.exe",
"TestApp-1.0.0-full.nupkg",
]
const expected = packagerOptions != null && packagerOptions.arch === "x64" ? expected64 : expected32.concat(expected64)
const filenames = artifacts.map(it => path.basename((it)))
assertThat(filenames.slice().sort()).deepEqual(expected.sort())
async function checkWindowsResult(packager: Packager, packagerOptions: PackagerOptions, artifacts: Array<ArtifactCreated>) {
const productName = getProductName(packager.metadata, packager.devMetadata)

function getWinExpected(archSuffix: string) {
return [
`RELEASES${archSuffix}`,
`${productName}Setup-1.0.0${archSuffix}.exe`,
`TestApp-1.0.0${archSuffix}-full.nupkg`,
]
}

const archSuffix = packagerOptions != null && packagerOptions.arch === "x64" ? "" : "-ia32"
const expected = archSuffix == "" ? getWinExpected(archSuffix) : getWinExpected(archSuffix).concat(getWinExpected(""))

const filenames = artifacts.map(it => path.basename(it.file))
assertThat(filenames.slice().sort()).deepEqual(expected.slice().sort())

let i = filenames.indexOf("RELEASES-ia32")
if (i !== -1) {
assertThat((await readText(artifacts[i])).indexOf("ia32")).not.equal(-1)
assertThat((await readText(artifacts[i].file)).indexOf("ia32")).not.equal(-1)
}

if (archSuffix == "") {
const expectedArtifactNames = expected.slice()
expectedArtifactNames[1] = `TestAppSetup-1.0.0${archSuffix}.exe`
assertThat(artifacts.map(it => it.artifactName).filter(it => it != null)).deepEqual([`TestAppSetup-1.0.0${archSuffix}.exe`])
}
}

Expand Down

0 comments on commit bfca0a7

Please sign in to comment.