Skip to content

Commit ca120e3

Browse files
committed
feat: extraFiles
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`.
1 parent a5e4571 commit ca120e3

File tree

6 files changed

+49
-40
lines changed

6 files changed

+49
-40
lines changed

docs/Options.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ Here documented only `electron-builder` specific options:
5454
| 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>
5555
| 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>
5656
| productName | <a name="BuildMetadata-productName"></a>See [AppMetadata.productName](#AppMetadata-productName).
57-
| 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>
57+
| 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>
58+
| 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).
5859
| osx | <a name="BuildMetadata-osx"></a>See [.build.osx](#OsXBuildOptions).
5960
| mas | <a name="BuildMetadata-mas"></a>See [.build.mas](#MasBuildOptions).
6061
| win | <a name="BuildMetadata-win"></a>See [.build.win](#LinuxBuildOptions).

src/metadata.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export interface BuildMetadata {
105105
readonly productName?: string | null
106106

107107
/**
108-
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).
108+
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).
109109
110110
You can use `${os}` (expanded to osx, linux or win according to current platform) and `${arch}` in the pattern.
111111
@@ -115,6 +115,11 @@ export interface BuildMetadata {
115115
*/
116116
readonly extraResources?: Array<string> | null
117117

118+
/**
119+
The same as [extraResources](#BuildMetadata-extraResources) but copy into the app's content directory (`Contents` for OS X, `` for Linux/Windows).
120+
*/
121+
readonly extraFiles?: Array<string> | null
122+
118123
/*
119124
See [.build.osx](#OsXBuildOptions).
120125
*/
@@ -334,6 +339,7 @@ export interface MetadataDirectories {
334339
}
335340

336341
export interface PlatformSpecificBuildOptions {
342+
readonly extraFiles?: Array<string> | null
337343
readonly extraResources?: Array<string> | null
338344

339345
readonly target?: Array<string> | null

src/platformPackager.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
153153

154154
protected async doPack(options: ElectronPackagerOptions, outDir: string, appOutDir: string, arch: string, customBuildOptions: DC) {
155155
await this.packApp(options, appOutDir)
156-
await this.copyExtraResources(appOutDir, arch, customBuildOptions)
156+
await this.copyExtraFiles(appOutDir, arch, customBuildOptions)
157157
}
158158

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

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

217-
const platformSpecificExtraResources = customBuildOptions.extraResources
218-
if (platformSpecificExtraResources != null) {
219-
extraResources = extraResources == null ? platformSpecificExtraResources : extraResources.concat(platformSpecificExtraResources)
217+
const platformSpecificExtra = isResources ? customBuildOptions.extraResources : customBuildOptions.extraFiles
218+
if (platformSpecificExtra != null) {
219+
extra = extra == null ? platformSpecificExtra : extra.concat(platformSpecificExtra)
220220
}
221221

222-
if (extraResources == null) {
222+
if (extra == null) {
223223
return BluebirdPromise.resolve([])
224224
}
225225

226-
const expandedPatterns = extraResources.map(it => it
226+
const expandedPatterns = extra.map(it => it
227227
.replace(/\$\{arch}/g, arch)
228228
.replace(/\$\{os}/g, this.platform.buildConfigurationKey))
229229
return globby(expandedPatterns, {cwd: this.projectDir})
230230
}
231231

232-
protected async copyExtraResources(appOutDir: string, arch: string, customBuildOptions: DC): Promise<Array<string>> {
233-
let resourcesDir = appOutDir
234-
if (this.platform === Platform.OSX) {
235-
resourcesDir = this.getOSXResourcesDir(appOutDir)
236-
}
237-
return await BluebirdPromise.map(await this.getExtraResources(arch, customBuildOptions), it => copy(path.join(this.projectDir, it), path.join(resourcesDir, it)))
232+
protected async copyExtraFiles(appOutDir: string, arch: string, customBuildOptions: DC): Promise<any> {
233+
await this.doCopyExtraFiles(true, appOutDir, arch, this.customBuildOptions)
234+
await this.doCopyExtraFiles(false, appOutDir, arch, this.customBuildOptions)
235+
}
236+
237+
private async doCopyExtraFiles(isResources: boolean, appOutDir: string, arch: string, customBuildOptions: DC): Promise<Array<string>> {
238+
const base = isResources ? this.getResourcesDir(appOutDir) : this.platform === Platform.OSX ? path.join(appOutDir, `${this.appName}.app`, "Contents") : appOutDir
239+
return await BluebirdPromise.map(await this.getExtraResources(isResources, arch, customBuildOptions), it => copy(path.join(this.projectDir, it), path.join(base, it)))
238240
}
239241

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

263265
private getOSXResourcesDir(appOutDir: string): string {
264-
return path.join(appOutDir, this.appName + ".app", "Contents", "Resources")
266+
return path.join(appOutDir, `${this.appName}.app`, "Contents", "Resources")
265267
}
266268

267269
private async statFileInPackage(resourcesDir: string, packageFile: string, isAsar: boolean): Promise<any> {

src/winPackager.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const __awaiter = require("./awaiter")
1414
export class WinPackager extends PlatformPackager<WinBuildOptions> {
1515
certFilePromise: Promise<string | null>
1616

17-
loadingGifStat: Promise<string> | null
18-
1917
readonly iconPath: Promise<string>
2018

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

6866
const installerOut = computeDistOut(outDir, arch)
6967
await BluebirdPromise.all([
70-
this.packApp(packOptions, appOutDir),
68+
this.doPack(packOptions, outDir, appOutDir, arch, this.customBuildOptions),
7169
emptyDir(installerOut)
7270
])
7371

74-
await this.copyExtraResources(appOutDir, arch, this.customBuildOptions)
75-
postAsyncTasks.push(this.packageInDistributableFormat(outDir, appOutDir, installerOut!, arch, packOptions))
72+
postAsyncTasks.push(this.packageInDistributableFormat(appOutDir, installerOut, arch, packOptions))
7673
}
7774

7875
protected computeAppOutDir(outDir: string, arch: string): string {
@@ -162,7 +159,7 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
162159
return options
163160
}
164161

165-
protected async packageInDistributableFormat(outDir: string, appOutDir: string, installerOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
162+
protected async packageInDistributableFormat(appOutDir: string, installerOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
166163
const winstaller = require("electron-winstaller-fixed")
167164
const version = this.metadata.version
168165
const archSuffix = arch === "x64" ? "" : ("-" + arch)

test/src/BuildTest.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,12 @@ test("afterPack", t => {
154154
})
155155
})
156156

157-
test("copy extra resource", async () => {
157+
test("copy extra content", async () => {
158158
for (let platform of getPossiblePlatforms()) {
159159
const osName = platform.buildConfigurationKey
160160

161+
const winDirPrefix = "lib/net45/resources/"
162+
161163
//noinspection SpellCheckingInspection
162164
await assertPack("test-app", {
163165
platform: [platform],
@@ -167,9 +169,6 @@ test("copy extra resource", async () => {
167169
tempDirCreated: (projectDir) => {
168170
return BluebirdPromise.all([
169171
modifyPackageJson(projectDir, data => {
170-
if (data.build == null) {
171-
data.build = {}
172-
}
173172
data.build.extraResources = [
174173
"foo",
175174
"bar/hello.txt",
@@ -179,40 +178,44 @@ test("copy extra resource", async () => {
179178

180179
data.build[osName] = {
181180
extraResources: [
182-
"platformSpecific"
183-
]
181+
"platformSpecificR"
182+
],
183+
extraFiles: [
184+
"platformSpecificF"
185+
],
184186
}
185187
}),
186188
outputFile(path.join(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"),
187189
outputFile(path.join(projectDir, "bar/hello.txt"), "data"),
188190
outputFile(path.join(projectDir, `bar/${process.arch}.txt`), "data"),
189191
outputFile(path.join(projectDir, `${osName}/${process.arch}.txt`), "data"),
190-
outputFile(path.join(projectDir, "platformSpecific"), "platformSpecific"),
192+
outputFile(path.join(projectDir, "platformSpecificR"), "platformSpecificR"),
191193
outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"),
192194
])
193195
},
194196
packed: async (projectDir) => {
195-
let resourcesDir = path.join(projectDir, outDirName, platform.buildConfigurationKey)
197+
const base = path.join(projectDir, outDirName, platform.buildConfigurationKey)
198+
let resourcesDir = path.join(base, "resources")
196199
if (platform === Platform.OSX) {
197-
resourcesDir = path.join(resourcesDir, "TestApp.app", "Contents", "Resources")
200+
resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources")
198201
}
199202
else if (platform === Platform.WINDOWS) {
200-
resourcesDir = path.join(projectDir, outDirName, "win-unpacked")
203+
resourcesDir = path.join(base + "-unpacked", "resources")
201204
}
202205
await assertThat(path.join(resourcesDir, "foo")).isDirectory()
203206
await assertThat(path.join(resourcesDir, "foo", "nameWithoutDot")).isFile()
204207
await assertThat(path.join(resourcesDir, "bar", "hello.txt")).isFile()
205208
await assertThat(path.join(resourcesDir, "bar", `${process.arch}.txt`)).isFile()
206209
await assertThat(path.join(resourcesDir, osName, `${process.arch}.txt`)).isFile()
207-
await assertThat(path.join(resourcesDir, "platformSpecific")).isFile()
210+
await assertThat(path.join(resourcesDir, "platformSpecificR")).isFile()
208211
await assertThat(path.join(resourcesDir, "ignoreMe.txt")).doesNotExist()
209212
},
210213
expectedContents: platform === Platform.WINDOWS ? pathSorter(expectedWinContents.concat(
211-
"lib/net45/bar/hello.txt",
212-
"lib/net45/bar/x64.txt",
213-
"lib/net45/foo/nameWithoutDot",
214-
"lib/net45/platformSpecific",
215-
"lib/net45/win/x64.txt"
214+
winDirPrefix + "bar/hello.txt",
215+
winDirPrefix + "bar/x64.txt",
216+
winDirPrefix + "foo/nameWithoutDot",
217+
winDirPrefix + "platformSpecificR",
218+
winDirPrefix + "win/x64.txt"
216219
)) : null,
217220
})
218221
}

test/src/winPackagerTest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class CheckingWinPackager extends WinPackager {
118118
this.effectiveDistOptions = await this.computeEffectiveDistOptions(appOutDir, installerOutDir, packOptions, "Foo.exe")
119119
}
120120

121-
async packageInDistributableFormat(outDir: string, appOutDir: string, installerOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
121+
async packageInDistributableFormat(appOutDir: string, installerOutDir: string, arch: string, packOptions: ElectronPackagerOptions): Promise<any> {
122122
// skip
123123
}
124124
}

0 commit comments

Comments
 (0)