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:
-rw-r--r--docs/content/cli-commands/npm-build.md34
-rw-r--r--lib/build.js140
-rw-r--r--lib/config/cmd-list.js2
-rw-r--r--lib/rebuild.js112
-rw-r--r--lib/unbuild.js137
5 files changed, 45 insertions, 380 deletions
diff --git a/docs/content/cli-commands/npm-build.md b/docs/content/cli-commands/npm-build.md
deleted file mode 100644
index eca5397d9..000000000
--- a/docs/content/cli-commands/npm-build.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-section: cli-commands
-title: npm-build
-description: Build a package
----
-
-# npm-build(1)
-
-## Build a package
-
-### Synopsis
-```shell
-npm build [<package-folder>]
-```
-
-* `<package-folder>`:
- A folder containing a `package.json` file in its root.
-
-### Description
-
-This is the plumbing command called by `npm link` and `npm install`.
-
-It should generally be called during installation, but if you need to run it
-directly, run:
-```bash
- npm run-script build
-```
-
-### See Also
-
-* [npm install](/cli-commands/install)
-* [npm link](/cli-commands/link)
-* [npm scripts](/using-npm/scripts)
-* [package.json](/configuring-npm/package-json)
diff --git a/lib/build.js b/lib/build.js
deleted file mode 100644
index f8b3c4933..000000000
--- a/lib/build.js
+++ /dev/null
@@ -1,140 +0,0 @@
-// npm build command
-
-// everything about the installation after the creation of
-// the .npm/{name}/{version}/package folder.
-// linking the modules into the npm.root,
-// resolving dependencies, etc.
-
-// This runs AFTER install or link are completed.
-
-var npm = require('./npm.js')
-var log = require('npmlog')
-var chain = require('slide').chain
-var path = require('path')
-var fs = require('graceful-fs')
-var lifecycle = require('./utils/lifecycle.js')
-var readJson = require('read-package-json')
-var binLinks = require('bin-links')
-var binLinksConfig = require('./config/bin-links.js')
-var ini = require('ini')
-var writeFile = require('write-file-atomic')
-
-module.exports = build
-build.usage = 'npm build [<folder>]'
-
-build._didBuild = {}
-build._noLC = {}
-function build (args, global, didPre, didRB, cb) {
- if (typeof cb !== 'function') {
- cb = didRB
- didRB = false
- }
- if (typeof cb !== 'function') {
- cb = didPre
- didPre = false
- }
- if (typeof cb !== 'function') {
- cb = global
- global = npm.config.get('global')
- }
-
- if (!args.length) {
- readJson(path.resolve(npm.localPrefix, 'package.json'), function (er, pkg) {
- if (!args.length && pkg && pkg.scripts && pkg.scripts.build) {
- log.warn('build', '`npm build` called with no arguments. Did you mean to `npm run-script build`?')
- }
- cb()
- })
- } else {
- // it'd be nice to asyncMap these, but actually, doing them
- // in parallel generally munges up the output from node-waf
- var builder = build_(global, didPre, didRB)
- chain(args.map(function (arg) {
- return function (cb) {
- builder(arg, cb)
- }
- }), cb)
- }
-}
-
-function build_ (global, didPre, didRB) {
- return function (folder, cb) {
- folder = path.resolve(folder)
- if (build._didBuild[folder]) log.info('build', 'already built', folder)
- build._didBuild[folder] = true
- log.info('build', folder)
- readJson(path.resolve(folder, 'package.json'), function (er, pkg) {
- if (er) return cb(er)
- chain([
- !didPre && [lifecycle, pkg, 'preinstall', folder],
- [linkStuff, pkg, folder, global],
- !didRB && [rebuildBundles, pkg, folder],
- [writeBuiltinConf, pkg, folder],
- didPre !== build._noLC && [lifecycle, pkg, 'install', folder],
- didPre !== build._noLC && [lifecycle, pkg, 'postinstall', folder]
- ],
- cb)
- })
- }
-}
-
-var writeBuiltinConf = build.writeBuiltinConf = function (pkg, folder, cb) {
- // the builtin config is "sticky". Any time npm installs
- // itself globally, it puts its builtin config file there
- var parent = path.dirname(folder)
- var dir = npm.globalDir
-
- // Make this count for canary, too
- if ((pkg.name !== 'npm' && pkg.name !== 'npmc') ||
- !npm.config.get('global') ||
- !npm.config.usingBuiltin ||
- dir !== parent) {
- return cb()
- }
-
- var data = ini.stringify(npm.config.sources.builtin.data)
- writeFile(path.resolve(folder, 'npmrc'), data, cb)
-}
-
-var linkStuff = build.linkStuff = function (pkg, folder, global, cb) {
- // allow to opt out of linking binaries.
- if (npm.config.get('bin-links') === false) return cb()
- return binLinks(pkg, folder, global, binLinksConfig(pkg), cb)
-}
-
-function rebuildBundles (pkg, folder, cb) {
- if (!npm.config.get('rebuild-bundle')) return cb()
-
- var deps = Object.keys(pkg.dependencies || {})
- .concat(Object.keys(pkg.devDependencies || {}))
- var bundles = pkg.bundleDependencies || pkg.bundledDependencies || []
-
- fs.readdir(path.resolve(folder, 'node_modules'), function (er, files) {
- // error means no bundles
- if (er) return cb()
-
- log.verbose('rebuildBundles', files)
- // don't asyncMap these, because otherwise build script output
- // gets interleaved and is impossible to read
- chain(files.filter(function (file) {
- // rebuild if:
- // not a .folder, like .bin or .hooks
- return !file.match(/^[._-]/) &&
- // not some old 0.x style bundle
- file.indexOf('@') === -1 &&
- // either not a dep, or explicitly bundled
- (deps.indexOf(file) === -1 || bundles.indexOf(file) !== -1)
- }).map(function (file) {
- file = path.resolve(folder, 'node_modules', file)
- return function (cb) {
- if (build._didBuild[file]) return cb()
- log.verbose('rebuild bundle', file)
- // if file is not a package dir, then don't do it.
- fs.lstat(path.resolve(file, 'package.json'), function (er) {
- if (er) return cb()
- build_(false)(file, cb)
- })
- }
- }), cb)
- })
-}
diff --git a/lib/config/cmd-list.js b/lib/config/cmd-list.js
index a8a977110..5dad17ad0 100644
--- a/lib/config/cmd-list.js
+++ b/lib/config/cmd-list.js
@@ -123,8 +123,6 @@ var cmdList = [
]
var plumbing = [
- 'build',
- 'unbuild',
'xmas',
'substack',
'visnup'
diff --git a/lib/rebuild.js b/lib/rebuild.js
index bbc5e8f48..df1d29566 100644
--- a/lib/rebuild.js
+++ b/lib/rebuild.js
@@ -1,78 +1,56 @@
+const Arborist = require('@npmcli/arborist')
+const npm = require('./npm.js')
+const usageUtil = require('./utils/usage.js')
+const { resolve } = require('path')
+const output = require('./utils/output.js')
+const npa = require('npm-package-arg')
+const semver = require('semver')
-module.exports = rebuild
+const cmd = (args, cb) => rebuild(args).then(() => cb()).catch(cb)
-var readInstalled = require('read-installed')
-var semver = require('semver')
-var log = require('npmlog')
-var npm = require('./npm.js')
-var npa = require('npm-package-arg')
-var usage = require('./utils/usage')
-var output = require('./utils/output.js')
+const usage = usageUtil('rebuild', 'npm rebuild [[<@scope>/]<name>[@<version>] ...]')
-rebuild.usage = usage(
- 'rebuild',
- 'npm rebuild [[<@scope>/<name>]...]'
-)
+const completion = require('./utils/completion/installed-deep.js')
-rebuild.completion = require('./utils/completion/installed-deep.js')
+const rebuild = async args => {
+ const globalTop = resolve(npm.globalDir, '..')
+ const where = npm.flatOptions.global ? globalTop : npm.prefix
+ const arb = new Arborist({
+ ...npm.flatOptions,
+ path: where
+ })
-function rebuild (args, cb) {
- var opt = { depth: npm.config.get('depth'), dev: true }
- readInstalled(npm.prefix, opt, function (er, data) {
- log.info('readInstalled', typeof data)
- if (er) return cb(er)
- var set = filter(data, args)
- var folders = Object.keys(set).filter(function (f) {
- return f !== npm.prefix
+ if (args.length) {
+ // get the set of nodes matching the name that we want rebuilt
+ const tree = await arb.loadActual()
+ const filter = getFilterFn(args)
+ await arb.rebuild({
+ nodes: tree.inventory.filter(filter)
})
- if (!folders.length) return cb()
- log.silly('rebuild set', folders)
- cleanBuild(folders, set, cb)
- })
-}
+ } else {
+ await arb.rebuild()
+ }
-function cleanBuild (folders, set, cb) {
- npm.commands.build(folders, function (er) {
- if (er) return cb(er)
- output(folders.map(function (f) {
- return set[f] + ' ' + f
- }).join('\n'))
- cb()
- })
+ output('rebuilt dependencies successfully')
}
-function filter (data, args, set, seen) {
- if (!set) set = {}
- if (!seen) seen = new Set()
- if (set.hasOwnProperty(data.path)) return set
- if (seen.has(data)) return set
- seen.add(data)
- var pass
- if (!args.length) pass = true // rebuild everything
- else if (data.name && data._id) {
- for (var i = 0, l = args.length; i < l; i++) {
- var arg = args[i]
- var nv = npa(arg)
- var n = nv.name
- var v = nv.rawSpec
- if (n !== data.name) continue
- if (!semver.satisfies(data.version, v, true)) continue
- pass = true
- break
- }
- }
- if (pass && data._id) {
- log.verbose('rebuild', 'path, id', [data.path, data._id])
- set[data.path] = data._id
- }
- // need to also dive through kids, always.
- // since this isn't an install these won't get auto-built unless
- // they're not dependencies.
- Object.keys(data.dependencies || {}).forEach(function (d) {
- // return
- var dep = data.dependencies[d]
- if (typeof dep === 'string') return
- filter(dep, args, set, seen)
+const getFilterFn = args => {
+ const specs = args.map(arg => {
+ const spec = npa(arg)
+ if (spec.type === 'tag' && spec.rawSpec === '')
+ return spec
+ if (spec.type !== 'range' && spec.type !== 'version')
+ throw new Error('`npm rebuild` only supports SemVer version/range specifiers')
+ return spec
+ })
+ return node => specs.some(spec => {
+ const { version } = node.package
+ if (spec.name !== node.name)
+ return false
+ if (spec.rawSpec === '' || spec.rawSpec === '*')
+ return true
+ return semver.satisfies(version, spec.fetchSpec)
})
- return set
}
+
+module.exports = Object.assign(cmd, { usage, completion })
diff --git a/lib/unbuild.js b/lib/unbuild.js
deleted file mode 100644
index 3e8d3e4f1..000000000
--- a/lib/unbuild.js
+++ /dev/null
@@ -1,137 +0,0 @@
-module.exports = unbuild
-module.exports.rmStuff = rmStuff
-unbuild.usage = 'npm unbuild <folder>\n(this is plumbing)'
-
-const readJson = require('read-package-json')
-const gentlyRm = require('./utils/gently-rm.js')
-const npm = require('./npm.js')
-const path = require('path')
-const isInside = require('path-is-inside')
-const lifecycle = require('./utils/lifecycle.js')
-const asyncMap = require('slide').asyncMap
-const chain = require('slide').chain
-const log = require('npmlog')
-const build = require('./build.js')
-const output = require('./utils/output.js')
-
-// args is a list of folders.
-// remove any bins/etc, and then delete the folder.
-function unbuild (args, silent, cb) {
- if (typeof silent === 'function') {
- cb = silent
- silent = false
- }
- asyncMap(args, unbuild_(silent), cb)
-}
-
-function unbuild_ (silent) {
- return function (folder, cb_) {
- function cb (er) {
- cb_(er, path.relative(npm.root, folder))
- }
- folder = path.resolve(folder)
- const base = isInside(folder, npm.prefix) ? npm.prefix : folder
- delete build._didBuild[folder]
- log.verbose('unbuild', folder.substr(npm.prefix.length + 1))
- readJson(path.resolve(folder, 'package.json'), function (er, pkg) {
- // if no json, then just trash it, but no scripts or whatever.
- if (er) return gentlyRm(folder, false, base, cb)
- chain(
- [
- [lifecycle, pkg, 'preuninstall', folder, { failOk: true }],
- [lifecycle, pkg, 'uninstall', folder, { failOk: true }],
- !silent && function (cb) {
- output('unbuild ' + pkg._id)
- cb()
- },
- [rmStuff, pkg, folder],
- [lifecycle, pkg, 'postuninstall', folder, { failOk: true }],
- [gentlyRm, folder, false, base]
- ],
- cb
- )
- })
- }
-}
-
-function rmStuff (pkg, folder, cb) {
- // if it's global, and folder is in {prefix}/node_modules,
- // then bins are in {prefix}/bin
- // otherwise, then bins are in folder/../.bin
- const dir = path.dirname(folder)
- const scope = path.basename(dir)
- const parent = scope.charAt(0) === '@' ? path.dirname(dir) : dir
- const gnm = npm.dir
- // gnm might be an absolute path, parent might be relative
- // this checks they're the same directory regardless
- const top = path.relative(gnm, parent) === ''
-
- log.verbose('unbuild rmStuff', pkg._id, 'from', gnm)
- if (!top) log.verbose('unbuild rmStuff', 'in', parent)
- asyncMap([rmBins, rmMans], function (fn, cb) {
- fn(pkg, folder, parent, top, cb)
- }, cb)
-}
-
-function rmBins (pkg, folder, parent, top, cb) {
- if (!pkg.bin) return cb()
- const binRoot = top ? npm.bin : path.resolve(parent, '.bin')
- asyncMap(Object.keys(pkg.bin), function (b, cb) {
- if (process.platform === 'win32') {
- chain([
- [gentlyRm, path.resolve(binRoot, b) + '.ps1', true, folder],
- [gentlyRm, path.resolve(binRoot, b) + '.cmd', true, folder],
- [gentlyRm, path.resolve(binRoot, b), true, folder]
- ], cb)
- } else {
- gentlyRm(path.resolve(binRoot, b), true, folder, cb)
- }
- }, gentlyRmBinRoot)
-
- function gentlyRmBinRoot (err) {
- if (err || top) return cb(err)
- return gentlyRm(binRoot, true, parent, cb)
- }
-}
-
-function rmMans (pkg, folder, parent, top, cb) {
- if (!pkg.man ||
- !top ||
- process.platform === 'win32' ||
- !npm.config.get('global')) {
- return cb()
- }
- const manRoot = path.resolve(npm.config.get('prefix'), 'share', 'man')
- log.verbose('rmMans', 'man files are', pkg.man, 'in', manRoot)
- asyncMap(pkg.man, function (man, cb) {
- if (Array.isArray(man)) {
- man.forEach(rmMan)
- } else {
- rmMan(man)
- }
-
- function rmMan (man) {
- log.silly('rmMan', 'preparing to remove', man)
- const parseMan = man.match(/(.*\.([0-9]+)(\.gz)?)$/)
- if (!parseMan) {
- log.error(
- 'rmMan', man, 'is not a valid name for a man file.',
- 'Man files must end with a number, ' +
- 'and optionally a .gz suffix if they are compressed.'
- )
- return cb()
- }
-
- const stem = parseMan[1]
- const sxn = parseMan[2]
- const gz = parseMan[3] || ''
- const bn = path.basename(stem)
- const manDest = path.join(
- manRoot,
- 'man' + sxn,
- (bn.indexOf(pkg.name) === 0 ? bn : pkg.name + '-' + bn) + '.' + sxn + gz
- )
- gentlyRm(manDest, true, cb)
- }
- }, cb)
-}