From 29c12f18726a3afb21fc89ab1bdacc6972d49e68 Mon Sep 17 00:00:00 2001 From: Kai Cataldo <7041728+kaicataldo@users.noreply.github.com> Date: Fri, 27 Sep 2019 21:49:56 -0400 Subject: [PATCH] Chore: cache results in runtime-info (#12320) --- lib/shared/runtime-info.js | 179 ++++++++++++++++--------------- tests/lib/shared/runtime-info.js | 4 +- 2 files changed, 97 insertions(+), 86 deletions(-) diff --git a/lib/shared/runtime-info.js b/lib/shared/runtime-info.js index 324f457d80b..169bbc58f13 100644 --- a/lib/shared/runtime-info.js +++ b/lib/shared/runtime-info.js @@ -20,110 +20,121 @@ const packageJson = require("../../package.json"); //------------------------------------------------------------------------------ /** - * Checks if a path is a child of a directory. - * @param {string} parentPath - The parent path to check. - * @param {string} childPath - The path to check. - * @returns {boolean} Whether or not the given path is a child of a directory. - */ -function isChildOfDirectory(parentPath, childPath) { - return !path.relative(parentPath, childPath).startsWith(".."); -} - -/** - * Synchronously executes a shell command and formats the result. - * @param {string} cmd - The command to execute. - * @param {Array} args - The arguments to be executed with the command. - * @returns {string} The version returned by the command. + * Generates and returns execution environment information. + * @returns {string} A string that contains execution environment information. */ -function execCommand(cmd, args) { - const process = spawn.sync(cmd, args, { encoding: "utf8" }); - - if (process.error) { - throw process.error; +function environment() { + const cache = new Map(); + + /** + * Checks if a path is a child of a directory. + * @param {string} parentPath - The parent path to check. + * @param {string} childPath - The path to check. + * @returns {boolean} Whether or not the given path is a child of a directory. + */ + function isChildOfDirectory(parentPath, childPath) { + return !path.relative(parentPath, childPath).startsWith(".."); } - return process.stdout.trim(); -} + /** + * Synchronously executes a shell command and formats the result. + * @param {string} cmd - The command to execute. + * @param {Array} args - The arguments to be executed with the command. + * @returns {string} The version returned by the command. + */ + function execCommand(cmd, args) { + const key = [cmd, ...args].join(" "); + + if (cache.has(key)) { + return cache.get(key); + } -/** - * Normalizes a version number. - * @param {string} versionStr - The string to normalize. - * @returns {string} The normalized version number. - */ -function normalizeVersionStr(versionStr) { - return versionStr.startsWith("v") ? versionStr : `v${versionStr}`; -} + const process = spawn.sync(cmd, args, { encoding: "utf8" }); -/** - * Gets bin version. - * @param {string} bin - The bin to check. - * @returns {string} The normalized version returned by the command. - */ -function getBinVersion(bin) { - const binArgs = ["--version"]; - - try { - return normalizeVersionStr(execCommand(bin, binArgs)); - } catch (e) { - log.error(`Error finding ${bin} version running the command \`${bin} ${binArgs.join(" ")}\``); - throw e; - } -} + if (process.error) { + throw process.error; + } -/** - * Gets installed npm package version. - * @param {string} pkg - The package to check. - * @param {boolean} global - Whether to check globally or not. - * @returns {string} The normalized version returned by the command. - */ -function getNpmPackageVersion(pkg, { global = false } = {}) { - const npmBinArgs = ["bin", "-g"]; - const npmLsArgs = ["ls", "--depth=0", "--json", "eslint"]; + const result = process.stdout.trim(); - if (global) { - npmLsArgs.push("-g"); + cache.set(key, result); + return result; } - try { - const parsedStdout = JSON.parse(execCommand("npm", npmLsArgs)); - - /* - * Checking globally returns an empty JSON object, while local checks - * include the name and version of the local project. - */ - if (isEmpty(parsedStdout) || !(parsedStdout.dependencies && parsedStdout.dependencies.eslint)) { - return "Not found"; - } + /** + * Normalizes a version number. + * @param {string} versionStr - The string to normalize. + * @returns {string} The normalized version number. + */ + function normalizeVersionStr(versionStr) { + return versionStr.startsWith("v") ? versionStr : `v${versionStr}`; + } - const [, processBinPath] = process.argv; - let npmBinPath; + /** + * Gets bin version. + * @param {string} bin - The bin to check. + * @returns {string} The normalized version returned by the command. + */ + function getBinVersion(bin) { + const binArgs = ["--version"]; try { - npmBinPath = execCommand("npm", npmBinArgs); + return normalizeVersionStr(execCommand(bin, binArgs)); } catch (e) { - log.error(`Error finding npm binary path when running command \`npm ${npmBinArgs.join(" ")}\``); + log.error(`Error finding ${bin} version running the command \`${bin} ${binArgs.join(" ")}\``); throw e; } + } - const isGlobal = isChildOfDirectory(npmBinPath, processBinPath); - let pkgVersion = parsedStdout.dependencies.eslint.version; - - if ((global && isGlobal) || (!global && !isGlobal)) { - pkgVersion += " (Currently used)"; + /** + * Gets installed npm package version. + * @param {string} pkg - The package to check. + * @param {boolean} global - Whether to check globally or not. + * @returns {string} The normalized version returned by the command. + */ + function getNpmPackageVersion(pkg, { global = false } = {}) { + const npmBinArgs = ["bin", "-g"]; + const npmLsArgs = ["ls", "--depth=0", "--json", "eslint"]; + + if (global) { + npmLsArgs.push("-g"); } - return normalizeVersionStr(pkgVersion); - } catch (e) { - log.error(`Error finding ${pkg} version running the command \`npm ${npmLsArgs.join(" ")}\``); - throw e; + try { + const parsedStdout = JSON.parse(execCommand("npm", npmLsArgs)); + + /* + * Checking globally returns an empty JSON object, while local checks + * include the name and version of the local project. + */ + if (isEmpty(parsedStdout) || !(parsedStdout.dependencies && parsedStdout.dependencies.eslint)) { + return "Not found"; + } + + const [, processBinPath] = process.argv; + let npmBinPath; + + try { + npmBinPath = execCommand("npm", npmBinArgs); + } catch (e) { + log.error(`Error finding npm binary path when running command \`npm ${npmBinArgs.join(" ")}\``); + throw e; + } + + const isGlobal = isChildOfDirectory(npmBinPath, processBinPath); + let pkgVersion = parsedStdout.dependencies.eslint.version; + + if ((global && isGlobal) || (!global && !isGlobal)) { + pkgVersion += " (Currently used)"; + } + + return normalizeVersionStr(pkgVersion); + } catch (e) { + log.error(`Error finding ${pkg} version running the command \`npm ${npmLsArgs.join(" ")}\``); + throw e; + } } -} -/** - * Generates and returns execution environment information. - * @returns {string} A string that contains execution environment information. - */ -function environment() { return [ "Environment Info:", "", diff --git a/tests/lib/shared/runtime-info.js b/tests/lib/shared/runtime-info.js index 77ada8bc78d..c82d416df9c 100644 --- a/tests/lib/shared/runtime-info.js +++ b/tests/lib/shared/runtime-info.js @@ -86,8 +86,7 @@ describe("RuntimeInfo", () => { } } } - `, - NPM_BIN_PATH + ` ]; }); @@ -138,6 +137,7 @@ describe("RuntimeInfo", () => { "version": "1.0.0" } `); + spawnSyncStubArgs.push(NPM_BIN_PATH); setupSpawnSyncStubReturnVals(spawnSyncStub, spawnSyncStubArgs); process.argv[1] = GLOBAL_ESLINT_BIN_PATH;