Skip to content

Commit

Permalink
Merge pull request #819 from electron-userland/prune-via-js-only
Browse files Browse the repository at this point in the history
Drop packageManager support & refactor pruning to be part of the copy filter
  • Loading branch information
malept authored Mar 31, 2018
2 parents 6a23f79 + dff1fb2 commit f178740
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 163 deletions.
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

[Unreleased]: https://github.com/electron-userland/electron-packager/compare/v11.2.0...master

### Changed

* `prune` exclusively utilizes the `galactus` module for pruning devDependencies, instead of
depending on package managers
* `electron-packager` is no longer ignored by default
* A warning is emitted when an Electron module is a production dependency

### Removed

* `packageManager` option

## [11.2.0] - 2018-03-24

[11.2.0]: https://github.com/electron-userland/electron-packager/compare/v11.1.0...v11.2.0
Expand Down
6 changes: 6 additions & 0 deletions common.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ module.exports = {
generateFinalBasename: generateFinalBasename,
generateFinalPath: generateFinalPath,
sanitizeAppName: sanitizeAppName,
/**
* Convert slashes to UNIX-format separators.
*/
normalizePath: function normalizePath (pathToNormalize) {
return pathToNormalize.replace(/\\/g, '/')
},

info: info,
warning: warning
Expand Down
17 changes: 1 addition & 16 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,21 +313,6 @@ The base directory where the finished package(s) are created.

Whether to replace an already existing output directory for a given platform (`true`) or skip recreating it (`false`).

##### `packageManager`

*String* or *Boolean* (default: `npm`)

The package manager used to [prune](#prune) `devDependencies` modules from the outputted Electron
app. Supported package managers:

* [`npm`](https://npmjs.com/)
* [`cnpm`](https://github.com/cnpm/cnpm) (Does not currently work with Windows, see
[GitHub issue](https://github.com/electron-userland/electron-packager/issues/515#issuecomment-297604044))
* [`yarn`](https://yarnpkg.com/)

If set to `false` we will use a custom [pruning module](https://www.npmjs.com/package/pruner) to walk your dependency
tree and prune your dependencies for you.

##### `platform`

*String* (default: the arch of the host computer running Node)
Expand All @@ -345,7 +330,7 @@ is not restricted to the official set if [`download.mirror`](#download) is set.

*Boolean* (default: `true`)

Runs the [package manager](#packagemanager) command to remove all of the packages specified in the
Walks the `node_modules` dependency tree to remove all of the packages specified in the
`devDependencies` section of `package.json` from the outputted Electron app.

##### `quiet`
Expand Down
19 changes: 11 additions & 8 deletions ignore.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
const common = require('./common')
const debug = require('debug')('electron-packager')
const path = require('path')
const prune = require('./prune')
const targets = require('./targets')

const DEFAULT_IGNORES = [
'/node_modules/electron($|/)',
'/node_modules/electron-prebuilt(-compile)?($|/)',
'/node_modules/electron-packager($|/)',
'/\\.git($|/)',
'/node_modules/\\.bin($|/)',
'\\.o(bj)?$'
Expand All @@ -30,8 +28,8 @@ function generateIgnores (opts) {
}

function generateOutIgnores (opts) {
let normalizedOut = opts.out ? path.resolve(opts.out) : null
let outIgnores = []
const normalizedOut = opts.out ? path.resolve(opts.out) : null
const outIgnores = []
if (normalizedOut === null || normalizedOut === process.cwd()) {
for (const platform of Object.keys(targets.officialPlatformArchCombos)) {
for (const arch of targets.officialPlatformArchCombos[platform]) {
Expand Down Expand Up @@ -66,7 +64,8 @@ function userIgnoreFilter (opts) {
}
}

let outIgnores = generateOutIgnores(opts)
const outIgnores = generateOutIgnores(opts)
const pruner = opts.prune ? new prune.Pruner(opts.dir) : null

return function filter (file) {
if (outIgnores.indexOf(file) !== -1) {
Expand All @@ -76,8 +75,12 @@ function userIgnoreFilter (opts) {
let name = file.split(path.resolve(opts.dir))[1]

if (path.sep === '\\') {
// convert slashes so unix-format ignores work
name = name.replace(/\\/g, '/')
name = common.normalizePath(name)
}

if (pruner && name.startsWith('/node_modules/')) {
return prune.isModule(file)
.then(isModule => isModule ? pruner.pruneModule(name) : ignoreFunc(name))
}

return ignoreFunc(name)
Expand Down
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
"electron-osx-sign": "^0.4.1",
"extract-zip": "^1.0.3",
"fs-extra": "^5.0.0",
"galactus": "^0.2.0",
"get-package-info": "^1.0.0",
"mz": "^2.6.0",
"nodeify": "^1.0.1",
"parse-author": "^2.0.0",
"pify": "^3.0.0",
"plist": "^2.0.0",
"pruner": "^0.0.7",
"rcedit": "^1.0.0",
"resolve": "^1.1.6",
"sanitize-filename": "^1.6.0",
Expand All @@ -40,18 +39,18 @@
"ava": "^0.25.0",
"buffer-equal": "^1.0.0",
"codecov": "^3.0.0",
"eslint": "^4.1.0",
"eslint": "^4.18.0",
"eslint-config-standard": "^11.0.0",
"eslint-plugin-ava": "^4.3.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-node": "^6.0.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.0",
"mz": "^2.6.0",
"nyc": "^11.0.0",
"pkg-up": "^2.0.0",
"sinon": "^4.1.3",
"tempy": "^0.2.1",
"which": "^1.2.14"
"tempy": "^0.2.1"
},
"engines": {
"node": ">= 4.0"
Expand Down
31 changes: 17 additions & 14 deletions platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ 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')
const pruneModules = require('./prune').pruneModules

const common = require('./common')

class App {
constructor (opts, templatePath) {
this.opts = opts
this.templatePath = templatePath

if (this.opts.prune === undefined) {
this.opts.prune = true
}
}

/**
Expand Down Expand Up @@ -94,7 +96,6 @@ class App {
}).then(() => fs.remove(path.join(this.originalResourcesDir, 'default_app.asar')))
// Prune and asar are performed before platform-specific logic, primarily so that
// this.originalResourcesAppDir is predictable (e.g. before .app is renamed for mac)
.then(() => this.prune())
.then(() => this.asarApp())
}

Expand All @@ -107,7 +108,18 @@ class App {
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
}
})
}

/**
Expand All @@ -130,15 +142,6 @@ class App {
.catch(/* istanbul ignore next */ () => null)
}

prune () {
if (this.opts.prune || this.opts.prune === undefined) {
return pruneModules(this.opts, this.originalResourcesAppDir)
.then(() => hooks.promisifyHooks(this.opts.afterPrune, [this.originalResourcesAppDir, this.opts.electronVersion, this.opts.platform, this.opts.arch]))
}

return Promise.resolve()
}

asarApp () {
const asarOptions = common.createAsarOpts(this.opts)
if (!asarOptions) {
Expand Down
86 changes: 55 additions & 31 deletions prune.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,69 @@
'use strict'

const child = require('mz/child_process')
const debug = require('debug')('electron-packager')
const Walker = require('pruner').Walker

const knownPackageManagers = ['npm', 'cnpm', 'yarn']

function pruneCommand (packageManager) {
switch (packageManager) {
case 'npm':
case 'cnpm':
return `${packageManager} prune --production`
case 'yarn':
return `${packageManager} install --production --no-bin-links --no-lockfile`
const common = require('./common')
const galactus = require('galactus')
const fs = require('fs-extra')
const path = require('path')

const ELECTRON_MODULES = [
'electron',
'electron-prebuilt',
'electron-prebuilt-compile'
]

class Pruner {
constructor (dir) {
this.baseDir = common.normalizePath(dir)
this.galactus = new galactus.DestroyerOfModules({
rootDirectory: dir,
shouldKeepModuleTest: (module, isDevDep) => this.shouldKeepModule(module, isDevDep)
})
this.walkedTree = false
}
}

function pruneModules (opts, appPath) {
if (opts.packageManager === false) {
const walker = new Walker(appPath)
return walker.prune()
} else {
const packageManager = opts.packageManager || 'npm'
setModuleMap (moduleMap) {
this.moduleMap = new Map()
// destructured assignments are in Node 6
for (const modulePair of moduleMap) {
const modulePath = modulePair[0]
const module = modulePair[1]
this.moduleMap.set(`/${common.normalizePath(modulePath)}`, module)
}
this.walkedTree = true
}

/* istanbul ignore if */
if (packageManager === 'cnpm' && process.platform === 'win32') {
return Promise.reject(new Error('cnpm support does not currently work with Windows, see: https://github.com/electron-userland/electron-packager/issues/515#issuecomment-297604044'))
pruneModule (name) {
if (this.walkedTree) {
return this.isProductionModule(name)
} else {
return this.galactus.collectKeptModules({ relativePaths: true })
.then(moduleMap => this.setModuleMap(moduleMap))
.then(() => this.isProductionModule(name))
}
}

const command = pruneCommand(packageManager)
shouldKeepModule (module, isDevDep) {
if (isDevDep || module.depType === galactus.DepType.ROOT) {
return false
}

if (command) {
debug(`Pruning modules via: ${command}`)
return child.exec(command, { cwd: appPath })
} else {
return Promise.reject(new Error(`Unknown package manager "${packageManager}". Known package managers: ${knownPackageManagers.join(', ')}`))
// Node 6 has Array.prototype.includes
if (ELECTRON_MODULES.indexOf(module.name) !== -1) {
common.warning(`Found '${module.name}' but not as a devDependency, pruning anyway`)
return false
}

return true
}

isProductionModule (name) {
return !!this.moduleMap.get(name)
}
}

module.exports = {
pruneCommand: pruneCommand,
pruneModules: pruneModules
isModule: function isModule (pathToCheck) {
return fs.pathExists(path.join(pathToCheck, 'package.json'))
},
Pruner: Pruner
}
1 change: 1 addition & 0 deletions test/_setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ function npmInstallForFixtures () {
const fixtures = [
'basic',
'basic-renamed-to-electron',
'electron-in-dependencies',
'infer-missing-version-only',
'el-0374'
]
Expand Down
8 changes: 1 addition & 7 deletions test/ci/before_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ case "$TRAVIS_OS_NAME" in
# Not using Trusty containers because it can't install wine1.6(-i386),
# see: https://github.com/travis-ci/travis-ci/issues/6460
sudo rm /etc/apt/sources.list.d/google-chrome.list
sudo apt-key adv --fetch-keys http://dl.yarnpkg.com/debian/pubkey.gpg
echo "deb http://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y wine1.6 yarn
sudo apt-get install -y wine1.6
;;
"osx")
# Create CA
Expand All @@ -31,9 +29,5 @@ case "$TRAVIS_OS_NAME" in
npm install [email protected]
# Setup ~/.wine by running a command
./node_modules/.bin/wine hostname
# Install yarn
npm install -g yarn
;;
esac

npm install -g cnpm
1 change: 1 addition & 0 deletions test/fixtures/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "4.99.101",
"productName": "MainJS",
"dependencies": {
"@types/node": "^8.0.0",
"run-series": "^1.1.1"
},
"//": "ncp used to test https://github.com/electron-userland/electron-packager/pull/186",
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/electron-in-dependencies/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!DOCTYPE html>
<html>
<body>Hello, world!</body>
</html>
1 change: 1 addition & 0 deletions test/fixtures/electron-in-dependencies/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
'use strict'
8 changes: 8 additions & 0 deletions test/fixtures/electron-in-dependencies/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"main": "main.js",
"productName": "MainJS",
"description": "Removing electron from dependencies",
"dependencies": {
"electron": "1.3.1"
}
}
Loading

0 comments on commit f178740

Please sign in to comment.