Skip to content

Commit

Permalink
Merge pull request #99 from electron-userland/common-dependencies
Browse files Browse the repository at this point in the history
Add minimal Electron dependencies
  • Loading branch information
fcastilloec authored Dec 30, 2018
2 parents e5eff39 + 34bfdad commit 80b40f2
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 17 deletions.
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@

## Requirements

This tool requires Node 6 or greater and `rpmbuild` to build the `.rpm` package. On Fedora you can do something like this:
This tool requires Node 6 or greater and `rpmbuild` to build the `.rpm` package.

**Note**: If your application uses the [Electron API's `shell.moveItemToTrash` method](https://electronjs.org/docs/api/shell#shellmoveitemtotrashfullpath), RPM 4.13.0 or greater is required, due to the [boolean dependency feature](http://rpm.org/user_doc/boolean_dependencies.html).

On Fedora you can do something like this:

```
$ sudo dnf install rpm-build
```

While on Ubuntu you'll need to do this instead:
While on Debian/Ubuntu you'll need to do this instead:

```
$ sudo apt-get install rpm
```
In order to use [boolean dependencies](http://rpm.org/user_doc/boolean_dependencies.html),`rpm >= 4.13` is required.

## Installation

Expand Down Expand Up @@ -272,10 +275,12 @@ Machine architecture the package is targeted to, used to set the `--target` opti

#### options.requires
Type: `Array[String]`
Default: `["lsb", "libXScrnSaver"]`
Default: The minimum list of packages needed for Electron to run

Packages that are required when the program starts, used in the [`Requires` field of the `spec` file](https://fedoraproject.org/wiki/How_to_create_an_RPM_package#Creating_a_SPEC_file).

All user requirements will be appended to the default array of requirements, and any duplicates will be removed.

#### options.homepage
Type: `String`
Default: `package.homepage || package.author.url`
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"dependencies": {
"debug": "^3.1.0",
"electron-installer-common": "^0.2.0",
"electron-installer-common": "^0.4.0",
"fs-extra": "^5.0.0",
"lodash": "^4.17.4",
"nodeify": "^1.0.1",
Expand All @@ -53,6 +53,7 @@
"eslint-plugin-standard": "^3.0.1",
"mocha": "^5.0.4",
"mz": "^2.7.0",
"promise-retry": "^1.1.1"
"promise-retry": "^1.1.1",
"sinon": "^7.2.2"
}
}
75 changes: 75 additions & 0 deletions src/dependencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use strict'

const dependencies = require('electron-installer-common/src/dependencies')
const spawn = require('./spawn')

const dependencyMap = {
gconf: 'GConf2',
glib2: 'glib2',
gtk2: 'gtk2',
gtk3: 'gtk3',
gvfs: 'gvfs-client',
kdeCliTools: 'kde-cli-tools',
kdeRuntime: 'kde-runtime',
notify: 'libnotify',
nss: 'nss',
trashCli: 'trash-cli',
uuid: 'libuuid',
xdgUtils: 'xdg-utils',
xss: 'libXScrnSaver',
xtst: 'libXtst'
}

/**
* Retrieves the RPM version number and determines whether it has support for boolean
* dependencies (>= 4.13.0).
*/
function rpmSupportsBooleanDependencies (logger) {
return spawn('rpmbuild', ['--version'], logger)
.then(output => rpmVersionSupportsBooleanDependencies(output.trim().split(' ')[2]))
}

/**
* Determine whether the RPM version string has support for boolean dependencies (>= 4.13.0).
*
* RPM does not follow semantic versioning, so `semver` cannot be used.
*/
function rpmVersionSupportsBooleanDependencies (rpmVersionString) {
const rpmVersion = rpmVersionString.split('.').slice(0, 3).map(n => parseInt(n))
return rpmVersion >= [4, 13, 0]
}

/**
* Transforms the list of trash requires into an RPM boolean dependency list.
*/
function trashRequiresAsBoolean (electronVersion, dependencyMap) {
const trashDepends = dependencies.getTrashDepends(electronVersion, dependencyMap)
if (trashDepends.length === 1) {
return [trashDepends[0]]
} else {
return [`(${trashDepends.join(' or ')})`]
}
}

module.exports = {
dependencyMap,
/**
* The dependencies for Electron itself, given an Electron version.
*/
forElectron: function dependenciesForElectron (electronVersion, logger) {
const requires = dependencies.getDepends(electronVersion, dependencyMap)
return module.exports.rpmSupportsBooleanDependencies(logger)
.then(supportsBooleanDependencies => {
if (supportsBooleanDependencies) {
const trashRequires = trashRequiresAsBoolean(electronVersion, dependencyMap)
return { requires: requires.concat(trashRequires) }
} else {
console.warn("You are using RPM < 4.13, which does not support boolean dependencies. This is required to express the dependencies needed for the 'shell.moveItemToTrash' API.\nIf you do not use this API, you can safely ignore this warning.\nIf you do use this API, please upgrade to RPM 4.13 or above to have the trash dependencies added to your RPM's requires section.")
return { requires }
}
})
},
rpmSupportsBooleanDependencies,
rpmVersionSupportsBooleanDependencies,
trashRequiresAsBoolean
}
20 changes: 10 additions & 10 deletions src/installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ const dependencies = require('electron-installer-common/src/dependencies')
const fs = require('fs-extra')
const nodeify = require('nodeify')
const path = require('path')
const readElectronVersion = require('electron-installer-common/src/readelectronversion')
const wrap = require('word-wrap')

const redhatDependencies = require('./dependencies')
const spawn = require('./spawn')
const util = require('./util')

Expand All @@ -23,26 +25,24 @@ const defaultRename = function (dest, src) {
* read from `package.json`, and some are hardcoded.
*/
const getDefaults = function (data) {
return common.readMeta(data)
.then(pkg => {
pkg = pkg || {}
return readElectronVersion(data.src)
.then(electronVersion => Promise.all([common.readMeta(data), redhatDependencies.forElectron(electronVersion, data.logger)]))
.then(([pkg, requires]) => {
if (!pkg) {
pkg = {}
}

return Object.assign(common.getDefaultsFromPackageJSON(pkg), {
version: pkg.version || '0.0.0',
license: pkg.license,
requires: [
'lsb',
'libXScrnSaver'
],
compressionLevel: 2,
execArguments: [],
icon: path.resolve(__dirname, '../resources/icon.png'),

pre: undefined,
post: undefined,
preun: undefined,
postun: undefined
})
}, requires)
})
}

Expand Down Expand Up @@ -93,7 +93,7 @@ function getOptions (data, defaults) {
*
* See: https://fedoraproject.org/wiki/How_to_create_an_RPM_package
*/
const createSpec = function (options, dir) {
function createSpec (options, dir) {
const specSrc = path.resolve(__dirname, '../resources/spec.ejs')
const specDest = path.join(dir, 'SPECS', options.name + '.spec')
options.logger(`Creating spec file at ${specDest}`)
Expand Down
57 changes: 57 additions & 0 deletions test/dependencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const dependencies = require('../src/dependencies')
const { expect } = require('chai')
const sinon = require('sinon')

describe('dependencies', () => {
describe('forElectron', () => {
beforeEach(() => {
sinon.spy(console, 'warn')
})

afterEach(() => {
sinon.restore()
})

it('uses an RPM that does not support boolean dependencies', () => {
sinon.stub(dependencies, 'rpmSupportsBooleanDependencies').resolves(false)
return dependencies.forElectron('v1.0.0')
.then(result => {
expect(console.warn.calledWithMatch(/^You are using RPM < 4.13/)).to.equal(true)
})
})

it('uses an RPM that supports boolean dependencies', () => {
sinon.stub(dependencies, 'rpmSupportsBooleanDependencies').resolves(true)
return dependencies.forElectron('v1.0.0')
.then(result => {
expect(console.warn.calledWithMatch(/^You are using RPM < 4.13/)).to.equal(false)
})
})
})

describe('rpmVersionSupportsBooleanDependencies', () => {
it('works with release candidates', () => {
expect(dependencies.rpmVersionSupportsBooleanDependencies('4.13.0-rc1')).to.equal(true)
})

it('works with git snapshots', () => {
expect(dependencies.rpmVersionSupportsBooleanDependencies('4.11.90-git12844')).to.equal(false)
})

it('works with 4 part versions (1.2.3.4)', () => {
expect(dependencies.rpmVersionSupportsBooleanDependencies('4.1.12.2')).to.equal(false)
})
})

describe('trashRequiresAsBoolean', () => {
it('does not use parentheses for one item', () => {
const trashDeps = dependencies.trashRequiresAsBoolean('1.0.0', dependencies.dependencyMap)[0]
expect(trashDeps[0]).to.not.match(/^\(/)
})

it('ORs more than one item', () => {
const trashDeps = dependencies.trashRequiresAsBoolean('1.5.0', dependencies.dependencyMap)[0]
expect(trashDeps).to.match(/^\(.* or .*\)$/)
})
})
})
2 changes: 1 addition & 1 deletion test/fixtures/app-without-asar/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.29.2
v1.8.5

0 comments on commit 80b40f2

Please sign in to comment.