Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish promisification refactor #753

Merged
merged 10 commits into from
Nov 14, 2017
185 changes: 22 additions & 163 deletions common.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
'use strict'

const asar = require('asar')
const debug = require('debug')('electron-packager')
const download = require('electron-download')
const fs = require('fs-extra')
const ignore = require('./ignore')
const os = require('os')
const path = require('path')
const pruneModules = require('./prune').pruneModules
const pify = require('pify')
const sanitize = require('sanitize-filename')
const semver = require('semver')
const series = require('run-series')
const targets = require('./targets')
const yargs = require('yargs-parser')

Expand Down Expand Up @@ -75,32 +71,6 @@ function parseCLIArgs (argv) {
return args
}

function asarApp (appPath, asarOptions, cb) {
var dest = path.join(appPath, '..', 'app.asar')
debug(`Running asar with the options ${JSON.stringify(asarOptions)}`)
asar.createPackageWithOptions(appPath, dest, asarOptions, function (err) {
if (err) return cb(err)
fs.remove(appPath, function (err) {
if (err) return cb(err)
cb(null, dest)
})
})
}

function copyExtraResources (operations, resourcesPath, extraResources) {
if (!Array.isArray(extraResources)) extraResources = [extraResources]

for (const resource of extraResources) {
operations.push(cb => {
fs.copy(resource, path.join(resourcesPath, path.basename(resource)), cb)
})
}
}

function isPlatformMac (platform) {
return platform === 'darwin' || platform === 'mas'
}

function sanitizeAppName (name) {
return sanitize(name, {replacement: '-'})
}
Expand Down Expand Up @@ -132,10 +102,6 @@ function subOptionWarning (properties, optionName, parameter, value, quiet) {
properties[parameter] = value
}

function baseTempDir (opts) {
return path.join(opts.tmpdir || os.tmpdir(), 'electron-packager')
}

function createAsarOpts (opts) {
let asarOptions
if (opts.asar === true) {
Expand Down Expand Up @@ -165,11 +131,9 @@ function createDownloadOpts (opts, platform, arch) {
module.exports = {
parseCLIArgs: parseCLIArgs,

isPlatformMac: isPlatformMac,

subOptionWarning: subOptionWarning,

baseTempDir: baseTempDir,
isPlatformMac: function isPlatformMac (platform) {
return platform === 'darwin' || platform === 'mas'
},

createAsarOpts: createAsarOpts,

Expand All @@ -181,6 +145,15 @@ module.exports = {
})
},
createDownloadOpts: createDownloadOpts,
downloadElectronZip: function downloadElectronZip (downloadOpts) {
// armv7l builds have only been backfilled for Electron >= 1.0.0.
// See: https://github.com/electron/electron/pull/6986
if (downloadOpts.arch === 'armv7l' && semver.lt(downloadOpts.version, '1.0.0')) {
downloadOpts.arch = 'arm'
}
debug(`Downloading Electron with options ${JSON.stringify(downloadOpts)}`)
return pify(download)(downloadOpts)
},

deprecatedParameter: function deprecatedParameter (properties, oldName, newName, newCLIName) {
if (properties.hasOwnProperty(oldName)) {
Expand All @@ -191,137 +164,23 @@ module.exports = {
delete properties[oldName]
}
},
subOptionWarning: subOptionWarning,

downloadElectronZip: function downloadElectronZip (downloadOpts, cb) {
// armv7l builds have only been backfilled for Electron >= 1.0.0.
// See: https://github.com/electron/electron/pull/6986
if (downloadOpts.arch === 'armv7l' && semver.lt(downloadOpts.version, '1.0.0')) {
downloadOpts.arch = 'arm'
}
debug(`Downloading Electron with options ${JSON.stringify(downloadOpts)}`)
download(downloadOpts, cb)
baseTempDir: function baseTempDir (opts) {
return path.join(opts.tmpdir || os.tmpdir(), 'electron-packager')
},

generateFinalBasename: generateFinalBasename,
generateFinalPath: generateFinalPath,
sanitizeAppName: sanitizeAppName,

info: info,

initializeApp: function initializeApp (opts, templatePath, appRelativePath, callback) {
// 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)
// * Creates an asar (if opts.asar is set)

var tempPath
if (opts.tmpdir === false) {
tempPath = generateFinalPath(opts)
} else {
tempPath = path.join(baseTempDir(opts), `${opts.platform}-${opts.arch}`, generateFinalBasename(opts))
}

debug(`Initializing app in ${tempPath} from ${templatePath} template`)

// Path to `app` directory
var appPath = path.join(tempPath, appRelativePath)
var resourcesPath = path.resolve(appPath, '..')

var operations = [
function (cb) {
fs.move(templatePath, tempPath, {clobber: true}, cb)
},
function (cb) {
fs.copy(opts.dir, appPath, {filter: ignore.userIgnoreFilter(opts), dereference: opts.derefSymlinks}, cb)
},
function (cb) {
var afterCopyHooks = (opts.afterCopy || []).map(function (afterCopyFn) {
return function (cb) {
afterCopyFn(appPath, opts.electronVersion, opts.platform, opts.arch, cb)
}
})
series(afterCopyHooks, cb)
},
function (cb) {
// Support removing old default_app folder that is now an asar archive
fs.remove(path.join(resourcesPath, 'default_app'), cb)
},
function (cb) {
fs.remove(path.join(resourcesPath, 'default_app.asar'), cb)
}
]

// Prune and asar are now performed before platform-specific logic, primarily so that
// appPath is predictable (e.g. before .app is renamed for mac)
if (opts.prune || opts.prune === undefined) {
operations.push(function (cb) {
pruneModules(opts, appPath, cb)
})
operations.push(function (cb) {
var afterPruneHooks = (opts.afterPrune || []).map(function (afterPruneFn) {
return function (cb) {
afterPruneFn(appPath, opts.electronVersion, opts.platform, opts.arch, cb)
}
})
series(afterPruneHooks, cb)
})
}

let asarOptions = createAsarOpts(opts)
if (asarOptions) {
operations.push(function (cb) {
asarApp(appPath, asarOptions, cb)
})
}

if (opts.extraResource) {
copyExtraResources(operations, resourcesPath, opts.extraResource)
}

series(operations, function (err) {
if (err) return callback(err)
// Resolve to path to temporary app folder for platform-specific processes to use
callback(null, tempPath)
})
},

moveApp: function finalizeApp (opts, tempPath, callback) {
var finalPath = generateFinalPath(opts)

if (opts.tmpdir === false) {
callback(null, finalPath)
return
}

debug(`Moving ${tempPath} to ${finalPath}`)
fs.move(tempPath, finalPath, function (err) {
callback(err, finalPath)
})
},

normalizeExt: function normalizeExt (filename, targetExt, cb) {
// Forces a filename to a given extension and fires the given callback with the normalized filename,
// if it exists. Otherwise reports the error from the fs.stat call.
// (Used for resolving icon filenames, particularly during --all runs.)

// This error path is used by win32.js if no icon is specified
if (!filename) return cb(new Error('No filename specified to normalizeExt'))

var ext = path.extname(filename)
if (ext !== targetExt) {
filename = filename.slice(0, filename.length - ext.length) + targetExt
promisifyHooks: function promisifyHooks (hooks, args) {
if (!hooks || !Array.isArray(hooks)) {
return Promise.resolve()
}

fs.stat(filename, function (err) {
cb(err, err ? null : filename)
})
return Promise.all(hooks.map(hookFn => pify(hookFn).apply(this, args)))
},

rename: function rename (basePath, oldName, newName, cb) {
debug(`Renaming ${oldName} to ${newName} in ${basePath}`)
fs.rename(path.join(basePath, oldName), path.join(basePath, newName), cb)
},
sanitizeAppName: sanitizeAppName,
info: info,
warning: warning
}
9 changes: 2 additions & 7 deletions ignore.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict'

const common = require('./common')
const debug = require('debug')('electron-packager')
const path = require('path')
const targets = require('./targets')
Expand All @@ -15,11 +16,8 @@ const DEFAULT_IGNORES = [

function generateIgnores (opts) {
if (typeof (opts.ignore) !== 'function') {
// Avoid a circular require that breaks things
const common = require('./common')

if (opts.ignore && !Array.isArray(opts.ignore)) opts.ignore = [opts.ignore]
opts.ignore = (opts.ignore) ? opts.ignore.concat(DEFAULT_IGNORES) : [].concat(DEFAULT_IGNORES)
opts.ignore = opts.ignore ? opts.ignore.concat(DEFAULT_IGNORES) : [].concat(DEFAULT_IGNORES)
if (process.platform === 'linux') {
opts.ignore.push(common.baseTempDir(opts))
}
Expand All @@ -29,9 +27,6 @@ function generateIgnores (opts) {
}

function generateOutIgnores (opts) {
// Avoid a circular require that breaks things
const common = require('./common')

let normalizedOut = opts.out ? path.resolve(opts.out) : null
let outIgnores = []
if (normalizedOut === null || normalizedOut === process.cwd()) {
Expand Down