Skip to content

Commit

Permalink
feat: Ability to customize the output directory
Browse files Browse the repository at this point in the history
Closes #272
  • Loading branch information
develar committed Apr 9, 2016
1 parent 422a032 commit 78bddc7
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 34 deletions.
13 changes: 7 additions & 6 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Here documented only `electron-builder` specific options:
# Application `package.json`
| Name | Description
| --- | ---
| name | <a name="AppMetadata-name"></a>The application name.
| **name** | <a name="AppMetadata-name"></a>The application name.
| productName | <a name="AppMetadata-productName"></a><p>As [name](#AppMetadata-name), but allows you to specify a product name for your executable which contains spaces and other special characters not allowed in the [name property](https://docs.npmjs.com/files/package.json#name}).</p>

<a name="DevMetadata"></a>
Expand All @@ -42,16 +42,16 @@ Here documented only `electron-builder` specific options:
| --- | ---
| homepage | <a name="DevMetadata-homepage"></a><p>The url to the project [homepage](https://docs.npmjs.com/files/package.json#homepage) (NuGet Package <code>projectUrl</code> (optional) or Linux Package URL (required)).</p> <p>If not specified and your project repository is public on GitHub, it will be <code>https://github.com/${user}/${project}</code> by default.</p>
| license | <a name="DevMetadata-license"></a>*linux-only.* The [license](https://docs.npmjs.com/files/package.json#license) name for this package.
| build | <a name="DevMetadata-build"></a>See [.build](#BuildMetadata).
| **build** | <a name="DevMetadata-build"></a>See [.build](#BuildMetadata).
| directories | <a name="DevMetadata-directories"></a>See [.directories](#MetadataDirectories)

<a name="BuildMetadata"></a>
## `.build`
| Name | Description
| --- | ---
| app-bundle-id | <a name="BuildMetadata-app-bundle-id"></a>The bundle identifier to use in the application's plist.
| app-category-type | <a name="BuildMetadata-app-category-type"></a><p>The application category type, as shown in the Finder via *View -&gt; Arrange by Application Category* when viewing the Applications directory.</p> <p>For example, <code>app-category-type=public.app-category.developer-tools</code> will set the application category to *Developer Tools*.</p> <p>Valid values are listed in [Apple’s documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/TP40009250-SW8).</p>
| iconUrl | <a name="BuildMetadata-iconUrl"></a><p>*windows-only.* A URL to an ICO file to use as the application icon (displayed in Control Panel &gt; Programs and Features). Defaults to the Atom icon.</p> <p>Please note — [local icon file url is not accepted](https://github.com/atom/grunt-electron-installer/issues/73), must be https/http.</p> <ul> <li>If you don’t plan to build windows installer, you can omit it.</li> <li>If your project repository is public on GitHub, it will be <code>https://raw.githubusercontent.com/${user}/${project}/master/build/icon.ico</code> by default.</li> </ul>
| **app-bundle-id** | <a name="BuildMetadata-app-bundle-id"></a>The bundle identifier to use in the application's plist.
| **app-category-type** | <a name="BuildMetadata-app-category-type"></a><p>The application category type, as shown in the Finder via *View -&gt; Arrange by Application Category* when viewing the Applications directory.</p> <p>For example, <code>app-category-type=public.app-category.developer-tools</code> will set the application category to *Developer Tools*.</p> <p>Valid values are listed in [Apple’s documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/TP40009250-SW8).</p>
| **iconUrl** | <a name="BuildMetadata-iconUrl"></a><p>*windows-only.* A URL to an ICO file to use as the application icon (displayed in Control Panel &gt; Programs and Features). Defaults to the Electron icon.</p> <p>Please note — [local icon file url is not accepted](https://github.com/atom/grunt-electron-installer/issues/73), must be https/http.</p> <ul> <li>If you don’t plan to build windows installer, you can omit it.</li> <li>If your project repository is public on GitHub, it will be <code>https://raw.githubusercontent.com/${user}/${project}/master/build/icon.ico</code> by default.</li> </ul>
| productName | <a name="BuildMetadata-productName"></a>See [AppMetadata.productName](#AppMetadata-productName).
| extraResources | <a name="BuildMetadata-extraResources"></a><p>A [glob expression](https://www.npmjs.com/package/glob#glob-primer), when specified, copy the file or directory with matching names directly into the app’s directory (<code>Contents/Resources</code> for OS X).</p> <p>You can use <code>${os}</code> (expanded to osx, linux or win according to current platform) and <code>${arch}</code> in the pattern.</p> <p>If directory matched, all contents are copied. So, you can just specify <code>foo</code> to copy <code>&lt;project_dir&gt;/foo</code> directory.</p> <p>May be specified in the platform options (i.e. in the <code>build.osx</code>).</p>
| osx | <a name="BuildMetadata-osx"></a>See [.build.osx](#OsXBuildOptions).
Expand All @@ -73,12 +73,13 @@ See all [appdmg options](https://www.npmjs.com/package/appdmg#json-specification
### `.build.linux`
| Name | Description
| --- | ---
| compression | <a name="LinuxBuildOptions-compression"></a>*deb-only.* The compression type, one of `gz`, `bzip2`, `xz`. (default: `xz`).
| compression | <a name="LinuxBuildOptions-compression"></a>*deb-only.* The compression type, one of `gz`, `bzip2`, `xz` (default: `xz`).

<a name="MetadataDirectories"></a>
## `.directories`
| Name | Description
| --- | ---
| buildResources | <a name="MetadataDirectories-buildResources"></a>The path to build resources, default `build`.
| output | <a name="MetadataDirectories-output"></a>The output directory, default `dist`.

<!-- end of generated block -->
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@
"pre-commit": "^1.1.2",
"semantic-release": "^4.3.5",
"should": "^8.3.0",
"ts-babel": "^0.6.9",
"ts-babel": "^0.7.0",
"tsconfig-glob": "^0.4.3",
"tslint": "next",
"typescript": "^1.9.0-dev.20160408",
"typescript": "1.9.0-dev.20160409",
"validate-commit-msg": "^2.5.0"
},
"babel": {
Expand Down
8 changes: 1 addition & 7 deletions src/linuxPackager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
import { PlatformPackager, BuildInfo } from "./platformPackager"
import { PlatformPackager, BuildInfo, use } from "./platformPackager"
import { Platform, LinuxBuildOptions } from "./metadata"
import { dir as _tpmDir, TmpOptions } from "tmp"
import { exec, log } from "./util"
Expand Down Expand Up @@ -199,12 +199,6 @@ Icon=${this.metadata.name}
}
}

function use<T>(value: T, task: (it: T) => void) {
if (value != null) {
task(value)
}
}

async function writeConfigFile(tempDir: string, templatePath: string, options: any): Promise<string> {
const config = template(await readFile(templatePath, "utf8"),
{
Expand Down
9 changes: 7 additions & 2 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export interface BuildMetadata {
readonly "app-category-type": string

/*
*windows-only.* A URL to an ICO file to use as the application icon (displayed in Control Panel > Programs and Features). Defaults to the Atom icon.
*windows-only.* A URL to an ICO file to use as the application icon (displayed in Control Panel > Programs and Features). Defaults to the Electron icon.
Please note — [local icon file url is not accepted](https://github.com/atom/grunt-electron-installer/issues/73), must be https/http.
Expand Down Expand Up @@ -157,7 +157,7 @@ export interface LinuxBuildOptions {
afterRemove?: string

/*
*deb-only.* The compression type, one of `gz`, `bzip2`, `xz`. (default: `xz`).
*deb-only.* The compression type, one of `gz`, `bzip2`, `xz` (default: `xz`).
*/
readonly compression?: string
}
Expand All @@ -170,6 +170,11 @@ export interface MetadataDirectories {
The path to build resources, default `build`.
*/
readonly buildResources?: string

/*
The output directory, default `dist`.
*/
readonly output?: string
}

export interface PlatformSpecificBuildOptions {
Expand Down
6 changes: 3 additions & 3 deletions src/packager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { EventEmitter } from "events"
import { Promise as BluebirdPromise } from "bluebird"
import { InfoRetriever } from "./repositoryInfo"
import { AppMetadata, DevMetadata } from "./metadata"
import { PackagerOptions, PlatformPackager, BuildInfo, ArtifactCreated } from "./platformPackager"
import { PackagerOptions, PlatformPackager, BuildInfo, ArtifactCreated, use } from "./platformPackager"
import MacPackager from "./macPackager"
import WinPackager from "./winPackager"
import * as errorMessages from "./errorMessages"
Expand Down Expand Up @@ -65,12 +65,12 @@ export class Packager implements BuildInfo {

private async doBuild(platforms: Array<string>, cleanupTasks: Array<() => Promise<any>>): Promise<any> {
const distTasks: Array<Promise<any>> = []
const outDir = path.resolve(this.projectDir, use(this.devMetadata.directories, it => it.output) || "dist")

for (let platform of platforms) {
const helper = this.createHelper(platform, cleanupTasks)
for (let arch of normalizeArchs(platform, this.options.arch)) {
await this.installAppDependencies(arch)

const outDir = path.join(this.projectDir, "dist")
// electron-packager uses productName in the directory name
const appOutDir = path.join(outDir, helper.appName + "-" + platform + "-" + arch)
await helper.pack(outDir, appOutDir, arch)
Expand Down
10 changes: 6 additions & 4 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>

this.buildResourcesDir = path.resolve(this.projectDir, this.relativeBuildResourcesDirname)

const buildMetadata: any = info.devMetadata.build
this.customBuildOptions = buildMetadata == null ? buildMetadata : buildMetadata[this.platform.buildConfigurationKey]
this.customBuildOptions = (<any>info.devMetadata.build)[this.platform.buildConfigurationKey]

this.appName = getProductName(this.metadata, this.devMetadata)
}

protected get relativeBuildResourcesDirname() {
const directories = this.devMetadata.directories
return (directories == null ? null : directories.buildResources) || "build"
return use(this.devMetadata.directories, it => it.buildResources) || "build"
}

protected dispatchArtifactCreated(file: string, artifactName?: string) {
Expand Down Expand Up @@ -197,4 +195,8 @@ export interface ArtifactCreated {
readonly artifactName?: string

readonly platform: Platform
}

export function use<T, R>(value: T, task: (it: T) => R): R {
return value == null ? null : task(value)
}
20 changes: 16 additions & 4 deletions test/src/BuildTest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from "./helpers/avaEx"
import { assertPack, modifyPackageJson } from "./helpers/packTester"
import { assertPack, modifyPackageJson, outDirName } from "./helpers/packTester"
import { move, outputFile, outputJson } from "fs-extra-p"
import { Promise as BluebirdPromise } from "bluebird"
import * as path from "path"
Expand All @@ -20,6 +20,17 @@ test("custom buildResources dir", () => assertPack("test-app-one", allPlatformsA
])
}))

test("custom output dir", () => assertPack("test-app-one", allPlatformsAndCurrentArch(false), {
tempDirCreated: projectDir => modifyPackageJson(projectDir, data => {
data.directories = {
output: "customDist"
}
}),
packed: async (projectDir) => {
await assertThat(path.join(projectDir, "customDist")).isDirectory()
}
}))

test("productName with space", () => assertPack("test-app-one", allPlatformsAndCurrentArch(), {
tempDirCreated: projectDir => modifyPackageJson(projectDir, data => {
data.productName = "Test App"
Expand Down Expand Up @@ -87,8 +98,8 @@ test("copy extra resource", async () => {
outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"),
])
},
packed: async(projectDir) => {
let resourcesDir = path.join(projectDir, "dist", "TestApp-" + platform + "-" + process.arch)
packed: async (projectDir) => {
let resourcesDir = path.join(projectDir, outDirName, "TestApp-" + platform + "-" + process.arch)
if (platform === "darwin") {
resourcesDir = path.join(resourcesDir, "TestApp.app", "Contents", "Resources")
}
Expand Down Expand Up @@ -135,9 +146,10 @@ test("copy extra resource", async () => {
}
})

function allPlatformsAndCurrentArch(): PackagerOptions {
function allPlatformsAndCurrentArch(dist: boolean = true): PackagerOptions {
return {
platform: getPossiblePlatforms(),
dist: dist
}
}

Expand Down
3 changes: 1 addition & 2 deletions test/src/helpers/fileAssert.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { stat } from "fs-extra-p"
import { AssertionError } from "assert"

//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")
Expand All @@ -22,7 +21,7 @@ class FileAssertions {
async isDirectory() {
const info = await stat(this.path)
if (!info.isDirectory()) {
throw new Error(`Path ${this.path} is not a file`)
throw new Error(`Path ${this.path} is not a directory`)
}
}

Expand Down
9 changes: 5 additions & 4 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { exec } from "out/util"
import pathSorter = require("path-sort")
import { tmpdir } from "os"
import DecompressZip = require("decompress-zip")
import { Promise as BluebirdPromise } from "bluebird"

//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")
Expand All @@ -24,6 +23,8 @@ if (process.env.TRAVIS !== "true") {
process.env.CIRCLE_BUILD_NUM = 42
}

export const outDirName = "dist"

interface AssertPackOptions {
readonly tempDirCreated?: (projectDir: string) => Promise<any>
readonly packed?: (projectDir: string) => Promise<any>
Expand All @@ -47,7 +48,7 @@ export async function assertPack(fixtureName: string, packagerOptions: PackagerO
await copy(projectDir, dir, {
filter: it => {
const basename = path.basename(it)
return basename !== "dist" && basename !== "node_modules" && basename[0] !== "."
return basename !== outDirName && basename !== "node_modules" && basename[0] !== "."
}
})
projectDir = dir
Expand Down Expand Up @@ -131,10 +132,10 @@ async function checkLinuxResult(projectDir: string, packager: Packager, packager
// 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 + "/dist/TestApp-1.1.0-amd64.deb"
const packageFile = `${projectDir}/${outDirName}/TestApp-1.1.0-amd64.deb`
assertThat(await getContents(packageFile, productName)).deepEqual(expectedContents)
if (packagerOptions.arch === "all" || packagerOptions.arch === "ia32") {
assertThat(await getContents(projectDir + "/dist/TestApp-1.1.0-i386.deb", productName)).deepEqual(expectedContents)
assertThat(await getContents(`${projectDir}/${outDirName}/TestApp-1.1.0-i386.deb`, productName)).deepEqual(expectedContents)
}

const regexp = /^ *(\w+): *(.+)$/gm
Expand Down

0 comments on commit 78bddc7

Please sign in to comment.