Permalink
Browse files

.jitsuconf should recurse parent directory like node_modules, use nconf

  • Loading branch information...
1 parent b0805b5 commit 83da61a34ac2d56156077a1f983afdd56d84307b @bmeck bmeck committed Jun 1, 2011
Showing with 284 additions and 259 deletions.
  1. +36 −30 lib/jitsu.js
  2. +36 −18 lib/jitsu/api/apps.js
  3. +20 −12 lib/jitsu/api/snapshots.js
  4. +25 −23 lib/jitsu/commands/apps.js
  5. +52 −43 lib/jitsu/commands/config.js
  6. +5 −4 lib/jitsu/commands/users.js
  7. +57 −96 lib/jitsu/config.js
  8. +52 −33 lib/jitsu/package.js
  9. +1 −0 package.json
View
66 lib/jitsu.js
@@ -79,14 +79,14 @@ jitsu.start = function (argv, callback) {
winston.info('Welcome to ' + 'Nodejitsu'.grey);
winston.info('It worked if it ends with ' + 'Nodejitsu'.grey + ' ok'.green.bold);
jitsu.utils.checkVersion(function () {
- jitsu.config.load(function (err) {
- if (!jitsu.config.username && jitsu.commands.requiresAuth(command[0])) {
+ jitsu.config.get("username",function (err,username) {
+ if (!username && jitsu.commands.requiresAuth(command[0])) {
return jitsu.setupUser(function (err) {
if (err) {
return callback(err);
}
- winston.info('Successfully configured user ' + jitsu.config.username.magenta);
+ winston.info('Successfully configured user ' + username.magenta);
return command.length > 0 ? jitsu.exec(command, callback) : callback();
});
}
@@ -132,36 +132,40 @@ jitsu.exec = function (command, callback) {
//
jitsu.setup = function (callback) {
if (!started) {
- jitsu.users = new jitsu.api.Users(jitsu.config.settings);
- jitsu.apps = new jitsu.api.Apps(jitsu.config.settings);
- jitsu.snapshots = new jitsu.api.Snapshots(jitsu.config.settings);
- started = true;
+ jitsu.config.load(function(err,store){
+ jitsu.users = new jitsu.api.Users(store);
+ jitsu.apps = new jitsu.api.Apps(store);
+ jitsu.snapshots = new jitsu.api.Snapshots(store);
+ started = true;
+ callback();
+ });
}
- callback();
+ else callback();
};
//
// ### function auth (callback)
// #### @callback {function} Continuation to pass control to when complete.
-// Attempts to authenicate the user identified in `jitsu.config.settings.auth`
+// Attempts to authenicate the user identified in `jitsu.config.get("auth")`
//
jitsu.auth = function (callback) {
if (auth) {
return callback();
}
-
- winston.silly('Attempting to authenticate as ' + jitsu.config.username.magenta);
- jitsu.users.auth(function (err, success) {
- if (err || !success) {
- winston.error('Unable to Authenticate as ' + jitsu.config.username.magenta);
- winston.error(err.message);
- return callback(err);
- }
-
- auth = true;
- winston.info('Authenticated as ' + jitsu.config.username.magenta);
- callback();
+ jitsu.config.get("username",function(err,username) {
+ winston.silly('Attempting to authenticate as ' + username.magenta);
+ jitsu.users.auth(function (err, success) {
+ if (err || !success) {
+ winston.error('Unable to Authenticate as ' + username.magenta);
+ winston.error(err.message);
+ return callback(err);
+ }
+
+ auth = true;
+ winston.info('Authenticated as ' + username.magenta);
+ return callback();
+ });
});
};
@@ -174,15 +178,17 @@ jitsu.auth = function (callback) {
jitsu.setupUser = function (callback) {
winston.info('No user has been setup on this machine');
jitsu.prompt.get(['username', 'password'], function (err, result) {
- jitsu.config.settings.auth = [result.username, result.password].join(':');
- jitsu.setup(function () {
- jitsu.auth(function (err) {
- if (err) {
- return callback(err);
- }
-
- jitsu.config.save(function (err) {
- return err ? callback(err) : callback();
+ jitsu.config.set("auth", [result.username, result.password].join(':'), function() {
+ jitsu.setup(function () {
+ jitsu.auth(function (err) {
+ if (err) {
+ return callback(err);
+ }
+
+ jitsu.config.save(function (err) {
+ return err ? callback(err) : callback();
+ });
+ return undefined;
});
});
});
View
54 lib/jitsu/api/apps.js
@@ -28,8 +28,10 @@ util.inherits(Apps, jitsu.api.Client);
// Lists all applications for the authenticated user
//
Apps.prototype.list = function (callback) {
- this._request('GET', ['apps', jitsu.config.username], callback, function (res, result) {
- callback(null, result.apps);
+ jitsu.config.get("username",function(err,username) {
+ this._request('GET', ['apps', username], callback, function (res, result) {
+ callback(null, result.apps);
+ });
});
};
@@ -40,8 +42,10 @@ Apps.prototype.list = function (callback) {
// Creates an application with the specified package.json manifest in `app`.
//
Apps.prototype.create = function (app, callback) {
- this._request('POST', ['apps', jitsu.config.username, app.name], app, callback, function (res, result) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ this._request('POST', ['apps', username, app.name], app, callback, function (res, result) {
+ callback();
+ });
});
};
@@ -52,8 +56,10 @@ Apps.prototype.create = function (app, callback) {
// Views the application specified by `name`.
//
Apps.prototype.view = function (name, callback) {
- this._request('GET', ['apps', jitsu.config.username, name], callback, function (res, result) {
- callback(null, result.app);
+ jitsu.config.get("username",function(err,username) {
+ this._request('GET', ['apps', username, name], callback, function (res, result) {
+ callback(null, result.app);
+ });
});
};
@@ -65,8 +71,10 @@ Apps.prototype.view = function (name, callback) {
// Updates the application with `name` with the specified attributes in `attrs`
//
Apps.prototype.update = function (name, attrs, callback) {
- this._request('PUT', ['apps', jitsu.config.username, name], attrs, callback, function (res, result) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ this._request('PUT', ['apps', username, name], attrs, callback, function (res, result) {
+ callback();
+ });
});
};
@@ -77,8 +85,10 @@ Apps.prototype.update = function (name, attrs, callback) {
// Destroys the application with `name` for the authenticated user.
//
Apps.prototype.destroy = function (name, callback) {
- this._request('DELETE', ['apps', jitsu.config.username, name], callback, function (res, result) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ this._request('DELETE', ['apps', username, name], callback, function (res, result) {
+ callback();
+ });
});
};
@@ -89,8 +99,10 @@ Apps.prototype.destroy = function (name, callback) {
// Starts the application with `name` for the authenticated user.
//
Apps.prototype.start = function (name, callback) {
- this._request('POST', ['apps', jitsu.config.username, name, 'start'], callback, function (res, result) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ this._request('POST', ['apps', username, name, 'start'], callback, function (res, result) {
+ callback();
+ });
});
};
@@ -101,8 +113,10 @@ Apps.prototype.start = function (name, callback) {
// Starts the application with `name` for the authenticated user.
//
Apps.prototype.restart = function (name, callback) {
- this._request('POST', ['apps', jitsu.config.username, name, 'restart'], callback, function (res, result) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ this._request('POST', ['apps', username, name, 'restart'], callback, function (res, result) {
+ callback();
+ });
});
};
@@ -113,8 +127,10 @@ Apps.prototype.restart = function (name, callback) {
// Stops the application with `name` for the authenticated user.
//
Apps.prototype.stop = function (name, callback) {
- this._request('POST', ['apps', jitsu.config.username, name, 'stop'], callback, function (res, result) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ this._request('POST', ['apps', username, name, 'stop'], callback, function (res, result) {
+ callback();
+ });
});
};
@@ -126,7 +142,9 @@ Apps.prototype.stop = function (name, callback) {
// in the current Nodejitsu environment.
//
Apps.prototype.available = function (app, callback) {
- this._request('POST', ['apps', jitsu.config.username, app.name, 'available'], app, callback, function (res, result) {
- callback(null, result);
+ jitsu.config.get("username",function(err,username) {
+ this._request('POST', ['apps', username, app.name, 'available'], app, callback, function (res, result) {
+ callback(null, result);
+ });
});
};
View
32 lib/jitsu/api/snapshots.js
@@ -30,8 +30,10 @@ util.inherits(Snapshots, jitsu.api.Client);
//
Snapshots.prototype.list = function (name, callback) {
winston.info('Listing snapshots for ' + name.magenta);
- this._request('GET', ['apps', jitsu.config.username, name, 'snapshots'], callback, function (res, result) {
- callback(null, result.snapshots);
+ jitsu.config.get("username",function(err,username) {
+ this._request('GET', ['apps', username, name, 'snapshots'], callback, function (res, result) {
+ callback(null, result.snapshots);
+ });
});
};
@@ -44,10 +46,12 @@ Snapshots.prototype.list = function (name, callback) {
// the `*.tgz` package data in `snapshot`.
//
Snapshots.prototype.create = function (appName, snapshotName, filename, callback) {
- var url = ['apps', jitsu.config.username, appName, 'snapshots', snapshotName];
- this._upload(url, 'application/octet-stream', filename, callback, function (res, body) {
- callback(null);
- });
+ jitsu.config.get("username",function(err,username) {
+ var url = ['apps', username, appName, 'snapshots', snapshotName];
+ this._upload(url, 'application/octet-stream', filename, callback, function (res, body) {
+ callback(null);
+ });
+ })
};
//
@@ -58,9 +62,11 @@ Snapshots.prototype.create = function (appName, snapshotName, filename, callback
// `snapshot.id === snapshotName`.
//
Snapshots.prototype.destroy = function (appName, snapshotName, callback) {
- var url = ['apps', jitsu.config.username, appName, 'snapshots', snapshotName];
- this._request('DELETE', url, callback, function (res, body) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ var url = ['apps', username, appName, 'snapshots', snapshotName];
+ this._request('DELETE', url, callback, function (res, body) {
+ callback();
+ });
});
};
@@ -73,8 +79,10 @@ Snapshots.prototype.destroy = function (appName, snapshotName, callback) {
// `snapshot.id === snapshotName`.
//
Snapshots.prototype.activate = function (appName, snapshotName, callback) {
- var url = ['apps', jitsu.config.username, appName, 'snapshots', snapshotName, 'activate'];
- this._request('POST', url, callback, function (res, body) {
- callback();
+ jitsu.config.get("username",function(err,username) {
+ var url = ['apps', username, appName, 'snapshots', snapshotName, 'activate'];
+ this._request('POST', url, callback, function (res, body) {
+ callback();
+ });
});
};
View
48 lib/jitsu/commands/apps.js
@@ -151,31 +151,33 @@ apps.create = function (name, callback) {
pkg.name = name || pkg.name;
jitsu.apps.list(function (err, apps) {
- var existing = apps.filter(function (a) {
- return a.name === pkg.name && a.user === jitsu.config.username;
- });
-
- if (existing.length > 0) {
- return winston.warn('Cannot create duplicate application ' + pkg.name.magenta);
- }
-
- //
- // TODO (indexzero): Configure this default value in nodejitsu APIs
- //
- pkg.state = 'stopped';
-
- winston.info('Checking app availability ' + pkg.name.magenta);
- jitsu.apps.available(pkg, function (err, result) {
- if (!result.available) {
- winston.error('Error creating ' + pkg.name.magenta);
- winston.error(result.message);
- return callback(new Error());
+ jitsu.config.get("username", function(err,username) {
+ var existing = apps.filter(function (a) {
+ return a.name === pkg.name && a.user === username;
+ });
+
+ if (existing.length > 0) {
+ return winston.warn('Cannot create duplicate application ' + pkg.name.magenta);
}
- winston.info('Creating app ' + pkg.name.magenta);
- jitsu.apps.create(pkg, function (err, res, result) {
- winston.silly('Done creating app ' + pkg.name.magenta);
- return err ? callback(err) : callback(null, pkg);
+ //
+ // TODO (indexzero): Configure this default value in nodejitsu APIs
+ //
+ pkg.state = 'stopped';
+
+ winston.info('Checking app availability ' + pkg.name.magenta);
+ jitsu.apps.available(pkg, function (err, result) {
+ if (!result.available) {
+ winston.error('Error creating ' + pkg.name.magenta);
+ winston.error(result.message);
+ return callback(new Error());
+ }
+
+ winston.info('Creating app ' + pkg.name.magenta);
+ jitsu.apps.create(pkg, function (err, res, result) {
+ winston.silly('Done creating app ' + pkg.name.magenta);
+ return err ? callback(err) : callback(null, pkg);
+ });
});
});
});
View
95 lib/jitsu/commands/config.js
@@ -37,8 +37,9 @@ config.set = function (key, value, callback) {
return callback(true, true);
}
- jitsu.config.settings[key] = value;
- jitsu.config.save(callback);
+ jitsu.config.set(key, value, function(err) {
+ jitsu.config.save(callback);
+ });
};
//
@@ -63,12 +64,14 @@ config.get = function (key, callback) {
return callback(true, true);
}
- if (!jitsu.config.settings[key]) {
- return winston.error('No configuration value for ' + key.yellow);
- }
-
- winston.data([key.yellow, jitsu.config.settings[key].magenta].join(' '));
- callback();
+ jitsu.config.get(key,function(err,value) {
+ if(!value) {
+ return winston.error('No configuration value for ' + key.yellow);
+ }
+
+ winston.data([key.yellow, value.magenta].join(' '));
+ callback();
+ })
};
//
@@ -93,18 +96,23 @@ config.delete = function (key, callback) {
winston.warn('No configuration for ' + 'undefined'.magenta);
return callback();
}
- else if (!jitsu.config.settings[key]) {
- winston.warn('No configuration value for ' + key.yellow);
- return callback();
- }
- else if (noDelete.indexOf(key) !== -1) {
- winston.warn('Cannot delete reserved setting ' + key.yellow);
- winston.help('Use jitsu config set <key> <value>');
- return callback();
+ else {
+ jitsu.config.get(key,function(err,value) {
+ if (!value) {
+ winston.warn('No configuration value for ' + key.yellow);
+ return callback();
+ }
+ else if (noDelete.indexOf(key) !== -1) {
+ winston.warn('Cannot delete reserved setting ' + key.yellow);
+ winston.help('Use jitsu config set <key> <value>');
+ return callback();
+ }
+
+ return jitsu.config.clear(key,function(){
+ jitsu.config.save(callback);
+ });
+ })
}
-
- delete jitsu.config.settings[key];
- jitsu.config.save(callback);
};
//
@@ -122,30 +130,31 @@ config.delete.usage = [
// Lists all the key-value pairs in jitsu config.
//
config.list = function (callback) {
- var display = [
- 'Hello ' + jitsu.config.username.green + ' here is your ' + jitsu.config.filepath().grey + ' file:',
- '',
- 'If you\'d like to change a property try:',
- '',
- ' jitsu config set <key> <value>',
- '',
- 'or...',
- '',
- ' jitsu config help',
- ];
-
- display.forEach(function (line) {
- winston.help(line);
- });
-
- jitsu.log.putObject(jitsu.config.settings, {
- auth: function (line) {
- var auth = line.match(/auth.*\:.*\'.*\:([^\']+).*$/)[1];
- return line.replace(auth, '********');
- }
- }, 2);
-
- callback();
+ jitsu.config.load(function(err,store){
+ var display = [
+ 'Hello ' + store.username.green + ' here is your ' + jitsu.config.store.file.grey + ' file:',
+ '',
+ 'If you\'d like to change a property try:',
+ '',
+ ' jitsu config set <key> <value>',
+ '',
+ 'or...',
+ '',
+ ' jitsu config help',
+ ];
+
+ display.forEach(function (line) {
+ winston.help(line);
+ });
+
+ jitsu.log.putObject(store, {
+ auth: function (line) {
+ var auth = line.match(/auth.*\:.*\'.*\:([^\']+).*$/)[1];
+ return line.replace(auth, '********');
+ }
+ }, 2);
+ callback();
+ })
};
//
View
9 lib/jitsu/commands/users.js
@@ -138,10 +138,11 @@ users.confirm.usage = [
// Attempts to logout current user by removing the name from .jitsuconf
//
users.logout = function (callback) {
- delete jitsu.config.settings.auth;
- jitsu.config.save(function (err) {
- winston.warn('User has been logged out');
- callback();
+ jitsu.config.clear("auth",function() {
+ jitsu.config.save(function (err) {
+ winston.warn('User has been logged out');
+ callback();
+ });
});
};
View
153 lib/jitsu/config.js
@@ -5,109 +5,70 @@
*
*/
-var path = require('path'),
+var nconf = require('nconf'),
+ path = require('path'),
winston = require('winston'),
- fs = require('fs'),
- jitsu = require('jitsu');
+ optimist = require('optimist'),
+ fs = require('fs');
-var config = exports, settings = config.settings = {
- root: process.env.HOME,
- protocol: 'http',
- remoteHost: 'api.nodejitsu.com',
- userconfig: '.jitsuconf',
- loglevel: 'info',
- tmproot: '/tmp',
- tar: 'tar',
- gzipbin: 'gzip'
-};
+//Set up our default config
+var dir = process.cwd();
+
+var looking = true;
+var configPath = undefined;
+while(looking) {
+ try {
+ fs.statSync(configPath = path.join(dir,".jitsuconf"));
+ looking = false;
+ }
+ catch(e) {
+ var olddir = dir;
+ dir = path.join(dir,"..");
+ if(olddir == dir) {
+ try {
+ fs.statSync(configPath = path.join(process.env.HOME,".jitsuconf"))
+ looking = false;
+ }
+ catch(e) {
+
+ }
+ }
+ }
+}
+if(configPath) {
+ winston.info("Using config file"+ configPath.magenta)
+ nconf.use( 'file', { file: path.join( process.env.HOME, '.jitsuconf' ) } );
+}
-//
-// Define the `remoteUri` property for the settings object
-//
-Object.defineProperty(config.settings, 'remoteUri', {
+var defaults = {
+ "root": process.env.HOME,
+ "protocol": "http",
+ "remoteHost": "api.nodejitsu.com",
+ "userconfig": ".jitsuconf",
+ "loglevel": "info",
+ "tmproot": "/tmp",
+ "tar": "tar",
+ "gzipbin": "gzip"
+};
+Object.defineProperty(defaults, 'remoteUri', {
get: function () {
var port = this.port ? ':' + this.port : '';
return [this.protocol, '://', this.remoteHost, port].join('');
}
});
-//
-// Configure the default winston logger for CLI output
-// and the set the default console log level to `info`.
-//
-winston.cli();
-winston.defaultTransports().console.level = 'info';
-
-//
-// ### function load (callback)
-// #### @callback {function} Continuation to pass control to when complete.
-// Loads the settings for this process.
-//
-config.load = function (callback) {
- fs.readFile(config.filepath(), function (err, data) {
- if (err && /ENOENT, No such file/.test(err.message)) {
- //
- // If there is no configuration file, save the default configuration
- // then reload the configuration.
- //
- return config.save(function (err) {
- return err ? callback(err) : config.load(callback);
- });
- }
- else if (err) {
- return callback(err);
- }
-
- //
- // Load all config data into `jitsu.config.settings`.
- //
-
- try {
- data = JSON.parse(data.toString());
+var overrides = optimist.argv
+var oldget = nconf.get
+nconf.get = function(key,callback) {
+ winston.info("looking for "+key.green)
+ if(overrides.hasOwnProperty(key)) callback(false,overrides[key])
+ debugger;
+ oldget.call(nconf,key,function(err,value) {
+ if(err) {
+ if(defaults.hasOwnProperty(key)) callback(false,defaults[key])
+ else callback(err)
}
- catch (err) {
- winston.error(config.filepath().grey + ' contains invalid JSON');
- winston.warn('Regenerating ' + '.jitsuconf'.grey + ' file');
- return jitsu.setupUser(callback);
- }
- Object.keys(data).forEach(function (key) {
- config.settings[key] = data[key];
- });
-
- //
- // Set the default console log level to `info`.
- //
- winston.defaultTransports().console.level = config.settings.loglevel || 'info';
-
- callback();
- });
-};
-
-//
-// ### function save (callback)
-// #### @callback {function} Continuation to pass control to when complete.
-// Saves the settings to the specified location for `.jitsuconf`
-//
-config.save = function (callback) {
- fs.writeFile(config.filepath(), JSON.stringify(config.settings, null, 2), function (err) {
- return err ? callback(err) : callback();
- });
-};
-
-//
-// ### function filepath ()
-// Gets the full path for the user config file.
-//
-config.filepath = function () {
- return path.join(settings.root, settings.userconfig);
-};
-
-//
-// ### @username {string}
-// Username for the user authenticated in this process.
-//
-Object.defineProperty(config, 'username', {
- get: function () {
- return settings.auth ? settings.auth.split(':')[0] : '';
- }
-});
+ else callback(false,value)
+ })
+}
+module.exports = nconf;
View
85 lib/jitsu/package.js
@@ -24,13 +24,17 @@ var package = exports;
// Attempts to read the package.json from the specified `dir`. If it is
// unable to do, walks the user through creating a new one from scratch.
//
-package.get = function (dir, callback) {
+package.get = function (dir, options, callback) {
+ if(!callback) {
+ callback = options;
+ options = {};
+ }
package.read(dir, function (err, pkg) {
if (err) {
return package.create(dir, callback);
}
- package.validate(pkg, dir, function (err, updated) {
+ package.validate(pkg, dir, options, function (err, updated) {
return err ? callback(err) : callback(null, updated);
});
});
@@ -131,7 +135,11 @@ package.create = function (dir, callback) {
// Validates the specified `pkg` against the properties list
// returned from `package.properties(dir)`.
//
-package.validate = function (pkg, dir, callback) {
+package.validate = function (pkg, dir, options, callback) {
+ if(!callback) {
+ callback = options;
+ options = {};
+ }
var properties = package.properties(dir),
missing = [];
@@ -186,7 +194,10 @@ package.validate = function (pkg, dir, callback) {
})
}
- tryAnalyze(pkg);
+ if(pkg.deploy && pkg.deploy.hasProperty("resolveDeps") && !pkg.deploy.resolveDeps)
+ callback(null, []);
+ else
+ tryAnalyze(pkg);
});
};
@@ -281,35 +292,43 @@ package.createTarball = function (dir, version, callback) {
dir = dir.slice(0, -1);
}
- var parent = path.dirname(dir),
- base = path.basename(dir),
- tarball = path.join(jitsu.config.settings.tmproot, [jitsu.config.username, pkg.name, version || pkg.version].join('-') + '.tgz'),
- target = fs.createWriteStream(tarball),
- tarargs = ['-cvf', '-', '-C', parent, base],
- tar, gzip, errState;
-
- //
- // TODO (indexzero) Support for `.jitsuignore` files and support for package.json files
- //
- tar = spawn(jitsu.config.settings.tar, tarargs);
- gzip = spawn(jitsu.config.settings.gzipbin, ["--stdout"]);
-
- //
- // TODO (indexzero) Make this piping more robust
- //
- util.pump(tar.stdout, gzip.stdin);
- util.pump(gzip.stdout, target);
-
- target.on("close", function (err, ok) {
- if (errState) {
- return;
- }
- else if (err) {
- return callback(errState = err);
- }
-
- callback(null, pkg, tarball);
- });
+ jitsu.config.get("tmproot",function(err,tmproot) {
+ jitsu.config.get("username", function(err,username) {
+ jitsu.config.get("tar", function(err,tar) {
+ jitsu.config.get("gzipbin", function(err,gzipbin) {
+ var parent = path.dirname(dir),
+ base = path.basename(dir),
+ tarball = path.join(tmproot, [username, pkg.name, version || pkg.version].join('-') + '.tgz'),
+ target = fs.createWriteStream(tarball),
+ tarargs = ['-cvf', '-', '-C', parent, base],
+ tar, gzip, errState;
+
+ //
+ // TODO (indexzero) Support for `.jitsuignore` files and support for package.json files
+ //
+ tar = spawn(tar, tarargs);
+ gzip = spawn(gzipbin, ["--stdout"]);
+
+ //
+ // TODO (indexzero) Make this piping more robust
+ //
+ util.pump(tar.stdout, gzip.stdin);
+ util.pump(gzip.stdout, target);
+
+ target.on("close", function (err, ok) {
+ if (errState) {
+ return undefined;
+ }
+ else if (err) {
+ return callback(errState = err);
+ }
+
+ return callback(null, pkg, tarball);
+ });
+ });
+ });
+ });
+ })
});
};
View
1 package.json
@@ -18,6 +18,7 @@
"async": "0.1.x",
"colors": "0.x.x",
"eyes": "0.1.x",
+ "nconf": "0.1.9",
"optimist": "0.2.x",
"progress": "0.0.x",
"request": "1.9.x",

0 comments on commit 83da61a

Please sign in to comment.