123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- 'use strict'
- const asar = require('asar')
- const debug = require('debug')('electron-packager')
- const fs = require('fs-extra')
- const path = require('path')
- const pify = require('pify')
- const common = require('./common')
- const hooks = require('./hooks')
- const ignore = require('./ignore')
- class App {
- constructor (opts, templatePath) {
- this.opts = opts
- this.templatePath = templatePath
- if (this.opts.prune === undefined) {
- this.opts.prune = true
- }
- }
- /**
- * Resource directory path before renaming.
- */
- get originalResourcesDir () {
- return this.resourcesDir
- }
- /**
- * Resource directory path after renaming.
- */
- get resourcesDir () {
- return path.join(this.stagingPath, 'resources')
- }
- get originalResourcesAppDir () {
- return path.join(this.originalResourcesDir, 'app')
- }
- get electronBinaryDir () {
- return this.stagingPath
- }
- get originalElectronName () {
- /* istanbul ignore next */
- throw new Error('Child classes must implement this')
- }
- get newElectronName () {
- /* istanbul ignore next */
- throw new Error('Child classes must implement this')
- }
- get executableName () {
- return this.opts.executableName || this.opts.name
- }
- get stagingPath () {
- if (this.opts.tmpdir === false) {
- return common.generateFinalPath(this.opts)
- } else {
- return path.join(
- common.baseTempDir(this.opts),
- `${this.opts.platform}-${this.opts.arch}`,
- common.generateFinalBasename(this.opts)
- )
- }
- }
- relativeRename (basePath, oldName, newName) {
- debug(`Renaming ${oldName} to ${newName} in ${basePath}`)
- return fs.rename(path.join(basePath, oldName), path.join(basePath, newName))
- }
- renameElectron () {
- return this.relativeRename(this.electronBinaryDir, this.originalElectronName, this.newElectronName)
- }
- /**
- * Performs the following initial operations for an app:
- * * Creates temporary directory
- * * Copies template into temporary directory
- * * Copies user's app into temporary directory
- * * Prunes non-production node_modules (if opts.prune is either truthy or undefined)
- * * Remove default_app (which is either a folder or an asar file)
- * * Creates an asar (if opts.asar is set)
- *
- * Prune and asar are performed before platform-specific logic, primarily so that
- * this.originalResourcesAppDir is predictable (e.g. before .app is renamed for Mac)
- */
- initialize () {
- debug(`Initializing app in ${this.stagingPath} from ${this.templatePath} template`)
- return fs.move(this.templatePath, this.stagingPath, { clobber: true })
- .then(() => this.copyTemplate())
- .then(() => this.removeDefaultApp())
- .then(() => this.asarApp())
- }
- copyTemplate () {
- return fs.copy(this.opts.dir, this.originalResourcesAppDir, {
- filter: ignore.userIgnoreFilter(this.opts),
- dereference: this.opts.derefSymlinks
- }).then(() => hooks.promisifyHooks(this.opts.afterCopy, [
- this.originalResourcesAppDir,
- this.opts.electronVersion,
- this.opts.platform,
- this.opts.arch
- ])).then(() => {
- if (this.opts.prune) {
- return hooks.promisifyHooks(this.opts.afterPrune, [
- this.originalResourcesAppDir,
- this.opts.electronVersion,
- this.opts.platform,
- this.opts.arch
- ])
- } else {
- return true
- }
- })
- }
- removeDefaultApp () {
- return fs.remove(path.join(this.originalResourcesDir, 'default_app'))
- .then(() => fs.remove(path.join(this.originalResourcesDir, 'default_app.asar')))
- }
- /**
- * Forces an icon filename to a given extension and returns the normalized filename,
- * if it exists. Otherwise, returns null.
- *
- * This error path is used by win32 if no icon is specified.
- */
- normalizeIconExtension (targetExt) {
- if (!this.opts.icon) throw new Error('No filename specified to normalizeExt')
- let iconFilename = this.opts.icon
- const ext = path.extname(iconFilename)
- if (ext !== targetExt) {
- iconFilename = path.join(path.dirname(iconFilename), path.basename(iconFilename, ext) + targetExt)
- }
- return fs.pathExists(iconFilename)
- .then(() => iconFilename)
- .catch(/* istanbul ignore next */ () => null)
- }
- asarApp () {
- const asarOptions = common.createAsarOpts(this.opts)
- if (!asarOptions) {
- return Promise.resolve()
- }
- const dest = path.join(this.originalResourcesDir, 'app.asar')
- debug(`Running asar with the options ${JSON.stringify(asarOptions)}`)
- return pify(asar.createPackageWithOptions)(this.originalResourcesAppDir, dest, asarOptions)
- .then(() => fs.remove(this.originalResourcesAppDir))
- }
- copyExtraResources () {
- if (!this.opts.extraResource) return Promise.resolve()
- const extraResources = common.ensureArray(this.opts.extraResource)
- return Promise.all(extraResources.map(
- resource => fs.copy(resource, path.resolve(this.stagingPath, this.resourcesDir, path.basename(resource)))
- ))
- }
- move () {
- const finalPath = common.generateFinalPath(this.opts)
- if (this.opts.tmpdir === false) {
- return Promise.resolve(finalPath)
- }
- debug(`Moving ${this.stagingPath} to ${finalPath}`)
- return fs.move(this.stagingPath, finalPath)
- .then(() => finalPath)
- }
- }
- module.exports = App
|