mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-18 15:18:00 -05:00
Implement flattening
This commit is contained in:
@@ -8,6 +8,7 @@ var logger = require('../logger')
|
||||
var installMultiple = require('../install_multiple')
|
||||
var config = require('../config')
|
||||
var save = require('../save')
|
||||
var linkPeers = require('../install/link_peers')
|
||||
|
||||
/*
|
||||
* Perform
|
||||
@@ -20,9 +21,10 @@ function run (cli) {
|
||||
var installType
|
||||
|
||||
return readPkgUp()
|
||||
.then(pkg_ => { pkg = pkg_ })
|
||||
.then(_ => { pkg = _ })
|
||||
.then(_ => updateContext(pkg.path))
|
||||
.then(_ => install())
|
||||
.then(_ => linkPeers(pkg, ctx.store, ctx.installs))
|
||||
|
||||
function install () {
|
||||
installType = cli.input && cli.input.length ? 'named' : 'general'
|
||||
|
||||
16
lib/fs/unsymlink.js
Normal file
16
lib/fs/unsymlink.js
Normal file
@@ -0,0 +1,16 @@
|
||||
var fs = require('mz/fs')
|
||||
|
||||
/*
|
||||
* Removes a symlink
|
||||
*/
|
||||
|
||||
module.exports = function unsymlink (path) {
|
||||
return fs.lstat(path)
|
||||
.then(stat => {
|
||||
if (stat.isSymbolicLink()) return fs.unlink(path)
|
||||
throw new Error('Can\'t unlink ' + path)
|
||||
})
|
||||
.catch(err => {
|
||||
if (err.code !== 'ENOENT') throw err
|
||||
})
|
||||
}
|
||||
39
lib/install/link_peers.js
Normal file
39
lib/install/link_peers.js
Normal file
@@ -0,0 +1,39 @@
|
||||
var Promise = require('../promise')
|
||||
var mkdirp = require('../mkdirp')
|
||||
var unsymlink = require('../fs/unsymlink')
|
||||
var relSymlink = require('../rel_symlink')
|
||||
var join = require('path').join
|
||||
var semver = require('semver')
|
||||
|
||||
/*
|
||||
* Links into `.store/node_modules`
|
||||
*/
|
||||
|
||||
module.exports = function linkPeers (pkg, store, installs) {
|
||||
var peers = {}
|
||||
var roots = {}
|
||||
|
||||
Object.keys(installs).forEach(name => {
|
||||
var pkgData = installs[name]
|
||||
var realname = pkgData.name
|
||||
|
||||
if (pkgData.keypath.length === 0) {
|
||||
roots[realname] = pkgData
|
||||
} else if (!peers[realname] ||
|
||||
semver.gt(pkgData.version, peers[realname].version)) {
|
||||
peers[realname] = pkgData
|
||||
}
|
||||
})
|
||||
|
||||
var modules = join(store, 'node_modules')
|
||||
return mkdirp(modules)
|
||||
.then(_ => Promise.all(Object.keys(roots).map(name =>
|
||||
unsymlink(join(modules, roots[name].name))
|
||||
)))
|
||||
.then(_ => Promise.all(Object.keys(peers).map(name =>
|
||||
relSymlink(
|
||||
join('..', peers[name].fullname),
|
||||
join(modules, peers[name].name))
|
||||
)))
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ var fs = require('fs')
|
||||
var prepare = require('./support/prepare')
|
||||
var install = require('../lib/cmd/install')
|
||||
require('./support/sepia')
|
||||
var stat
|
||||
|
||||
var stat, _
|
||||
|
||||
test('eslint', require('tape-eslint')())
|
||||
|
||||
@@ -30,7 +31,7 @@ test('no dependencies (lodash)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['lodash@4.0.0'], flags: { quiet: true } })
|
||||
.then(function () {
|
||||
var _ = require(join(process.cwd(), 'node_modules', 'lodash'))
|
||||
_ = require(join(process.cwd(), 'node_modules', 'lodash'))
|
||||
t.ok(typeof _ === 'function', '_ is available')
|
||||
t.ok(typeof _.clone === 'function', '_.clone is available')
|
||||
t.end()
|
||||
@@ -41,7 +42,7 @@ test('scoped modules without version spec (@rstacruz/tap-spec)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['@rstacruz/tap-spec'], flags: { quiet: true } })
|
||||
.then(function () {
|
||||
var _ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
_ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
t.ok(typeof _ === 'function', 'tap-spec is available')
|
||||
t.end()
|
||||
}, t.end)
|
||||
@@ -51,7 +52,7 @@ test('scoped modules with versions (@rstacruz/tap-spec@4.1.1)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['@rstacruz/tap-spec@4.1.1'], flags: { quiet: true } })
|
||||
.then(function () {
|
||||
var _ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
_ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
t.ok(typeof _ === 'function', 'tap-spec is available')
|
||||
t.end()
|
||||
}, t.end)
|
||||
@@ -61,7 +62,7 @@ test('scoped modules (@rstacruz/tap-spec@*)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['@rstacruz/tap-spec@*'], flags: { quiet: true } })
|
||||
.then(function () {
|
||||
var _ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
_ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
t.ok(typeof _ === 'function', 'tap-spec is available')
|
||||
t.end()
|
||||
}, t.end)
|
||||
@@ -71,7 +72,7 @@ test('multiple scoped modules (@rstacruz/...)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['@rstacruz/tap-spec@*', '@rstacruz/travis-encrypt@*'], flags: { quiet: true } })
|
||||
.then(function () {
|
||||
var _ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
_ = require(join(process.cwd(), 'node_modules', '@rstacruz/tap-spec'))
|
||||
t.ok(typeof _ === 'function', 'tap-spec is available')
|
||||
_ = require(join(process.cwd(), 'node_modules', '@rstacruz/travis-encrypt'))
|
||||
t.ok(typeof _ === 'function', 'travis-encrypt is available')
|
||||
@@ -215,3 +216,38 @@ test('multiple save to package.json with `exact` versions (@rstacruz/tap-spec &
|
||||
t.end()
|
||||
}, t.end)
|
||||
})
|
||||
|
||||
test('flattening symlinks (minimatch@3.0.0)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['minimatch@3.0.0'], flags: { quiet: true } })
|
||||
.then(function () {
|
||||
stat = fs.lstatSync(join(process.cwd(), 'node_modules', '.store', 'node_modules', 'balanced-match'))
|
||||
t.ok(stat.isSymbolicLink(), 'balanced-match is linked into store node_modules')
|
||||
|
||||
_ = exists(join(process.cwd(), 'node_modules', 'balanced-match'))
|
||||
t.ok(!_, 'balanced-match is not linked into main node_modules')
|
||||
t.end()
|
||||
}, t.end)
|
||||
})
|
||||
|
||||
test('flattening symlinks (minimatch + balanced-match)', function (t) {
|
||||
prepare()
|
||||
install({ input: ['minimatch@3.0.0'], flags: { quiet: true } })
|
||||
.then(_ => install({ input: ['balanced-match@^0.3.0'], flags: { quiet: true } }))
|
||||
.then(function () {
|
||||
_ = exists(join(process.cwd(), 'node_modules', '.store', 'node_modules', 'balanced-match'))
|
||||
t.ok(!_, 'balanced-match is removed from store node_modules')
|
||||
|
||||
_ = exists(join(process.cwd(), 'node_modules', 'balanced-match'))
|
||||
t.ok(_, 'balanced-match now in main node_modules')
|
||||
t.end()
|
||||
}, t.end)
|
||||
})
|
||||
|
||||
function exists (path) {
|
||||
try {
|
||||
return fs.statSync(path)
|
||||
} catch (err) {
|
||||
if (err.code !== 'ENOENT') throw err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user