diff options
author | Kat Marchán <kzm@sykosomatic.org> | 2017-05-26 05:11:21 +0300 |
---|---|---|
committer | Kat Marchán <kzm@sykosomatic.org> | 2017-05-26 06:14:32 +0300 |
commit | 674004c4c5ef50ed303add582351b32e2293b78e (patch) | |
tree | ff03fb23e994b572e87d5feba0922e0fe99f1ef6 /lib | |
parent | db766320bcb8a1012d1f7b9d005718b83d8163c3 (diff) |
lifecycle: added prepack and postpack (#16725)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/config/pacote.js | 95 | ||||
-rw-r--r-- | lib/fetch-package-metadata.js | 9 | ||||
-rw-r--r-- | lib/install/action/extract.js | 5 | ||||
-rw-r--r-- | lib/install/inflate-shrinkwrap.js | 8 | ||||
-rw-r--r-- | lib/pack.js | 118 | ||||
-rw-r--r-- | lib/publish.js | 12 | ||||
-rw-r--r-- | lib/utils/tar.js | 19 |
7 files changed, 143 insertions, 123 deletions
diff --git a/lib/config/pacote.js b/lib/config/pacote.js index 185ee922f..705544fe3 100644 --- a/lib/config/pacote.js +++ b/lib/config/pacote.js @@ -1,26 +1,24 @@ 'use strict' -const BB = require('bluebird') const Buffer = require('safe-buffer').Buffer -const cp = require('child_process') const npm = require('../npm') const log = require('npmlog') -const packToStream = require('../utils/tar').packToStream +let pack const path = require('path') -const pipe = BB.promisify(require('mississippi').pipe) -const readJson = BB.promisify(require('read-package-json')) -const PassThrough = require('stream').PassThrough let effectiveOwner module.exports = pacoteOpts function pacoteOpts (moreOpts) { + if (!pack) { + pack = require('../pack.js') + } const ownerStats = calculateOwner() const opts = { cache: path.join(npm.config.get('cache'), '_cacache'), defaultTag: npm.config.get('tag'), - dirPacker: prepareAndPack, + dirPacker: pack.packGitDep, hashAlgorithm: 'sha1', localAddress: npm.config.get('local-address'), log: log, @@ -108,86 +106,3 @@ function calculateOwner () { return effectiveOwner } - -const PASSTHROUGH_OPTS = [ - 'always-auth', - 'auth-type', - 'ca', - 'cafile', - 'cert', - 'git', - 'local-address', - 'maxsockets', - 'offline', - 'prefer-offline', - 'prefer-online', - 'proxy', - 'https-proxy', - 'registry', - 'send-metrics', - 'sso-poll-frequency', - 'sso-type', - 'strict-ssl' -] - -function prepareAndPack (manifest, dir) { - const stream = new PassThrough() - readJson(path.join(dir, 'package.json')).then((pkg) => { - if (pkg.scripts && pkg.scripts.prepare) { - log.verbose('prepareGitDep', `${manifest._spec}: installing devDeps and running prepare script.`) - const cliArgs = PASSTHROUGH_OPTS.reduce((acc, opt) => { - if (npm.config.get(opt, 'cli') != null) { - acc.push(`--${opt}=${npm.config.get(opt)}`) - } - return acc - }, []) - const child = cp.spawn(process.env.NODE || process.execPath, [ - require.main.filename, - 'install', - '--ignore-prepublish', - '--no-progress', - '--no-save' - ].concat(cliArgs), { - cwd: dir, - env: process.env - }) - let errData = [] - let errDataLen = 0 - let outData = [] - let outDataLen = 0 - child.stdout.on('data', (data) => { - outData.push(data) - outDataLen += data.length - log.gauge.pulse('preparing git package') - }) - child.stderr.on('data', (data) => { - errData.push(data) - errDataLen += data.length - log.gauge.pulse('preparing git package') - }) - return BB.fromNode((cb) => { - child.on('error', cb) - child.on('exit', (code, signal) => { - if (code > 0) { - const err = new Error(`${signal}: npm exited with code ${code} while attempting to build ${manifest._requested}. Clone the repository manually and run 'npm install' in it for more information.`) - err.code = code - err.signal = signal - cb(err) - } else { - cb() - } - }) - }).then(() => { - if (outDataLen > 0) log.silly('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString()) - if (errDataLen > 0) log.silly('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString()) - }, (err) => { - if (outDataLen > 0) log.error('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString()) - if (errDataLen > 0) log.error('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString()) - throw err - }) - } - }).then(() => { - return pipe(packToStream(manifest, dir), stream) - }).catch((err) => stream.emit('error', err)) - return stream -} diff --git a/lib/fetch-package-metadata.js b/lib/fetch-package-metadata.js index 45d6acbfa..cca6dc64f 100644 --- a/lib/fetch-package-metadata.js +++ b/lib/fetch-package-metadata.js @@ -12,7 +12,7 @@ const npmlog = require('npmlog') const limit = require('call-limit') const tempFilename = require('./utils/temp-filename') const pacote = require('pacote') -const pacoteOpts = require('./config/pacote') +let pacoteOpts const isWindows = require('./utils/is-windows.js') function andLogAndFinish (spec, tracker, done) { @@ -52,7 +52,9 @@ function fetchPackageMetadata (spec, where, opts, done) { err.code = 'EWINDOWSPATH' return logAndFinish(err) } - + if (!pacoteOpts) { + pacoteOpts = require('./config/pacote') + } pacote.manifest(dep, pacoteOpts({ annotate: true, fullMetadata: opts.fullMetadata, @@ -83,6 +85,9 @@ function fetchPackageMetadata (spec, where, opts, done) { module.exports.addBundled = addBundled function addBundled (pkg, next) { validate('OF', arguments) + if (!pacoteOpts) { + pacoteOpts = require('./config/pacote') + } if (pkg._bundled !== undefined) return next(null, pkg) if (!pkg.bundleDependencies && pkg._requested.type !== 'directory') return next(null, pkg) diff --git a/lib/install/action/extract.js b/lib/install/action/extract.js index c05a25dcd..437d7e57f 100644 --- a/lib/install/action/extract.js +++ b/lib/install/action/extract.js @@ -12,13 +12,16 @@ const move = BB.promisify(require('../../utils/move.js')) const npa = require('npm-package-arg') const packageId = require('../../utils/package-id.js') const pacote = require('pacote') -const pacoteOpts = require('../../config/pacote') +let pacoteOpts const path = require('path') module.exports = extract function extract (staging, pkg, log) { log.silly('extract', packageId(pkg)) const extractTo = moduleStagingPath(staging, pkg) + if (!pacoteOpts) { + pacoteOpts = require('../../config/pacote') + } const opts = pacoteOpts({ integrity: pkg.package._integrity }) diff --git a/lib/install/inflate-shrinkwrap.js b/lib/install/inflate-shrinkwrap.js index 02f7eaedd..8cb75626b 100644 --- a/lib/install/inflate-shrinkwrap.js +++ b/lib/install/inflate-shrinkwrap.js @@ -2,10 +2,10 @@ const BB = require('bluebird') -const addBundled = BB.promisify(require('../fetch-package-metadata.js').addBundled) +let addBundled const childPath = require('../utils/child-path.js') const createChild = require('./node.js').create -const fetchPackageMetadata = BB.promisify(require('../fetch-package-metadata.js')) +let fetchPackageMetadata const inflateBundled = require('./inflate-bundled.js') const moduleName = require('../utils/module-name.js') const normalizePackageData = require('normalize-package-data') @@ -15,6 +15,10 @@ const validate = require('aproba') const path = require('path') module.exports = function (tree, swdeps, opts, finishInflating) { + if (!fetchPackageMetadata) { + fetchPackageMetadata = BB.promisify(require('../fetch-package-metadata.js')) + addBundled = BB.promisify(fetchPackageMetadata.addBundled) + } if (!npm.config.get('shrinkwrap') || !npm.config.get('package-lock')) { return finishInflating() } diff --git a/lib/pack.js b/lib/pack.js index 68c6030ee..075a672d6 100644 --- a/lib/pack.js +++ b/lib/pack.js @@ -8,16 +8,19 @@ const BB = require('bluebird') const cache = require('./cache') const cacache = require('cacache') +const cp = require('child_process') const deprCheck = require('./utils/depr-check') -const fpm = BB.promisify(require('./fetch-package-metadata')) +const fpm = require('./fetch-package-metadata') const fs = require('graceful-fs') const install = require('./install') const lifecycle = BB.promisify(require('./utils/lifecycle')) +const log = require('npmlog') const move = require('move-concurrently') const npm = require('./npm') const output = require('./utils/output') const pacoteOpts = require('./config/pacote') const path = require('path') +const PassThrough = require('stream').PassThrough const pathIsInside = require('path-is-inside') const pipe = BB.promisify(require('mississippi').pipe) const prepublishWarning = require('./utils/warn-deprecated')('prepublish-on-install') @@ -53,7 +56,7 @@ function pack (args, silent, cb) { // add to cache, then cp to the cwd function pack_ (pkg, dir) { - return fpm(pkg, dir).then((mani) => { + return BB.fromNode((cb) => fpm(pkg, dir, cb)).then((mani) => { let name = mani.name[0] === '@' // scoped packages get special treatment ? mani.name.substr(1).replace(/\//g, '-') @@ -108,10 +111,111 @@ function prepareDirectory (dir) { module.exports.packDirectory = packDirectory function packDirectory (mani, dir, target) { deprCheck(mani) - return cacache.tmp.withTmp(npm.tmp, {tmpPrefix: 'packing'}, (tmp) => { - const tmpTarget = path.join(tmp, path.basename(target)) - return tarPack(tmpTarget, dir, mani).then(() => { - return move(tmpTarget, target, {Promise: BB, fs}) - }).then(() => target) + return readJson(path.join(dir, 'package.json')).then((pkg) => { + return lifecycle(pkg, 'prepack', dir) + }).then(() => { + return readJson(path.join(dir, 'package.json')) + }).then((pkg) => { + return cacache.tmp.withTmp(npm.tmp, {tmpPrefix: 'packing'}, (tmp) => { + const tmpTarget = path.join(tmp, path.basename(target)) + return tarPack(tmpTarget, dir, pkg).then(() => { + return move(tmpTarget, target, {Promise: BB, fs}) + }).then(() => { + return lifecycle(pkg, 'postpack', dir) + }).then(() => target) + }) }) } + +const PASSTHROUGH_OPTS = [ + 'always-auth', + 'auth-type', + 'ca', + 'cafile', + 'cert', + 'git', + 'local-address', + 'maxsockets', + 'offline', + 'prefer-offline', + 'prefer-online', + 'proxy', + 'https-proxy', + 'registry', + 'send-metrics', + 'sso-poll-frequency', + 'sso-type', + 'strict-ssl' +] + +module.exports.packGitDep = packGitDep +function packGitDep (manifest, dir) { + const stream = new PassThrough() + readJson(path.join(dir, 'package.json')).then((pkg) => { + if (pkg.scripts && pkg.scripts.prepare) { + log.verbose('prepareGitDep', `${manifest._spec}: installing devDeps and running prepare script.`) + const cliArgs = PASSTHROUGH_OPTS.reduce((acc, opt) => { + if (npm.config.get(opt, 'cli') != null) { + acc.push(`--${opt}=${npm.config.get(opt)}`) + } + return acc + }, []) + const child = cp.spawn(process.env.NODE || process.execPath, [ + require.main.filename, + 'install', + '--ignore-prepublish', + '--no-progress', + '--no-save' + ].concat(cliArgs), { + cwd: dir, + env: process.env + }) + let errData = [] + let errDataLen = 0 + let outData = [] + let outDataLen = 0 + child.stdout.on('data', (data) => { + outData.push(data) + outDataLen += data.length + log.gauge.pulse('preparing git package') + }) + child.stderr.on('data', (data) => { + errData.push(data) + errDataLen += data.length + log.gauge.pulse('preparing git package') + }) + return BB.fromNode((cb) => { + child.on('error', cb) + child.on('exit', (code, signal) => { + if (code > 0) { + const err = new Error(`${signal}: npm exited with code ${code} while attempting to build ${manifest._requested}. Clone the repository manually and run 'npm install' in it for more information.`) + err.code = code + err.signal = signal + cb(err) + } else { + cb() + } + }) + }).then(() => { + if (outDataLen > 0) log.silly('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString()) + if (errDataLen > 0) log.silly('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString()) + }, (err) => { + if (outDataLen > 0) log.error('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString()) + if (errDataLen > 0) log.error('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString()) + throw err + }) + } + }).then(() => { + return readJson(path.join(dir, 'package.json')) + }).then((pkg) => { + return cacache.tmp.withTmp(npm.tmp, { + tmpPrefix: 'pacote-packing' + }, (tmp) => { + const tmpTar = path.join(tmp, 'package.tgz') + return packDirectory(manifest, dir, tmpTar).then(() => { + return pipe(fs.createReadStream(tmpTar), stream) + }) + }) + }).catch((err) => stream.emit('error', err)) + return stream +} diff --git a/lib/publish.js b/lib/publish.js index 49c98fb8e..5d99bfd08 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -76,15 +76,23 @@ function publish_ (arg) { } function publishFromDirectory (arg) { - return pack.prepareDirectory(arg).tap((pkg) => { + // All this readJson is because any of the given scripts might modify the + // package.json in question, so we need to refresh after every step. + return pack.prepareDirectory(arg).then(() => { + return readJson(path.join(arg, 'package.json')) + }).then((pkg) => { return lifecycle(pkg, 'prepublishOnly', arg) - }).tap((pkg) => { + }).then(() => { + return readJson(path.join(arg, 'package.json')) + }).then((pkg) => { return cacache.tmp.withTmp(npm.tmp, {tmpPrefix: 'fromDir'}, (tmpDir) => { const target = path.join(tmpDir, 'package.tgz') return pack.packDirectory(pkg, arg, target).then(() => { return upload(arg, pkg, false, target) }) }) + }).then(() => { + return readJson(path.join(arg, 'package.json')) }).tap((pkg) => { return lifecycle(pkg, 'publish', arg) }).tap((pkg) => { diff --git a/lib/utils/tar.js b/lib/utils/tar.js index 7ebc9d687..ebbee025a 100644 --- a/lib/utils/tar.js +++ b/lib/utils/tar.js @@ -3,8 +3,6 @@ // commands for packing and unpacking tarballs // this file is used by lib/cache.js -const BB = require('bluebird') - var fs = require('graceful-fs') var path = require('path') var writeFileAtomic = require('write-file-atomic') @@ -28,11 +26,6 @@ var moduleName = require('./module-name.js') var packageId = require('./package-id.js') var pulseTillDone = require('../utils/pulse-till-done.js') -const cacache = require('cacache') -const packAsync = BB.promisify(pack) -const PassThrough = require('stream').PassThrough -const pipe = BB.promisify(require('mississippi').pipe) - if (process.env.SUDO_UID && myUid === 0) { if (!isNaN(process.env.SUDO_UID)) myUid = +process.env.SUDO_UID if (!isNaN(process.env.SUDO_GID)) myGid = +process.env.SUDO_GID @@ -41,18 +34,6 @@ if (process.env.SUDO_UID && myUid === 0) { exports.pack = pack exports.unpack = unpack -module.exports.packToStream = packToStream -function packToStream (mani, dir) { - const stream = new PassThrough() - cacache.tmp.withTmp(npm.tmp, (tmp) => { - const tmpTarget = path.join(tmp, 'package.tgz') - return packAsync(tmpTarget, dir, mani).then(() => { - return pipe(fs.createReadStream(tmpTarget), stream) - }) - }).catch((err) => stream.emit('error', err)) - return stream -} - function pack (tarball, folder, pkg, cb) { log.verbose('tar pack', [tarball, folder]) |