Skip to content

Commit

Permalink
feat: asarUnpack
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Nov 11, 2016
1 parent 22f73c0 commit 8a8ccad
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 25 deletions.
3 changes: 2 additions & 1 deletion docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ Don't customize paths to background and icon, — just follow conventions.
| --- | ---
| appId | <a name="BuildMetadata-appId"></a><p>The application id. Used as [CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070) for MacOS and as [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows (NSIS target only, Squirrel.Windows not supported).</p> <p>Defaults to <code>com.electron.${name}</code>. It is strongly recommended that an explicit ID be set.</p>
| copyright | <a name="BuildMetadata-copyright"></a>The human-readable copyright line for the app. Defaults to `Copyright © year author`.
| 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> <p>Or you can pass object of any asar options.</p> <p>Node modules, that must be unpacked, will be detected automatically, you don’t need to explicitly set <code>asar.unpackDir</code> - please file issue if this doesn’t work.</p>
| productName | <a name="BuildMetadata-productName"></a>See [AppMetadata.productName](#AppMetadata-productName).
| files | <a name="BuildMetadata-files"></a><p>A [glob patterns](https://www.npmjs.com/package/glob#glob-primer) relative to the [app directory](#MetadataDirectories-app), which specifies which files to include when copying files to create the package.</p> <p>See [File Patterns](#multiple-glob-patterns).</p>
| extraResources | <a name="BuildMetadata-extraResources"></a><p>A [glob patterns](https://www.npmjs.com/package/glob#glob-primer) relative to the project directory, when specified, copy the file or directory with matching names directly into the app’s resources directory (<code>Contents/Resources</code> for MacOS, <code>resources</code> for Linux/Windows).</p> <p>Glob rules the same as for [files](#multiple-glob-patterns).</p>
| extraFiles | <a name="BuildMetadata-extraFiles"></a>The same as [extraResources](#BuildMetadata-extraResources) but copy into the app's content directory (`Contents` for MacOS, root directory for Linux/Windows).
| asar | <a name="BuildMetadata-asar"></a><p>Whether to package the application’s source code into an archive, using [Electron’s archive format](http://electron.atom.io/docs/tutorial/application-packaging/). 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/tutorial/application-packaging/#limitations-of-the-node-api).</p> <p>Or you can pass object of any asar options.</p> <p>Node modules, that must be unpacked, will be detected automatically, you don’t need to explicitly set <code>asarUnpack</code> - please file issue if this doesn’t work.</p>
| asarUnpack | <a name="BuildMetadata-asarUnpack"></a>A [glob patterns](https://www.npmjs.com/package/glob#glob-primer) relative to the [app directory](#MetadataDirectories-app), which specifies which files to unpack when creating the [asar](http://electron.atom.io/docs/tutorial/application-packaging/) archive.
| fileAssociations | <a name="BuildMetadata-fileAssociations"></a>The file associations. See [.build.fileAssociations](#FileAssociation).
| protocols | <a name="BuildMetadata-protocols"></a>The URL protocol scheme(s) to associate the app with. See [.build.protocol](#Protocol).
| mac | <a name="BuildMetadata-mac"></a>See [.build.mac](#MacOptions).
Expand Down
8 changes: 4 additions & 4 deletions src/asarUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ export async function walk(initialDirPath: string, consumer?: (file: string, sta
return result
}

export async function createAsarArchive(src: string, resourcesPath: string, options: AsarOptions, filter: Filter): Promise<any> {
export async function createAsarArchive(src: string, resourcesPath: string, options: AsarOptions, filter: Filter, unpackPattern: Filter | null): Promise<any> {
// sort files to minimize file change (i.e. asar file is not changed dramatically on small change)
await new AsarPackager(src, resourcesPath, options).pack(filter)
await new AsarPackager(src, resourcesPath, options, unpackPattern).pack(filter)
}

function isUnpackDir(path: string, pattern: Minimatch, rawPattern: string): boolean {
Expand All @@ -83,7 +83,7 @@ class AsarPackager {

private srcRealPath: Promise<string>

constructor(private src: string, private resourcesPath: string, private options: AsarOptions) {
constructor(private readonly src: string, private readonly resourcesPath: string, private readonly options: AsarOptions, private readonly unpackPattern: Filter | null) {
this.outFile = path.join(this.resourcesPath, "app.asar")
}

Expand Down Expand Up @@ -234,7 +234,7 @@ class AsarPackager {
const fileSize = newData == null ? stat.size : Buffer.byteLength(newData)
const node = this.fs.searchNodeFromPath(file)
node.size = fileSize
if (dirNode.unpacked || (unpack != null && unpack.match(file))) {
if (dirNode.unpacked || (this.unpackPattern != null && this.unpackPattern(file, stat)) || (unpack != null && unpack.match(file))) {
node.unpacked = true

if (!dirNode.unpacked) {
Expand Down
27 changes: 17 additions & 10 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,6 @@ export interface BuildMetadata {
*/
readonly copyright?: string | null

/*
Whether to package the application's source code into an archive, using [Electron's archive format](https://github.com/electron/asar). Defaults to `true`.
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/).
Or you can pass object of any asar options.
Node modules, that must be unpacked, will be detected automatically, you don't need to explicitly set `asar.unpackDir` - please file issue if this doesn't work.
*/
readonly asar?: AsarOptions | boolean | null

// deprecated
readonly iconUrl?: string | null

Expand Down Expand Up @@ -137,6 +127,21 @@ export interface BuildMetadata {
*/
readonly extraFiles?: Array<string> | string | null

/*
Whether to package the application's source code into an archive, using [Electron's archive format](http://electron.atom.io/docs/tutorial/application-packaging/). Defaults to `true`.
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/tutorial/application-packaging/#limitations-of-the-node-api).
Or you can pass object of any asar options.
Node modules, that must be unpacked, will be detected automatically, you don't need to explicitly set `asarUnpack` - please file issue if this doesn't work.
*/
readonly asar?: AsarOptions | boolean | null

/**
A [glob patterns](https://www.npmjs.com/package/glob#glob-primer) relative to the [app directory](#MetadataDirectories-app), which specifies which files to unpack when creating the [asar](http://electron.atom.io/docs/tutorial/application-packaging/) archive.
*/
readonly asarUnpack?: Array<string> | string | null

/*
The file associations. See [.build.fileAssociations](#FileAssociation).
*/
Expand Down Expand Up @@ -322,6 +327,8 @@ export interface PlatformSpecificBuildOptions {
readonly extraFiles?: Array<string> | null
readonly extraResources?: Array<string> | null

readonly asarUnpack?: Array<string> | null

readonly asar?: AsarOptions | boolean

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

abstract pack(outDir: string, arch: Arch, targets: Array<Target>, postAsyncTasks: Array<Promise<any>>): Promise<any>

private getExtraFileMatchers(isResources: boolean, appOutDir: string, fileMatchOptions: FileMatchOptions, customBuildOptions: DC): Array<FileMatcher> | n {
private getExtraFileMatchers(isResources: boolean, appOutDir: string, fileMatchOptions: FileMatchOptions, customBuildOptions: DC): Array<FileMatcher> | null {
const base = isResources ? this.getResourcesDir(appOutDir) : (this.platform === Platform.MAC ? path.join(appOutDir, `${this.appInfo.productFilename}.app`, "Contents") : appOutDir)
return this.getFileMatchers(isResources ? "extraResources" : "extraFiles", this.projectDir, base, true, fileMatchOptions, customBuildOptions)
}
Expand Down Expand Up @@ -199,8 +199,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

const patterns = this.getFileMatchers("files", appDir, path.join(resourcesPath, "app"), false, fileMatchOptions, platformSpecificBuildOptions)
let defaultMatcher = patterns != null ? patterns[0] : new FileMatcher(appDir, path.join(resourcesPath, "app"), fileMatchOptions)

let defaultMatcher = patterns == null ? new FileMatcher(appDir, path.join(resourcesPath, "app"), fileMatchOptions) : patterns[0]
if (defaultMatcher.isEmpty()) {
defaultMatcher.addPattern("**/*")
}
Expand Down Expand Up @@ -243,9 +242,15 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

const filter = defaultMatcher.createFilter(ignoreFiles, rawFilter, excludePatterns.length ? excludePatterns : null)
const promise = asarOptions == null ?
copyFiltered(appDir, path.join(resourcesPath, "app"), filter, this.info.devMetadata.build.dereference || this.platform === Platform.WINDOWS)
: createAsarArchive(appDir, resourcesPath, asarOptions, filter)
let promise
if (asarOptions == null) {
promise = copyFiltered(appDir, path.join(resourcesPath, "app"), filter, this.info.devMetadata.build.dereference || this.platform === Platform.WINDOWS)
}
else {
const unpackPattern = this.getFileMatchers("asarUnpack", appDir, path.join(resourcesPath, "app"), false, fileMatchOptions, platformSpecificBuildOptions)
const fileMatcher = unpackPattern == null ? null : unpackPattern[0]
promise = createAsarArchive(appDir, resourcesPath, asarOptions, filter, fileMatcher == null ? null : fileMatcher.createFilter())
}

const promises = [promise, unlinkIfExists(path.join(resourcesPath, "default_app.asar")), unlinkIfExists(path.join(appOutDir, "version"))]
if (this.info.electronVersion != null && this.info.electronVersion[0] === "0") {
Expand Down Expand Up @@ -311,7 +316,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
})
}

private doCopyExtraFiles(patterns: Array<FileMatcher> | n): Promise<any> {
private doCopyExtraFiles(patterns: Array<FileMatcher> | null): Promise<any> {
if (patterns == null || patterns.length === 0) {
return BluebirdPromise.resolve()
}
Expand All @@ -327,7 +332,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}
}

private getFileMatchers(name: "files" | "extraFiles" | "extraResources", defaultSrc: string, defaultDest: string, allowAdvancedMatching: boolean, fileMatchOptions: FileMatchOptions, customBuildOptions: DC): Array<FileMatcher> | n {
private getFileMatchers(name: "files" | "extraFiles" | "extraResources" | "asarUnpack", defaultSrc: string, defaultDest: string, allowAdvancedMatching: boolean, fileMatchOptions: FileMatchOptions, customBuildOptions: DC): Array<FileMatcher> | null {
let globalPatterns: Array<string | FilePattern> | string | n | FilePattern = (<any>this.devMetadata.build)[name]
let platformSpecificPatterns: Array<string | FilePattern> | string | n = (<any>customBuildOptions)[name]

Expand Down Expand Up @@ -370,7 +375,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
fileMatchers.unshift(defaultMatcher)
}

return fileMatchers.length ? fileMatchers : null
return fileMatchers.length === 0 ? null : fileMatchers
}

private getResourcesDir(appOutDir: string): string {
Expand Down
2 changes: 1 addition & 1 deletion src/util/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function hasMagic(pattern: Minimatch) {
export type Filter = (file: string, stat: Stats) => boolean

export function createFilter(src: string, patterns: Array<Minimatch>, ignoreFiles?: Set<string>, rawFilter?: (file: string) => boolean, excludePatterns?: Array<Minimatch> | null): Filter {
return function filter(it, stat) {
return function (it, stat) {
if (src === it) {
return true
}
Expand Down

0 comments on commit 8a8ccad

Please sign in to comment.