diff --git a/package.json b/package.json index c059ffd..4206a68 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,8 @@ "eslint-plugin-node": "^10.0.0", "eslint-plugin-promise": "^4.0.1", "eslint-plugin-standard": "^4.0.0", - "nyc": "^14.0.0" + "nyc": "^14.0.0", + "sinon": "^7.5.0" }, "dependencies": { "cross-spawn-promise": "^0.10.1", diff --git a/src/yaml.js b/src/yaml.js index 48ea03e..c62b0fb 100644 --- a/src/yaml.js +++ b/src/yaml.js @@ -22,6 +22,8 @@ const merge = require('lodash.merge') const path = require('path') const pull = require('lodash.pull') const semver = require('semver') +const spawn = require('cross-spawn-promise') +const which = require('which') const yaml = require('js-yaml') const { createDesktopLaunchCommand } = require('./launcher') @@ -73,6 +75,41 @@ class SnapcraftYAML { return this.data.parts[this.appName] } + async detectBase (lsbRelease) { + if (!lsbRelease) { + lsbRelease = 'lsb_release' + } + const lsbReleasePath = await this.findLsbRelease(lsbRelease) + if (!lsbReleasePath) { + debug('Using base: core18 as recommended by the Snapcraft docs') + return 'core18' + } + + const [distro, distroVersion] = await this.detectDistro(lsbReleasePath) + if (distro === 'Ubuntu' && distroVersion === '16.04') { + return 'core' + } + + return 'core18' + } + + async findLsbRelease (lsbRelease) { + try { + return await which(lsbRelease) + } catch (err) { + debug(`Error when looking for lsb_release:\n${err}`) + } + } + + async detectDistro (lsbRelease) { + const output = await spawn(lsbRelease, ['--short', '--id', '--release']) + if (output) { + return output.toString().trim().split('\n') + } + + return [null, null] + } + renameSubtree (parentObject, fromKey, toKey) { parentObject[toKey] = parentObject[fromKey] delete parentObject[fromKey] @@ -174,6 +211,12 @@ class SnapcraftYAML { this.features = merge({}, userSupplied.features || {}) delete userSupplied.features + if (!userSupplied.base) { + // eslint-disable-next-line require-atomic-updates + userSupplied.base = await this.detectBase(userSupplied.lsbRelease) + } + delete userSupplied.lsbRelease + const appConfig = { apps: { electronApp: userSupplied.appConfig || {} } } delete userSupplied.appConfig const appPlugsSlots = { apps: { electronApp: {} } } @@ -213,3 +256,5 @@ module.exports = async function createYamlFromTemplate (snapDir, packageDir, use await yamlData.transform(packageDir, userSupplied) await yamlData.write(path.join(snapDir, 'snap', 'snapcraft.yaml')) } + +module.exports.SnapcraftYAML = SnapcraftYAML diff --git a/test/yaml.js b/test/yaml.js index c555a1b..c9769b9 100644 --- a/test/yaml.js +++ b/test/yaml.js @@ -18,10 +18,13 @@ limitations under the License. const createYamlFromTemplate = require('../src/yaml') const fs = require('fs-extra') const path = require('path') +const sinon = require('sinon') const test = require('ava') const util = require('./_util') const yaml = require('js-yaml') +const SnapcraftYAML = createYamlFromTemplate.SnapcraftYAML + async function createYaml (t, userDefined, electronVersion) { const yamlPath = path.join(t.context.tempDir.name, 'snap', 'snapcraft.yaml') if (typeof electronVersion === 'undefined') { @@ -141,3 +144,41 @@ test('Electron 4 apps require uuid', async t => { const snapcraftYaml = await createYaml(t, { name: 'electronAppName' }, '4.0.0') assertStagedPackage(t, snapcraftYaml, 'libuuid1') }) + +test('base autodetect defaults to core18 when lsb_release is not found', async t => { + const snapcraftYaml = await createYaml(t, { name: 'electronAppName', lsbRelease: '/does/not/exist' }) + t.is(snapcraftYaml.base, 'core18') +}) + +test('base autodetect does not run when it is set by the user', async t => { + const snapcraftYaml = await createYaml(t, { name: 'electronAppName', base: 'bare' }) + t.is(snapcraftYaml.base, 'bare') +}) + +test('base autodetect returns core when Ubuntu 16.04 is detected', async t => { + const yaml = new SnapcraftYAML() + const lsbRelease = sinon.stub(yaml, 'findLsbRelease') + lsbRelease.resolves('lsb_release') + const distro = sinon.stub(yaml, 'detectDistro') + distro.resolves(['Ubuntu', '16.04']) + try { + t.is('core', await yaml.detectBase()) + } finally { + lsbRelease.restore() + distro.restore() + } +}) + +test('base autodetect returns core18 for non-Ubuntu distros', async t => { + const yaml = new SnapcraftYAML() + const lsbRelease = sinon.stub(yaml, 'findLsbRelease') + lsbRelease.resolves('lsb_release') + const distro = sinon.stub(yaml, 'detectDistro') + distro.resolves(['Debian', '10']) + try { + t.is('core18', await yaml.detectBase()) + } finally { + lsbRelease.restore() + distro.restore() + } +})