Skip to content

Commit

Permalink
New: Adds new info flag (fixes #11958)
Browse files Browse the repository at this point in the history
New: add test case

fix: remove showing up browser information

fix: show up local version of eslint

fix: test

fix: update local package info glob

fix: explicitly return a promise

fix: update local package glob

tweaks

fix: fixup async behavior

fix: update test case

fix: handle promise rejection

fix: revert

switch over to synchronous version

WIP: spike info flag implementation
  • Loading branch information
jamesgeorge007 committed Aug 23, 2019
1 parent f5e0cc4 commit 9806ebc
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 13 deletions.
35 changes: 24 additions & 11 deletions bin/eslint.js
Expand Up @@ -16,9 +16,10 @@ require("v8-compile-cache");
// Helpers
//------------------------------------------------------------------------------

const useStdIn = (process.argv.indexOf("--stdin") > -1),
init = (process.argv.indexOf("--init") > -1),
debug = (process.argv.indexOf("--debug") > -1);
const useStdIn = process.argv.includes("--stdin"),
init = process.argv.includes("--init"),
debug = process.argv.includes("--debug"),
info = process.argv.includes("--info");

// must do this initialization *before* other requires in order to work
if (debug) {
Expand All @@ -30,9 +31,10 @@ if (debug) {
//------------------------------------------------------------------------------

// now we can safely include the other modules that use debug
const cli = require("../lib/cli"),
path = require("path"),
fs = require("fs");
const path = require("path"),
fs = require("fs"),
cli = require("../lib/cli"),
logger = require("../lib/shared/logging");

//------------------------------------------------------------------------------
// Execution
Expand All @@ -47,11 +49,11 @@ process.once("uncaughtException", err => {
const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8"));
const pkg = require("../package.json");

console.error("\nOops! Something went wrong! :(");
console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
logger.error("\nOops! Something went wrong! :(");
logger.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
} else {

console.error(err.stack);
logger.error(err.stack);
}

process.exitCode = 2;
Expand All @@ -67,15 +69,26 @@ if (useStdIn) {
const STDIN_FILE_DESCRIPTOR = 0;

process.exitCode = cli.execute(process.argv, fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8"));
} else if (info) {
const infoLogger = require("../lib/info");

try {
infoLogger.log();
process.exitCode = 0;
} catch (err) {
process.exitCode = 1;
logger.error(err.message);
logger.error(err.stack);
}
} else if (init) {
const configInit = require("../lib/init/config-initializer");

configInit.initializeConfig().then(() => {
process.exitCode = 0;
}).catch(err => {
process.exitCode = 1;
console.error(err.message);
console.error(err.stack);
logger.error(err.message);
logger.error(err.stack);
});
} else {
process.exitCode = cli.execute(process.argv);
Expand Down
21 changes: 19 additions & 2 deletions lib/cli.js
Expand Up @@ -18,6 +18,7 @@
const fs = require("fs"),
path = require("path"),
mkdirp = require("mkdirp"),
{ execSync } = require("child_process"),
{ CLIEngine } = require("./cli-engine"),
options = require("./options"),
log = require("./shared/logging");
Expand Down Expand Up @@ -67,7 +68,8 @@ function translateOptions(cliOptions) {
fixTypes: cliOptions.fixType,
allowInlineConfig: cliOptions.inlineConfig,
reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives,
resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo
resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo,
info: cliOptions.info
};
}

Expand Down Expand Up @@ -165,7 +167,6 @@ const cli = {
if (currentOptions.version) { // version from package.json

log.info(`v${require("../package.json").version}`);

} else if (currentOptions.printConfig) {
if (files.length) {
log.error("The --print-config option must be used with exactly one file name.");
Expand All @@ -182,6 +183,22 @@ const cli = {

log.info(JSON.stringify(fileConfig, null, " "));
return 0;
} else if (currentOptions.info) {
log.info("\n Environment Information:-\n");
const packageInfo = {
node: "node -v",
npm: "npm -v",
eslint: "eslint -v"
};

Object.keys(packageInfo).forEach(pkg => {
try {
log.info(` ${pkg}: ${execSync(packageInfo[pkg])}`);
} catch (err) {

// handle err
}
});
} else if (currentOptions.help || (!files.length && !useStdin)) {

log.info(options.generateHelp());
Expand Down
142 changes: 142 additions & 0 deletions lib/info/index.js
@@ -0,0 +1,142 @@
/**
* @fileoverview Log information for debugging purposes
* @author Kai Cataldo
*/

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const path = require("path");
const spawn = require("cross-spawn");
const { isEmpty } = require("lodash");
const logger = require("../shared/logging");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

const STRIP_VERSION_REGEX = /v(\d)/u;

/**
* Checks if a given path is in a given 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 in the given directory.
*/
function isInDirectory(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.
*/
function execCommand(cmd, args) {
const process = spawn.sync(cmd, args, { encoding: "utf8" });

if (process.error) {
throw process.error;
}

return process.stdout.trim();
}

/**
* Normalizes a version number.
* @param {string} version - The string to normalize.
* @returns {string} The normalized version number.
*/
function normalizeVersionNumber(version) {
return version.replace(STRIP_VERSION_REGEX, "$1");
}

/**
* 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 execCommand(bin, binArgs);
} catch (e) {
logger.error(`Error finding ${bin} version running the command ${bin} ${binArgs.join(" ")}`);
throw e;
}
}

/**
* 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");
}

try {
const parsedStdout = JSON.parse(execCommand("npm", npmLsArgs));

if (isEmpty(parsedStdout)) {
return "Not found";
}

const [, processBinPath] = process.argv;
let npmBinPath;

try {
npmBinPath = execCommand("npm", npmBinArgs);
} catch (e) {
logger.error(`Error finding npm binary path when running command npm ${npmBinArgs.join(" ")}`);
throw e;
}

const isGlobal = isInDirectory(npmBinPath, processBinPath);
let version = parsedStdout.dependencies.eslint.version;

if ((global && isGlobal) || (!global && !isGlobal)) {
version += " (Currently used)";
}

return version;
} catch (e) {
logger.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 generateInfo() {
return [
"Environment Info:",
"",
`Node version: ${normalizeVersionNumber(getBinVersion("node"))}`,
`npm version: ${normalizeVersionNumber(getBinVersion("npm"))}`,
`Local ESLint version: ${normalizeVersionNumber(getNpmPackageVersion("eslint", { global: false }))}`,
`Global ESLint version: ${normalizeVersionNumber(getNpmPackageVersion("eslint", { global: true }))}`
].join("\n");
}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

module.exports = {
log() {
logger.info(generateInfo());
}
};
12 changes: 12 additions & 0 deletions lib/options.js
Expand Up @@ -224,6 +224,12 @@ module.exports = optionator({
default: "false",
description: "Run config initialization wizard"
},
{
option: "info",
type: "Boolean",
default: "false",
description: "Output environment information for debugging purposes"
},
{
option: "debug",
type: "Boolean",
Expand All @@ -246,6 +252,12 @@ module.exports = optionator({
option: "print-config",
type: "path::String",
description: "Print the configuration for the given file"
},
{
option: "info",
alias: "i",
type: "Boolean",
description: "Print debugging information concerning the local environmet"
}
]
});
7 changes: 7 additions & 0 deletions tests/lib/cli.js
Expand Up @@ -1112,4 +1112,11 @@ describe("cli", () => {
});
});

describe("when passing --info", () => {
it("should print out debugging information concerning the local environment", () => {
cli.execute("--info");
assert.isTrue(log.info.called);
});
});

});

0 comments on commit 9806ebc

Please sign in to comment.