diff --git a/axioms/licensee.js b/axioms/licensee.js index 473fabb5..96764d19 100644 --- a/axioms/licensee.js +++ b/axioms/licensee.js @@ -4,16 +4,12 @@ const licensee = require('../lib/licensee') const Result = require('../lib/result') -module.exports = function (fileSystem) { +module.exports = async function (fileSystem) { let licenses = [] try { - licenses = licensee.identifyLicensesSync(fileSystem.targetDir) + licenses = await licensee.identifyLicense(fileSystem.targetDir) } catch (error) { - if (error.message === 'Licensee not installed') { - return new Result('Licensee not found in path, only running license-independent rules', [], false) - } else { - return new Result(error.message, [], false) - } + return new Result(error.message, [], false) } return new Result('', licenses.map(l => { return { passed: true, path: l } }), true) } diff --git a/axioms/linguist.js b/axioms/linguist.js index b977aab8..f77695a7 100644 --- a/axioms/linguist.js +++ b/axioms/linguist.js @@ -4,19 +4,15 @@ const linguist = require('../lib/linguist') const Result = require('../lib/result') -module.exports = function (fileSystem) { +module.exports = async function (fileSystem) { const languages = [] try { - var jsonObj = linguist.identifyLanguagesSync(fileSystem.targetDir) + var jsonObj = await linguist.identifyLanguages(fileSystem.targetDir) for (var language in jsonObj) { languages.push(language.toLowerCase()) } } catch (error) { - if (error.message === 'Linguist not installed') { - return new Result('Linguist not found in path, only running language-independent rules', [], false) - } else { - return new Result(error.message, [], false) - } + return new Result(error.message, [], false) } return new Result('', languages.map(l => { return { passed: true, path: l } }), true) } diff --git a/lib/command_exists.js b/lib/command_exists.js new file mode 100644 index 00000000..fb8679a3 --- /dev/null +++ b/lib/command_exists.js @@ -0,0 +1,31 @@ +// Copyright 2017 TODO Group. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +const commandExistsLib = require('command-exists') + +/** + * Checks whether or not a list of commands exists in the + * current environment. Returns the first command that was + * found to exist. + * + * @protected + * @param {string|string[]} command The command or commands to check for. + * @returns {string|null} The first command found to exist, or null of none were found. + */ +async function commandExists (command) { + // convert to array if needed + if (!Array.isArray(command)) { + command = [command] + } + for (const commandString of command) { + try { + await commandExistsLib(commandString) + return commandString + } catch (e) { + // do nothing + } + } + return null +} + +module.exports.commandExists = commandExists diff --git a/lib/licensee.js b/lib/licensee.js index faf5c0d6..acb5e504 100644 --- a/lib/licensee.js +++ b/lib/licensee.js @@ -1,7 +1,7 @@ // Copyright 2018 TODO Group. All rights reserved. // Licensed under the Apache License, Version 2.0. -const isWindows = require('is-windows') +const { commandExists } = require('./command_exists') const spawnSync = require('child_process').spawnSync class Licensee { @@ -11,14 +11,17 @@ class Licensee { * Throws 'Licensee not installed' error if command line of 'licensee' is not available. * * @param {string} targetDir The directory to run licensee on - * @returns {string[]} License identifiers + * @returns {Promise} License identifiers */ - identifyLicensesSync (targetDir) { - const licenseeOutput = spawnSync(isWindows() ? 'licensee.bat' : 'licensee', ['detect', '--json', targetDir]).stdout - if (licenseeOutput == null) { + async identifyLicense (targetDir) { + const command = await commandExists(['licensee', 'licensee.bat']) + if (command === null) { throw new Error('Licensee not installed') } - + const licenseeOutput = spawnSync(command, ['detect', '--json', targetDir]).stdout + if (licenseeOutput == null) { + throw new Error('Error executing licensee') + } const json = licenseeOutput.toString() return JSON.parse(json).licenses.map(function (license) { return license.spdx_id }) } diff --git a/lib/linguist.js b/lib/linguist.js index 56b65848..6d23b636 100644 --- a/lib/linguist.js +++ b/lib/linguist.js @@ -1,8 +1,8 @@ // Copyright 2017 TODO Group. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -const isWindows = require('is-windows') const spawnSync = require('child_process').spawnSync +const { commandExists } = require('./command_exists') class Linguist { /** @@ -12,18 +12,20 @@ class Linguist { * Throws 'Linguist not installed' error if command line of 'linguist' is not available. * * @param {string} targetDir The directory to run linguist on - * @returns {object} The linguist output + * @returns {Promise} The linguist output */ - identifyLanguagesSync (targetDir) { + async identifyLanguages (targetDir) { // Command was renamed in https://github.com/github/linguist/pull/4208 - for (const command of ['github-linguist', 'linguist']) { - const output = spawnSync(isWindows() ? `${command}.bat` : command, [targetDir, '--json']).stdout - if (output !== null) { - return JSON.parse(output.toString()) - } + const command = await commandExists(['github-linguist', 'linguist', 'github-linguist.bat', 'linguist.bat']) + if (command === null) { + throw new Error('Linguist not installed') + } + const output = spawnSync(command, [targetDir, '--json']).stdout + if (output !== null) { + return JSON.parse(output.toString()) + } else { + throw new Error('Execution of linguist failed!') } - - throw new Error('Linguist not installed') } } diff --git a/package-lock.json b/package-lock.json index 611f2c8b..8fbed584 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2527,8 +2527,7 @@ "command-exists": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" }, "commander": { "version": "2.20.3", diff --git a/package.json b/package.json index a5cc5f0d..afcb1ee3 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "dependencies": { "ajv": "^6.12.4", "chalk": "^4.1.0", + "command-exists": "^1.2.9", "emoji-regex": "^9.0.0", "eslint-config-standard": "^14.1.1", "find-config": "^1.0.0", @@ -63,7 +64,6 @@ "chai-as-promised": "^7.1.1", "chai-each": "0.0.1", "chai-string": "^1.5.0", - "command-exists": "^1.2.9", "documentation": "^13.0.2", "eslint": "^7.7.0", "eslint-plugin-jsdoc": "^30.3.0", diff --git a/tests/axioms/licensee_tests.js b/tests/axioms/licensee_tests.js index dba40535..5aa60b06 100644 --- a/tests/axioms/licensee_tests.js +++ b/tests/axioms/licensee_tests.js @@ -15,18 +15,18 @@ describe('licensee', function () { } else { const licenseeAxiom = require('../../axioms/licensee') - it('runs licensee', () => { + it('runs licensee', async () => { const mockFs = { targetDir: path.resolve(__dirname, '../../') } - const res = licenseeAxiom(mockFs) + const res = await licenseeAxiom(mockFs) expect(res.passed).to.equal(true) expect(res.targets).to.have.length(1) expect(res.targets[0].path).to.equal('Apache-2.0') }) - it('returns nothing if no licenses are found', () => { + it('returns nothing if no licenses are found', async () => { const mockFs = { targetDir: path.resolve(__dirname) } - const res = licenseeAxiom(mockFs) + const res = await licenseeAxiom(mockFs) expect(res.passed).to.equal(true) expect(res.targets).to.have.length(0) diff --git a/tests/axioms/linguist_tests.js b/tests/axioms/linguist_tests.js index ddc1818d..bec58e59 100644 --- a/tests/axioms/linguist_tests.js +++ b/tests/axioms/linguist_tests.js @@ -15,9 +15,9 @@ describe('linguist', function () { } else { const linguistAxiom = require('../../axioms/linguist') - it('runs linguist', () => { + it('runs linguist', async () => { const mockFs = { targetDir: path.resolve(__dirname, '../../') } - const res = linguistAxiom(mockFs) + const res = await linguistAxiom(mockFs) expect(res.passed).to.equal(true) expect(res.targets).to.have.length.greaterThan(0)