Skip to content

Commit

Permalink
feat: extraFiles
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `extraResources` copying files to `resources` on Linux/Windows, not to root directory as before. To copy to the root please use new option `extraFiles`.
  • Loading branch information
develar committed May 29, 2016
1 parent a5e4571 commit ca120e3
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 40 deletions.
3 changes: 2 additions & 1 deletion docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ Here documented only `electron-builder` specific options:
| app-category-type | <a name="BuildMetadata-app-category-type"></a><p>*OS X-only.* 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>
| asar | <a name="BuildMetadata-asar"></a><p>Whether to package the application’s source code into an archive, using [Electron’s archive format](https://github.com/electron/asar). Defaults to <code>true</code>. Reasons why you may want to disable this feature are described in [an application packaging tutorial in Electron’s documentation](http://electron.atom.io/docs/latest/tutorial/application-packaging/#limitations-on-node-api/).</p>
| 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>
| 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 resources directory (<code>Contents/Resources</code> for OS X, <code>resources</code> for Linux/Windows).</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>
| extraFiles | <a name="BuildMetadata-extraFiles"></a>The same as [extraResources](#BuildMetadata-extraResources) but copy into the app's content directory (`Contents` for OS X, `` for Linux/Windows).
| osx | <a name="BuildMetadata-osx"></a>See [.build.osx](#OsXBuildOptions).
| mas | <a name="BuildMetadata-mas"></a>See [.build.mas](#MasBuildOptions).
| win | <a name="BuildMetadata-win"></a>See [.build.win](#LinuxBuildOptions).
Expand Down
8 changes: 7 additions & 1 deletion src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export interface BuildMetadata {
readonly productName?: string | null

/**
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 (`Contents/Resources` for OS X).
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 resources directory (`Contents/Resources` for OS X, `resources` for Linux/Windows).
You can use `${os}` (expanded to osx, linux or win according to current platform) and `${arch}` in the pattern.
Expand All @@ -115,6 +115,11 @@ export interface BuildMetadata {
*/
readonly extraResources?: Array<string> | null

/**
The same as [extraResources](#BuildMetadata-extraResources) but copy into the app's content directory (`Contents` for OS X, `` for Linux/Windows).
*/
readonly extraFiles?: Array<string> | null

/*
See [.build.osx](#OsXBuildOptions).
*/
Expand Down Expand Up @@ -334,6 +339,7 @@ export interface MetadataDirectories {
}

export interface PlatformSpecificBuildOptions {
readonly extraFiles?: Array<string> | null
readonly extraResources?: Array<string> | null

readonly target?: Array<string> | null
Expand Down
32 changes: 17 additions & 15 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>

protected async doPack(options: ElectronPackagerOptions, outDir: string, appOutDir: string, arch: string, customBuildOptions: DC) {
await this.packApp(options, appOutDir)
await this.copyExtraResources(appOutDir, arch, customBuildOptions)
await this.copyExtraFiles(appOutDir, arch, customBuildOptions)
}

protected computePackOptions(outDir: string, appOutDir: string, arch: string): ElectronPackagerOptions {
Expand Down Expand Up @@ -210,31 +210,33 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
await this.sanityCheckPackage(appOutDir, <boolean>options.asar)
}

private getExtraResources(arch: string, customBuildOptions: DC): Promise<Array<string>> {
private getExtraResources(isResources: boolean, arch: string, customBuildOptions: DC): Promise<Array<string>> {
const buildMetadata: any = this.devMetadata.build
let extraResources: Array<string> | n = buildMetadata == null ? null : buildMetadata.extraResources
let extra: Array<string> | n = buildMetadata == null ? null : buildMetadata[isResources ? "extraResources" : "extraFiles"]

const platformSpecificExtraResources = customBuildOptions.extraResources
if (platformSpecificExtraResources != null) {
extraResources = extraResources == null ? platformSpecificExtraResources : extraResources.concat(platformSpecificExtraResources)
const platformSpecificExtra = isResources ? customBuildOptions.extraResources : customBuildOptions.extraFiles
if (platformSpecificExtra != null) {
extra = extra == null ? platformSpecificExtra : extra.concat(platformSpecificExtra)
}

if (extraResources == null) {
if (extra == null) {
return BluebirdPromise.resolve([])
}

const expandedPatterns = extraResources.map(it => it
const expandedPatterns = extra.map(it => it
.replace(/\$\{arch}/g, arch)
.replace(/\$\{os}/g, this.platform.buildConfigurationKey))
return globby(expandedPatterns, {cwd: this.projectDir})
}

protected async copyExtraResources(appOutDir: string, arch: string, customBuildOptions: DC): Promise<Array<string>> {
let resourcesDir = appOutDir
if (this.platform === Platform.OSX) {
resourcesDir = this.getOSXResourcesDir(appOutDir)
}
return await BluebirdPromise.map(await this.getExtraResources(arch, customBuildOptions), it => copy(path.join(this.projectDir, it), path.join(resourcesDir, it)))
protected async copyExtraFiles(appOutDir: string, arch: string, customBuildOptions: DC): Promise<any> {
await this.doCopyExtraFiles(true, appOutDir, arch, this.customBuildOptions)
await this.doCopyExtraFiles(false, appOutDir, arch, this.customBuildOptions)
}

private async doCopyExtraFiles(isResources: boolean, appOutDir: string, arch: string, customBuildOptions: DC): Promise<Array<string>> {
const base = isResources ? this.getResourcesDir(appOutDir) : this.platform === Platform.OSX ? path.join(appOutDir, `${this.appName}.app`, "Contents") : appOutDir
return await BluebirdPromise.map(await this.getExtraResources(isResources, arch, customBuildOptions), it => copy(path.join(this.projectDir, it), path.join(base, it)))
}

protected async computePackageUrl(): Promise<string | null> {
Expand All @@ -261,7 +263,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

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

private async statFileInPackage(resourcesDir: string, packageFile: string, isAsar: boolean): Promise<any> {
Expand Down
9 changes: 3 additions & 6 deletions src/winPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ const __awaiter = require("./awaiter")
export class WinPackager extends PlatformPackager<WinBuildOptions> {
certFilePromise: Promise<string | null>

loadingGifStat: Promise<string> | null

readonly iconPath: Promise<string>

constructor(info: BuildInfo, cleanupTasks: Array<() => Promise<any>>) {
Expand Down Expand Up @@ -67,12 +65,11 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {

const installerOut = computeDistOut(outDir, arch)
await BluebirdPromise.all([
this.packApp(packOptions, appOutDir),
this.doPack(packOptions, outDir, appOutDir, arch, this.customBuildOptions),
emptyDir(installerOut)
])

await this.copyExtraResources(appOutDir, arch, this.customBuildOptions)
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, installerOut!, arch, packOptions))
postAsyncTasks.push(this.packageInDistributableFormat(appOutDir, installerOut, arch, packOptions))
}

protected computeAppOutDir(outDir: string, arch: string): string {
Expand Down Expand Up @@ -162,7 +159,7 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
return options
}

protected async packageInDistributableFormat(outDir: string, appOutDir: string, installerOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
protected async packageInDistributableFormat(appOutDir: string, installerOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
const winstaller = require("electron-winstaller-fixed")
const version = this.metadata.version
const archSuffix = arch === "x64" ? "" : ("-" + arch)
Expand Down
35 changes: 19 additions & 16 deletions test/src/BuildTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,12 @@ test("afterPack", t => {
})
})

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

const winDirPrefix = "lib/net45/resources/"

//noinspection SpellCheckingInspection
await assertPack("test-app", {
platform: [platform],
Expand All @@ -167,9 +169,6 @@ test("copy extra resource", async () => {
tempDirCreated: (projectDir) => {
return BluebirdPromise.all([
modifyPackageJson(projectDir, data => {
if (data.build == null) {
data.build = {}
}
data.build.extraResources = [
"foo",
"bar/hello.txt",
Expand All @@ -179,40 +178,44 @@ test("copy extra resource", async () => {

data.build[osName] = {
extraResources: [
"platformSpecific"
]
"platformSpecificR"
],
extraFiles: [
"platformSpecificF"
],
}
}),
outputFile(path.join(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"),
outputFile(path.join(projectDir, "bar/hello.txt"), "data"),
outputFile(path.join(projectDir, `bar/${process.arch}.txt`), "data"),
outputFile(path.join(projectDir, `${osName}/${process.arch}.txt`), "data"),
outputFile(path.join(projectDir, "platformSpecific"), "platformSpecific"),
outputFile(path.join(projectDir, "platformSpecificR"), "platformSpecificR"),
outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"),
])
},
packed: async (projectDir) => {
let resourcesDir = path.join(projectDir, outDirName, platform.buildConfigurationKey)
const base = path.join(projectDir, outDirName, platform.buildConfigurationKey)
let resourcesDir = path.join(base, "resources")
if (platform === Platform.OSX) {
resourcesDir = path.join(resourcesDir, "TestApp.app", "Contents", "Resources")
resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources")
}
else if (platform === Platform.WINDOWS) {
resourcesDir = path.join(projectDir, outDirName, "win-unpacked")
resourcesDir = path.join(base + "-unpacked", "resources")
}
await assertThat(path.join(resourcesDir, "foo")).isDirectory()
await assertThat(path.join(resourcesDir, "foo", "nameWithoutDot")).isFile()
await assertThat(path.join(resourcesDir, "bar", "hello.txt")).isFile()
await assertThat(path.join(resourcesDir, "bar", `${process.arch}.txt`)).isFile()
await assertThat(path.join(resourcesDir, osName, `${process.arch}.txt`)).isFile()
await assertThat(path.join(resourcesDir, "platformSpecific")).isFile()
await assertThat(path.join(resourcesDir, "platformSpecificR")).isFile()
await assertThat(path.join(resourcesDir, "ignoreMe.txt")).doesNotExist()
},
expectedContents: platform === Platform.WINDOWS ? pathSorter(expectedWinContents.concat(
"lib/net45/bar/hello.txt",
"lib/net45/bar/x64.txt",
"lib/net45/foo/nameWithoutDot",
"lib/net45/platformSpecific",
"lib/net45/win/x64.txt"
winDirPrefix + "bar/hello.txt",
winDirPrefix + "bar/x64.txt",
winDirPrefix + "foo/nameWithoutDot",
winDirPrefix + "platformSpecificR",
winDirPrefix + "win/x64.txt"
)) : null,
})
}
Expand Down
2 changes: 1 addition & 1 deletion test/src/winPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class CheckingWinPackager extends WinPackager {
this.effectiveDistOptions = await this.computeEffectiveDistOptions(appOutDir, installerOutDir, packOptions, "Foo.exe")
}

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

0 comments on commit ca120e3

Please sign in to comment.