Skip to content
This repository has been archived by the owner on Mar 27, 2019. It is now read-only.

Commit

Permalink
refactor a bunch more
Browse files Browse the repository at this point in the history
  • Loading branch information
ianstormtaylor committed Apr 8, 2014
1 parent 9b239a7 commit 5c430f2
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 120 deletions.
126 changes: 66 additions & 60 deletions lib/build.js
Expand Up @@ -5,11 +5,13 @@
* install as well as we figure out what things work across both
*/



var async = require('async');
var path = require('path');
var spec = require('./spec');
var toFn = require('to-function');
var Ware = require('ware');
var values = require('object-values');

var normalize = spec.normalize;

/**
Expand All @@ -36,79 +38,83 @@ function build(fn){
var install = this.installTo();
var dest = this.buildTo();
var dev = this.development();
var json = this.json();
var plugins = [];

this.getComponents(function(err, installed){
this.readComponents(function(err, components){
if (err) return fn(err);

var tree = { json: json };
var build = {};
var components = [];
/**
* Populate the `pegs` for each component.
*/

Ware()
.use(resolve)
.use(plugins)
.run(res, fn);
var pegs = components.reduce(function(memo, component){
var name = component.repository;
var deps = dev
? extend({}, json.development, json.dependencies)
: json.dependencies;
for (var repo in deps) memo[repo][name] = deps[repo];
}, {});

/**
* Assert that each components satisfies semver for its pegs.
*/

for (var i = 0, component; component = components[i]; i++) {
if ('remote' != component.type) return;
var repo = component.repository;
var version = component.version;
var range = values(pegs[repo]).join(' ');
if (!semver.satisfies(version, range)) {
var err = new Error('Version mismatch.');
err.type = 'version_mismatch';
err.repository = repo;
err.version = pegs[repo];
return fn(err);
}
}

populate(json, function(err){
fn(null, components);
});
/**
* Read the files for each component.
*/

function populate(node, done){
async.map(components, read, function(err, res){
Ware()
.use(getFiles())
.use(getDependencies())
.run(node, function(err, node){
if (err) return done(err);
components.push(node.json);
done();
});
}
.use(plugins)
.run({ components: res.map(toFn('.conf')) }, fn);
});
});

function getFiles(node, done){
var json = node.json;
var norm = normalize.json(json);
var repo = json.repository;
/**
* Read the files for a given `component`.
*
* @param {Object} component
* @param {Function} done
*/

async.each(spec.types, type, done);
function read(component, done){
var json = component.json;
var repo = json.repository;

function type(name, finish){
async.map(json[name], read, function(err, files){
if (err) return finish(err);
json[name] = files;
finish();
});
}
async.each(spec.types, type, done);

function read(file, finish){
var path = join(install, repo, file);
fs.readFile(path, 'utf8', function(err, str){
finish(err, {
filename: file,
contents: str
});
});
}
function type(name, finish){
async.map(json[name], file, function(err, files){
if (err) return finish(err);
json[name] = files;
finish();
});
}

function getDependencies(node, done){
var json = node.json;
var deps = dev
? extend({}, json.dependencies, json.development)
: json.dependencies;

async.map(Object.keys(deps), dependency, function(err, nodes){
if (err) return done(err);
node.dependencies = nodes;
done();
function file(name, finish){
var filename = path.join(install, repo, name);
fs.readFile(filename, 'utf8', function(err, str){
finish(err, {
filename: file,
contents: str
});
});

function dependency(name, finish){
populate({ json: installed[name] }, finish);
}
}

});
}

return this;
}
34 changes: 5 additions & 29 deletions lib/index.js
Expand Up @@ -151,46 +151,22 @@ Component.prototype.remotes = function(remotes){
};

/**
* Read any components that have already been installed to the component's
* install destination folder, and callback `fn(err, components)`.
* Resolve all of the locally-installed dependencies for the component, both
* in `paths` and in the install directory.
*
* @param {Function} fn
*/

Component.prototype.readComponents = function(fn){
var components = [];
var dest = this.installTo();

fs.exists(dest, function(exists){
if (!exists) return fn(null, components);

fs.readdir(dest, function(err, repos){
if (err) return fn(err);

for (var i = 0, repo; repo = repos[i]; i++) {
try {
var json = require(path.join(dest, repo, 'component.json'));
var repo = json.repository;
components.push(json);
components[repo] = json;
} catch (e) {
return fn('Invalid JSON in locally-installed "' + repo + '".');
}
}

fn(null, components);
});
});
};
Component.prototype.local = require('./local');

/**
* Resolve the dependencies for the component, applying remotes and semver.
* Resolve the remote dependencies for the component.
*
* @param {Function} fn
* @return {Component}
*/

Component.prototype.resolveComponents = require('./resolve');
Component.prototype.remote = require('./remote');

/**
* Install the component, and callback `fn(err, ast)`.
Expand Down
7 changes: 2 additions & 5 deletions lib/install.js
Expand Up @@ -12,10 +12,6 @@ module.exports = install;
/**
* Install a component and its dependencies, then callback `fn(err, tree)`.
*
* - Recursively retrieve each dependency's metadata.
* - Try to resolve semver constraints among the dependencies.
* - Download all of the dependencies' files.
*
* @param {Function} fn
* @return {Component}
*/
Expand All @@ -42,6 +38,7 @@ function install(fn){
var version = component.version;
var json = component.json;
var repo = component.repository;
var remote = component.remote;
var out = path.join(dest, repo.replace('/', '-'));

if (installed[repo] && installed[repo].version == version) {
Expand All @@ -63,7 +60,7 @@ function install(fn){

function file(filename, end){
self.emit('downloading file', repo, version, filename);
component.remote.file(filename, repo, version, function(err, str){
remote.file(filename, repo, version, function(err, str){
if (err) return end(err);
fs.outputFile(path.join(out, filename), str, end);
self.emit('download file', repo, version, filename);
Expand Down
55 changes: 55 additions & 0 deletions lib/local.js
@@ -0,0 +1,55 @@

var fs = require('fs');
var path = require('path');
var spec = require('./spec');

var normalize = spec.normalize;

/**
* Expose `local`.
*/

module.exports = local;

/**
* Resolve all of the locally-installed dependencies for the component, both
* in `paths` and in the install directory.
*
* @param {Function} fn
*/

function local(fn){
var components = [];
var dest = this.installTo();

fs.exists(dest, function(exists){
if (!exists) return fn(null, components);

fs.readdir(dest, function(err, dirs){
if (err) return fn(err);

for (var i = 0, dir; dir = dirs[i]; i++) {
try {
var json = require(path.join(dest, dir, 'component.json'));
var conf = normalize.json(json);
var repo = conf.repository;
var component = {
type: 'remote',
name: repo,
repository: repo,
version: conf.version,
conf: conf,
json: json
};

components.push(component);
components[repo] = component;
} catch (e) {
return fn('Invalid JSON in locally-installed "' + dir + '".');
}
}

fn(null, components);
});
});
}
31 changes: 15 additions & 16 deletions lib/resolve.js → lib/remote.js
Expand Up @@ -7,26 +7,29 @@ var spec = require('./spec');
var semver = require('semver');
var values = require('object-values');
var Ware = require('ware');

var normalize = spec.normalize;

/**
* Expose `resolve`.
* Expose `remote`.
*/

module.exports = resolve;
module.exports = remote;

/**
* Resolve the dependencies for the component, applying remotes and semver.
* Resolve the remote dependencies for the component.
*
* @param {Function} fn
* @return {Component}
*/

function resolve(fn){
function remote(fn){
var self = this;
var dev = this.development();
var remotes = this.remotes();
var metadata = {};

var pegs = {};
var versions = {};
var components = [];
var tree = {
type: 'root',
Expand Down Expand Up @@ -103,10 +106,9 @@ function resolve(fn){

remote.versions(repo, function(err, versions){
if (err) return done(err);
var data = metadata[repo] = metadata[repo] || {};
data.pegs = data.pegs || {};
data.pegs[parent] = node.version;
data.versions = versions;
versions[repo] = versions;
pegs[repo] = pegs[repo] || {};
pegs[repo][parent] = node.version;
self.emit('versions', repo, versions);
done();
});
Expand All @@ -123,11 +125,8 @@ function resolve(fn){
if ('remote' != node.type) return setImmediate(done);
var repo = node.repository;
var version = node.version;
var data = metadata[repo];
var versions = data.versions;
var pegs = data.pegs;

var match = semver.maxSatisfying(versions, version);
var match = semver.maxSatisfying(versions[repo], version);
if (!match) {
debugger;
var err = new Error('Version not found.');
Expand All @@ -137,13 +136,13 @@ function resolve(fn){
return done(err);
}

var range = values(pegs).join(' ') + ' ' + version;
match = semver.maxSatisfying(versions, range);
var range = values(pegs[repo]).join(' ') + ' ' + version;
match = semver.maxSatisfying(versions[repo], range);
if (!match) {
var err = new Error('Version mismatch.');
err.type = 'version_mismatch';
err.repository = repo;
err.versions = pegs;
err.versions = pegs[repo];
return done(err);
}

Expand Down

0 comments on commit 5c430f2

Please sign in to comment.