Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGar <gar+gh@danger.computer>2021-02-25 02:54:50 +0300
committerRuy Adorno <ruyadorno@hotmail.com>2021-03-05 00:05:08 +0300
commit4a5dd3a5a200b3f4f7b47168497d8e03dca3a2ca (patch)
treed34a1ea229b719c3cfbdce85899ceaf67b43e7ab /lib/help.js
parentb33c760cea7fe2696d35b5530abc1b455980fef1 (diff)
fix(npm) pass npm context everywhere
Instead of files randomly requiring the npm singleton, we pass it where it needs to go so that tests don't need to do so much require mocking everywhere PR-URL: https://github.com/npm/cli/pull/2772 Credit: @wraithgar Close: #2772 Reviewed-by: @ruyadorno
Diffstat (limited to 'lib/help.js')
-rw-r--r--lib/help.js357
1 files changed, 195 insertions, 162 deletions
diff --git a/lib/help.js b/lib/help.js
index 6f215c76c..d7897326f 100644
--- a/lib/help.js
+++ b/lib/help.js
@@ -1,191 +1,224 @@
-
-module.exports = help
-
-help.completion = async (opts) => {
- if (opts.conf.argv.remain.length > 2)
- return []
- const g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]')
- const files = await new Promise((resolve, reject) => {
- glob(g, function (er, files) {
- if (er)
- return reject(er)
- resolve(files)
- })
- })
-
- return Object.keys(files.reduce(function (acc, file) {
- file = path.basename(file).replace(/\.[0-9]+$/, '')
- file = file.replace(/^npm-/, '')
- acc[file] = true
- return acc
- }, { help: true }))
-}
-
const npmUsage = require('./utils/npm-usage.js')
const { spawn } = require('child_process')
const path = require('path')
-const npm = require('./npm.js')
const log = require('npmlog')
-const openUrl = require('./utils/open-url')
+const openUrl = require('./utils/open-url.js')
const glob = require('glob')
const output = require('./utils/output.js')
const usage = require('./utils/usage.js')
-help.usage = usage('help', 'npm help <term> [<terms..>]')
-
-function help (args, cb) {
- const argv = npm.config.parsedArgv.cooked
-
- let argnum = 0
- if (args.length === 2 && ~~args[0])
- argnum = ~~args.shift()
-
- // npm help foo bar baz: search topics
- if (args.length > 1 && args[0])
- return npm.commands['help-search'](args, cb)
+class Help {
+ constructor (npm) {
+ this.npm = npm
+ }
- const affordances = {
- 'find-dupes': 'dedupe',
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
+ get usage () {
+ return usage('help', 'npm help <term> [<terms..>]')
}
- let section = affordances[args[0]] || npm.deref(args[0]) || args[0]
- // npm help <noargs>: show basic usage
- if (!section) {
- npmUsage(argv[0] === 'help')
- return cb()
+ async completion (opts) {
+ if (opts.conf.argv.remain.length > 2)
+ return []
+ const g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]')
+ const files = await new Promise((resolve, reject) => {
+ glob(g, function (er, files) {
+ if (er)
+ return reject(er)
+ resolve(files)
+ })
+ })
+
+ return Object.keys(files.reduce(function (acc, file) {
+ file = path.basename(file).replace(/\.[0-9]+$/, '')
+ file = file.replace(/^npm-/, '')
+ acc[file] = true
+ return acc
+ }, { help: true }))
}
- // npm <command> -h: show command usage
- if (npm.config.get('usage') &&
- npm.commands[section] &&
- npm.commands[section].usage) {
- npm.config.set('loglevel', 'silent')
- log.level = 'silent'
- output(npm.commands[section].usage)
- return cb()
+ exec (args, cb) {
+ this.help(args).then(() => cb()).catch(cb)
}
- let pref = [1, 5, 7]
- if (argnum)
- pref = [argnum].concat(pref.filter(n => n !== argnum))
-
- // npm help <section>: Try to find the path
- const manroot = path.resolve(__dirname, '..', 'man')
-
- // legacy
- if (section === 'global')
- section = 'folders'
- else if (section.match(/.*json/))
- section = section.replace('.json', '-json')
-
- // find either /section.n or /npm-section.n
- // The glob is used in the glob. The regexp is used much
- // further down. Globs and regexps are different
- const compextglob = '.+(gz|bz2|lzma|[FYzZ]|xz)'
- const compextre = '\\.(gz|bz2|lzma|[FYzZ]|xz)$'
- const f = '+(npm-' + section + '|' + section + ').[0-9]?(' + compextglob + ')'
- return glob(manroot + '/*/' + f, (er, mans) => {
- if (er)
- return cb(er)
-
- if (!mans.length)
- return npm.commands['help-search'](args, cb)
-
- mans = mans.map((man) => {
- const ext = path.extname(man)
- if (man.match(new RegExp(compextre)))
- man = path.basename(man, ext)
-
- return man
+ async help (args) {
+ const argv = this.npm.config.parsedArgv.cooked
+
+ let argnum = 0
+ if (args.length === 2 && ~~args[0])
+ argnum = ~~args.shift()
+
+ // npm help foo bar baz: search topics
+ if (args.length > 1 && args[0])
+ return this.helpSearch(args)
+
+ const affordances = {
+ 'find-dupes': 'dedupe',
+ }
+ let section = affordances[args[0]] || this.npm.deref(args[0]) || args[0]
+
+ // npm help <noargs>: show basic usage
+ if (!section) {
+ npmUsage(this.npm, argv[0] === 'help')
+ return
+ }
+
+ // npm <command> -h: show command usage
+ if (this.npm.config.get('usage') &&
+ this.npm.commands[section] &&
+ this.npm.commands[section].usage) {
+ this.npm.config.set('loglevel', 'silent')
+ log.level = 'silent'
+ output(this.npm.commands[section].usage)
+ return
+ }
+
+ let pref = [1, 5, 7]
+ if (argnum)
+ pref = [argnum].concat(pref.filter(n => n !== argnum))
+
+ // npm help <section>: Try to find the path
+ const manroot = path.resolve(__dirname, '..', 'man')
+
+ // legacy
+ if (section === 'global')
+ section = 'folders'
+ else if (section.match(/.*json/))
+ section = section.replace('.json', '-json')
+
+ // find either /section.n or /npm-section.n
+ // The glob is used in the glob. The regexp is used much
+ // further down. Globs and regexps are different
+ const compextglob = '.+(gz|bz2|lzma|[FYzZ]|xz)'
+ const compextre = '\\.(gz|bz2|lzma|[FYzZ]|xz)$'
+ const f = '+(npm-' + section + '|' + section + ').[0-9]?(' + compextglob + ')'
+ return new Promise((resolve, reject) => {
+ glob(manroot + '/*/' + f, async (er, mans) => {
+ if (er)
+ return reject(er)
+
+ if (!mans.length) {
+ this.helpSearch(args).then(resolve).catch(reject)
+ return
+ }
+
+ mans = mans.map((man) => {
+ const ext = path.extname(man)
+ if (man.match(new RegExp(compextre)))
+ man = path.basename(man, ext)
+
+ return man
+ })
+
+ this.viewMan(this.pickMan(mans, pref), (err) => {
+ if (err)
+ return reject(err)
+ return resolve()
+ })
+ })
})
+ }
- viewMan(pickMan(mans, pref), cb)
- })
-}
-
-function pickMan (mans, pref_) {
- const nre = /([0-9]+)$/
- const pref = {}
- pref_.forEach((sect, i) => pref[sect] = i)
- mans = mans.sort((a, b) => {
- const an = a.match(nre)[1]
- const bn = b.match(nre)[1]
- return an === bn ? (a > b ? -1 : 1)
- : pref[an] < pref[bn] ? -1
- : 1
- })
- return mans[0]
-}
+ helpSearch (args) {
+ return new Promise((resolve, reject) => {
+ this.npm.commands['help-search'](args, (err) => {
+ // This would only error if args was empty, which it never is
+ /* istanbul ignore next */
+ if (err)
+ return reject(err)
-function viewMan (man, cb) {
- const nre = /([0-9]+)$/
- const num = man.match(nre)[1]
- const section = path.basename(man, '.' + num)
-
- // at this point, we know that the specified man page exists
- const manpath = path.join(__dirname, '..', 'man')
- const env = {}
- Object.keys(process.env).forEach(function (i) {
- env[i] = process.env[i]
- })
- env.MANPATH = manpath
- const viewer = npm.config.get('viewer')
-
- const opts = {
- env,
- stdio: 'inherit',
+ resolve()
+ })
+ })
}
- let bin = 'man'
- const args = []
- switch (viewer) {
- case 'woman':
- bin = 'emacsclient'
- args.push('-e', `(woman-find-file '${man}')`)
- break
-
- case 'browser':
- bin = false
- try {
- const url = htmlMan(man)
- openUrl(url, 'help available at the following URL', cb)
- } catch (err) {
- return cb(err)
- }
- break
-
- default:
- args.push(num, section)
- break
+ pickMan (mans, pref_) {
+ const nre = /([0-9]+)$/
+ const pref = {}
+ pref_.forEach((sect, i) => pref[sect] = i)
+ mans = mans.sort((a, b) => {
+ const an = a.match(nre)[1]
+ const bn = b.match(nre)[1]
+ return an === bn ? (a > b ? -1 : 1)
+ : pref[an] < pref[bn] ? -1
+ : 1
+ })
+ return mans[0]
}
- if (bin) {
- const proc = spawn(bin, args, opts)
- proc.on('exit', (code) => {
- if (code)
- return cb(new Error(`help process exited with code: ${code}`))
+ viewMan (man, cb) {
+ const nre = /([0-9]+)$/
+ const num = man.match(nre)[1]
+ const section = path.basename(man, '.' + num)
- return cb()
+ // at this point, we know that the specified man page exists
+ const manpath = path.join(__dirname, '..', 'man')
+ const env = {}
+ Object.keys(process.env).forEach(function (i) {
+ env[i] = process.env[i]
})
+ env.MANPATH = manpath
+ const viewer = this.npm.config.get('viewer')
+
+ const opts = {
+ env,
+ stdio: 'inherit',
+ }
+
+ let bin = 'man'
+ const args = []
+ switch (viewer) {
+ case 'woman':
+ bin = 'emacsclient'
+ args.push('-e', `(woman-find-file '${man}')`)
+ break
+
+ case 'browser':
+ bin = false
+ try {
+ const url = this.htmlMan(man)
+ openUrl(this.npm, url, 'help available at the following URL').then(
+ () => cb()
+ ).catch(cb)
+ } catch (err) {
+ cb(err)
+ }
+ break
+
+ default:
+ args.push(num, section)
+ break
+ }
+
+ if (bin) {
+ const proc = spawn(bin, args, opts)
+ proc.on('exit', (code) => {
+ if (code)
+ return cb(new Error(`help process exited with code: ${code}`))
+
+ return cb()
+ })
+ }
}
-}
-function htmlMan (man) {
- let sect = +man.match(/([0-9]+)$/)[1]
- const f = path.basename(man).replace(/[.]([0-9]+)$/, '')
- switch (sect) {
- case 1:
- sect = 'commands'
- break
- case 5:
- sect = 'configuring-npm'
- break
- case 7:
- sect = 'using-npm'
- break
- default:
- throw new Error('invalid man section: ' + sect)
+ htmlMan (man) {
+ let sect = +man.match(/([0-9]+)$/)[1]
+ const f = path.basename(man).replace(/[.]([0-9]+)$/, '')
+ switch (sect) {
+ case 1:
+ sect = 'commands'
+ break
+ case 5:
+ sect = 'configuring-npm'
+ break
+ case 7:
+ sect = 'using-npm'
+ break
+ default:
+ throw new Error('invalid man section: ' + sect)
+ }
+ return 'file://' + path.resolve(__dirname, '..', 'docs', 'output', sect, f + '.html')
}
- return 'file://' + path.resolve(__dirname, '..', 'docs', 'output', sect, f + '.html')
}
+module.exports = Help