Continue refactoring

This commit is contained in:
Rico Sta. Cruz
2016-01-30 01:19:47 +08:00
parent 2527a705f4
commit ae4a1350d6

View File

@@ -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
}