mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-05 12:41:44 -05:00
Refactor linkBins()
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
var Promise = require('./promise')
|
||||
var debug = require('debug')('pnpm:install')
|
||||
var npa = require('npm-package-arg')
|
||||
var config = require('./config')
|
||||
var join = require('path').join
|
||||
var mkdirp = require('./mkdirp')
|
||||
var fetch = require('./fetch')
|
||||
var resolve = require('./resolve')
|
||||
var getUuid = require('node-uuid')
|
||||
var symlink = require('./force_symlink')
|
||||
var linkBins = require('./install/link_bins')
|
||||
var fs = require('mz/fs')
|
||||
var basename = require('path').basename
|
||||
|
||||
/*
|
||||
* Installs a package.
|
||||
@@ -49,8 +48,9 @@ module.exports = function install (ctx, pkg, modules, options) {
|
||||
var log = ctx.log(pkgSpec) // function
|
||||
var tmp = join(ctx.tmp, getUuid()) // 'node_modules/.tmp/000-11...'
|
||||
|
||||
return fs.stat(join(modules, pkgSpec.name))
|
||||
return fs.stat(join(modules, pkgSpec.name, 'package.json'))
|
||||
.catch((err) => {
|
||||
if (err.code !== 'ENOENT') throw err
|
||||
return resolve(pkgSpec)
|
||||
.then(set)
|
||||
.then(_ => log('resolved', pkgData))
|
||||
@@ -63,7 +63,6 @@ module.exports = function install (ctx, pkg, modules, options) {
|
||||
.then(_ => log('downloading'))
|
||||
.then(_ => mkdirp(store))
|
||||
.then(_ => mkdirp(tmp))
|
||||
// TODO: check for existence of target
|
||||
.then(_ => fetch(tmp, dist.tarball, dist.shasum, log))
|
||||
.then(_ => linkBins(modules, tmp, fullname))
|
||||
.then(_ => log('dependencies'))
|
||||
@@ -76,7 +75,7 @@ module.exports = function install (ctx, pkg, modules, options) {
|
||||
.then(_ => unlock(ctx, target))
|
||||
})
|
||||
.then(_ => mkdirp(modules))
|
||||
.then(_ => doSymlink())
|
||||
.then(_ => symlinkToModules(fullname, name, modules, depth))
|
||||
})
|
||||
.then(_ => log('done'))
|
||||
.catch((err) => {
|
||||
@@ -92,17 +91,6 @@ module.exports = function install (ctx, pkg, modules, options) {
|
||||
name = res.name
|
||||
dist = res.dist
|
||||
}
|
||||
|
||||
// perform the final symlinking of ./.store/x@1.0.0 => ./x.
|
||||
function doSymlink () {
|
||||
if (depth === 0) {
|
||||
return symlink(join('.store', fullname), join(modules, name))
|
||||
} else {
|
||||
// we'll go back to ..../.store here so the same module will act the same
|
||||
// on node_modules/.tmp
|
||||
return symlink(join('..', '..', '..', '.store', fullname), join(modules, name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function lock (ctx, path) {
|
||||
@@ -119,7 +107,7 @@ function isLocked (ctx, path) {
|
||||
}
|
||||
|
||||
/*
|
||||
* symlink a package into its own node_modules. this way, babel-runtime@5 can
|
||||
* Symlink a package into its own node_modules. this way, babel-runtime@5 can
|
||||
* require('babel-runtime') within itself.
|
||||
*/
|
||||
|
||||
@@ -135,45 +123,20 @@ function symlinkSelf (target, name, depth) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Links executables into `node_modules/.bin`
|
||||
* Perform the final symlinking of ./.store/x@1.0.0 -> ./x.
|
||||
*
|
||||
* module = 'project/node_modules'
|
||||
* target = 'project/node_modules/.tmp/a1b3c56...'
|
||||
* linkBins(module, target, 'rimraf@2.5.1')
|
||||
*
|
||||
* // node_modules/.bin/rimraf -> ../.store/rimraf@2.5.1/cmd.js
|
||||
* fullname = 'lodash@4.0.0'
|
||||
* name = 'lodash'
|
||||
* modules = './node_modules'
|
||||
* symlinkToModules(fullname, name, modules, 0)
|
||||
*/
|
||||
|
||||
function linkBins (module, target, fullname) {
|
||||
var pkg = tryRequire(join(target, 'package.json'))
|
||||
if (!pkg || !pkg.bin) return
|
||||
|
||||
var bins = binify(pkg)
|
||||
|
||||
return Object.keys(bins).map((bin) => {
|
||||
var actualBin = bins[bin]
|
||||
|
||||
return Promise.resolve()
|
||||
.then(_ => fs.chmod(join(target, actualBin), 0o755))
|
||||
.then(_ => mkdirp(join(module, '.bin')))
|
||||
.then(_ => symlink(
|
||||
join('..', '.store', fullname, actualBin),
|
||||
join(module, '.bin', bin)))
|
||||
})
|
||||
}
|
||||
|
||||
function binify (pkg) {
|
||||
if (typeof pkg.bin === 'string') {
|
||||
var obj = {}
|
||||
obj[pkg.name] = pkg.bin
|
||||
return obj
|
||||
function symlinkToModules (fullname, name, modules, depth) {
|
||||
if (depth === 0) {
|
||||
return symlink(join('.store', fullname), join(modules, name))
|
||||
} else {
|
||||
// we'll go back to ..../.store here so the same module will act the same
|
||||
// on node_modules/.tmp
|
||||
return symlink(join('..', '..', '..', '.store', fullname), join(modules, name))
|
||||
}
|
||||
|
||||
return pkg.bin
|
||||
}
|
||||
|
||||
function tryRequire (path) {
|
||||
try {
|
||||
return require(path)
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
65
lib/install/link_bins.js
Normal file
65
lib/install/link_bins.js
Normal file
@@ -0,0 +1,65 @@
|
||||
var join = require('path').join
|
||||
var symlink = require('../force_symlink')
|
||||
var fs = require('mz/fs')
|
||||
var mkdirp = require('../mkdirp')
|
||||
|
||||
/*
|
||||
* Links executables into `node_modules/.bin`.
|
||||
*
|
||||
* - `modules` (String) - the node_modlules path
|
||||
* - `target` (String) - where the module is now; read package.json from here
|
||||
* - `fullname` (String) - fullname of the module (`rimraf@2.5.1`)
|
||||
*
|
||||
* module = 'project/node_modules'
|
||||
* target = 'project/node_modules/.tmp/a1b3c56...'
|
||||
* linkBins(module, target, 'rimraf@2.5.1')
|
||||
*
|
||||
* // node_modules/.bin/rimraf -> ../.store/rimraf@2.5.1/cmd.js
|
||||
*/
|
||||
|
||||
module.exports = function linkBins (modules, target, fullname) {
|
||||
var pkg = tryRequire(join(target, 'package.json'))
|
||||
if (!pkg || !pkg.bin) return
|
||||
|
||||
var bins = binify(pkg)
|
||||
|
||||
return Object.keys(bins).map((bin) => {
|
||||
var actualBin = bins[bin]
|
||||
|
||||
return Promise.resolve()
|
||||
.then(_ => fs.chmod(join(target, actualBin), 0o755))
|
||||
.then(_ => mkdirp(join(modules, '.bin')))
|
||||
.then(_ => symlink(
|
||||
join('..', '.store', fullname, actualBin),
|
||||
join(modules, '.bin', bin)))
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Like `require()`, but returns `undefined` when it fails
|
||||
*/
|
||||
|
||||
function tryRequire (path) {
|
||||
try { return require(path) } catch (e) { }
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns bins for a package in a standard object format. This normalizes
|
||||
* between npm's string and object formats.
|
||||
*
|
||||
* binify({ name: 'rimraf', bin: 'cmd.js' })
|
||||
* => { rimraf: 'cmd.js' }
|
||||
*
|
||||
* binify({ name: 'rmrf', bin: { rmrf: 'cmd.js' } })
|
||||
* => { rmrf: 'cmd.js' }
|
||||
*/
|
||||
|
||||
function binify (pkg) {
|
||||
if (typeof pkg.bin === 'string') {
|
||||
var obj = {}
|
||||
obj[pkg.name] = pkg.bin
|
||||
return obj
|
||||
}
|
||||
|
||||
return pkg.bin
|
||||
}
|
||||
Reference in New Issue
Block a user