mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.9 KiB
153 lines
4.9 KiB
var assert = require('assert')
|
|
var path = require('path')
|
|
var mkdir = require('mkdirp')
|
|
var chownr = require('chownr')
|
|
var pathIsInside = require('path-is-inside')
|
|
var readJson = require('read-package-json')
|
|
var log = require('npmlog')
|
|
var npm = require('../npm.js')
|
|
var tar = require('../utils/tar.js')
|
|
var deprCheck = require('../utils/depr-check.js')
|
|
var prepublishWarning = require('../utils/warn-deprecated.js')('prepublish-on-install')
|
|
var getCacheStat = require('./get-stat.js')
|
|
var cachedPackageRoot = require('./cached-package-root.js')
|
|
var addLocalTarball = require('./add-local-tarball.js')
|
|
var sha = require('sha')
|
|
var inflight = require('inflight')
|
|
var lifecycle = require('../utils/lifecycle.js')
|
|
var iferr = require('iferr')
|
|
var chain = require('slide').chain
|
|
|
|
module.exports = addLocal
|
|
|
|
function addLocal (p, pkgData, cb_) {
|
|
assert(typeof p === 'object', 'must have spec info')
|
|
assert(typeof cb_ === 'function', 'must have callback')
|
|
|
|
pkgData = pkgData || {}
|
|
|
|
function cb (er, data) {
|
|
if (er) {
|
|
log.error('addLocal', 'Could not install %s', p.spec)
|
|
return cb_(er)
|
|
}
|
|
if (data && !data._fromHosted) {
|
|
data._from = path.relative(npm.prefix, p.spec) || '.'
|
|
var resolved = path.relative(npm.prefix, p.spec)
|
|
if (resolved) data._resolved = 'file:' + resolved
|
|
}
|
|
return cb_(er, data)
|
|
}
|
|
|
|
if (p.type === 'directory') {
|
|
addLocalDirectory(p.spec, pkgData, null, cb)
|
|
} else {
|
|
addLocalTarball(p.spec, pkgData, null, cb)
|
|
}
|
|
}
|
|
|
|
// At this point, if shasum is set, it's something that we've already
|
|
// read and checked. Just stashing it in the data at this point.
|
|
function addLocalDirectory (p, pkgData, shasum, cb) {
|
|
assert(pkgData, 'must pass package data')
|
|
assert(typeof cb === 'function', 'must have callback')
|
|
|
|
// if it's a folder, then read the package.json,
|
|
// tar it to the proper place, and add the cache tar
|
|
if (pathIsInside(p, npm.cache)) {
|
|
return cb(new Error(
|
|
'Adding a cache directory to the cache will make the world implode.'
|
|
))
|
|
}
|
|
|
|
readJson(path.join(p, 'package.json'), false, function (er, data) {
|
|
if (er) return cb(er)
|
|
|
|
if (!data.name) {
|
|
return cb(new Error('No name provided in package.json'))
|
|
} else if (pkgData.name && pkgData.name !== data.name) {
|
|
return cb(new Error(
|
|
'Invalid package: expected ' + pkgData.name + ' but found ' + data.name
|
|
))
|
|
}
|
|
|
|
if (!data.version) {
|
|
return cb(new Error('No version provided in package.json'))
|
|
} else if (pkgData.version && pkgData.version !== data.version) {
|
|
return cb(new Error(
|
|
'Invalid package: expected ' + pkgData.name + '@' + pkgData.version +
|
|
' but found ' + data.name + '@' + data.version
|
|
))
|
|
}
|
|
|
|
deprCheck(data)
|
|
|
|
// pack to {cache}/name/ver/package.tgz
|
|
var root = cachedPackageRoot(data)
|
|
var tgz = path.resolve(root, 'package.tgz')
|
|
var pj = path.resolve(root, 'package/package.json')
|
|
|
|
var wrapped = inflight(tgz, next)
|
|
if (!wrapped) return log.verbose('addLocalDirectory', tgz, 'already in flight; waiting')
|
|
log.verbose('addLocalDirectory', tgz, 'not in flight; packing')
|
|
|
|
getCacheStat(function (er, cs) {
|
|
mkdir(path.dirname(pj), function (er, made) {
|
|
if (er) return wrapped(er)
|
|
var doPrePublish = !pathIsInside(p, npm.tmp)
|
|
if (doPrePublish) {
|
|
// TODO: for `npm@5`, change the behavior and remove this warning.
|
|
// see https://github.com/npm/npm/issues/10074 for details
|
|
if (data && data.scripts && data.scripts.prepublish) {
|
|
prepublishWarning([
|
|
'As of npm@5, `prepublish` scripts will run only for `npm publish`.',
|
|
'(In npm@4 and previous versions, it also runs for `npm install`.)',
|
|
'See the deprecation note in `npm help scripts` for more information.'
|
|
])
|
|
}
|
|
|
|
chain(
|
|
[
|
|
[lifecycle, data, 'prepublish', p],
|
|
[lifecycle, data, 'prepare', p]
|
|
],
|
|
iferr(wrapped, thenPack)
|
|
)
|
|
} else {
|
|
thenPack()
|
|
}
|
|
function thenPack () {
|
|
tar.pack(tgz, p, data, function (er) {
|
|
if (er) {
|
|
log.error('addLocalDirectory', 'Could not pack', p, 'to', tgz)
|
|
return wrapped(er)
|
|
}
|
|
|
|
if (!cs || isNaN(cs.uid) || isNaN(cs.gid)) return wrapped()
|
|
|
|
chownr(made || tgz, cs.uid, cs.gid, function (er) {
|
|
if (er && er.code === 'ENOENT') return wrapped()
|
|
wrapped(er)
|
|
})
|
|
})
|
|
}
|
|
})
|
|
})
|
|
|
|
function next (er) {
|
|
if (er) return cb(er)
|
|
// if we have the shasum already, just add it
|
|
if (shasum) {
|
|
return addLocalTarball(tgz, data, shasum, cb)
|
|
} else {
|
|
sha.get(tgz, function (er, shasum) {
|
|
if (er) {
|
|
return cb(er)
|
|
}
|
|
data._shasum = shasum
|
|
return addLocalTarball(tgz, data, shasum, cb)
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|