From ae4a1350d697d2699350ec11b78b8cf74d6d2468 Mon Sep 17 00:00:00 2001 From: "Rico Sta. Cruz" Date: Sat, 30 Jan 2016 01:19:47 +0800 Subject: [PATCH] Continue refactoring --- lib/install.js | 93 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/lib/install.js b/lib/install.js index 546ff421f6..d2e4c753a8 100644 --- a/lib/install.js +++ b/lib/install.js @@ -35,43 +35,60 @@ var fs = require('mz/fs') * - symlink bins */ -module.exports = function install (ctx, pkg, modules, options) { - debug('installing ' + pkg) - - var keypath = (options && options.keypath || []) - var pkgSpec = npa(pkg) // { raw, name, scope, type, spec, rawSpec } - var pkgData // { name, version, ... } - var fullname // 'lodash@4.0.0' - var dist // { shasum, tarball } - var log = ctx.log(pkgSpec) // function +module.exports = function install (ctx, pkgSpec, modules, options) { + debug('installing ' + pkgSpec) if (!ctx.fetches) ctx.fetches = {} - var paths = { - modules: modules, - store: join(ctx.root, 'node_modules', '.store'), - tmp: join(ctx.root, 'node_modules', '.tmp', getUuid()), - target: undefined // store + '/lodash@4.0.0' + var pkg = { + // Preliminary spec data + // => { raw, name, scope, type, spec, rawSpec } + spec: npa(pkgSpec), + + // Dependency path to the current package + // => ['babel-core@6.4.5', 'babylon@6.4.5', 'babel-runtime@5.8.35'] + keypath: (options && options.keypath || []), + + // Full name of package => 'lodash@4.0.0' + fullname: undefined, + + // Distribution data from resolve() => { shasum, tarball } + dist: undefined, + + // package.json data as retrieved from resolve() => { name, version, ... } + data: undefined } - return fs.stat(join(modules, pkgSpec.name, 'package.json')) + var paths = { + modules: modules, // './node_modules' + + // Final destination + store: join(ctx.root, 'node_modules', '.store'), + + // Temporary destination while building + tmp: join(ctx.root, 'node_modules', '.tmp', getUuid()), + + // Final destination => store + '/lodash@4.0.0' + target: undefined + } + + var log = ctx.log(pkg.spec) // function + + return fs.stat(join(modules, pkg.spec.name, 'package.json')) .catch(err => { if (err.code !== 'ENOENT') throw err - return resolve(pkgSpec) + return resolve(pkg.spec) .then(set) - .then(_ => log('resolved', pkgData)) + .then(_ => log('resolved', pkg.data)) .then(_ => fs.stat(join(paths.target, 'package.json'))) // todo: verify version? .catch(err => { if (err.code !== 'ENOENT') throw err - var isCircular = keypath.indexOf(fullname) > -1 - if (isCircular) { - return Promise.resolve() - } else { - return memoize(ctx.fetches, fullname, - _ => doFetch(ctx, paths, dist, pkgData, keypath.concat(fullname), log)) - } + return isCircular(pkg) + ? Promise.resolve() + : memoize(ctx.fetches, pkg.fullname, + _ => doFetch(ctx, paths, pkg, log)) }) .then(_ => mkdirp(paths.modules)) - .then(_ => symlinkToModules(paths.target, pkgSpec, paths.modules)) + .then(_ => symlinkToModules(paths.target, pkg.spec, paths.modules)) }) .then(_ => log('done')) .catch(err => { @@ -81,15 +98,15 @@ module.exports = function install (ctx, pkg, modules, options) { // set metadata as fetched from resolve() function set (res) { - pkgData = res - fullname = '' + res.name.replace('/', '!') + '@' + res.version - paths.target = join(paths.store, fullname) - dist = res.dist + pkg.data = res + pkg.fullname = '' + res.name.replace('/', '!') + '@' + res.version + pkg.dist = res.dist + paths.target = join(paths.store, pkg.fullname) } } // perform a fetch to `.store/lodash@4.0.0` (paths.target) -function doFetch (ctx, paths, dist, pkgData, keypath, log) { +function doFetch (ctx, paths, pkg, log) { var installAll = require('./install_multiple') return Promise.resolve() @@ -98,14 +115,14 @@ function doFetch (ctx, paths, dist, pkgData, keypath, log) { .then(_ => log('downloading')) .then(_ => mkdirp(paths.store)) .then(_ => mkdirp(paths.tmp)) - .then(_ => fetch(paths.tmp, dist.tarball, dist.shasum, log)) + .then(_ => fetch(paths.tmp, pkg.dist.tarball, pkg.dist.shasum, log)) .then(_ => linkBins(paths.modules, paths.tmp, paths.target)) .then(_ => log('dependencies')) .then(_ => installAll(ctx, - pkgData.dependencies, + pkg.data.dependencies, join(paths.tmp, 'node_modules'), - { keypath: keypath })) - .then(_ => symlinkSelf(paths.tmp, pkgData, keypath.length - 1)) + { keypath: pkg.keypath.concat([ pkg.fullname ]) })) + .then(_ => symlinkSelf(paths.tmp, pkg.data, pkg.keypath.length)) .then(_ => fs.unlink(paths.target)) .then(_ => fs.rename(paths.tmp, paths.target)) } @@ -154,3 +171,11 @@ function symlinkToModules (target, pkg, modules) { return relSymlink(target, join(modules, pkg.name)) } + +/* + * Checks if the current package is a circular dependency. + */ + +function isCircular (pkg) { + return pkg.keypath.indexOf(pkg.fullname) > -1 +}