Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial support for running seed from the command line

  • Loading branch information...
commit 34cdb7d0959ba11f149c9ac14334fe938134b113 1 parent 286b55f
Charles Jolley authored
Showing with 928 additions and 171 deletions.
  1. +7 −53 REPOSITORY
  2. +8 −0 bin/seed
  3. +0 −26 bootstrap/seed.js
  4. 0  {packages/seed → }/default.json
  5. 0  {packages/seed → }/fixtures/basic/lib/bar.js
  6. 0  {packages/seed → }/fixtures/basic/lib/bar/baz.js
  7. 0  {packages/seed → }/fixtures/basic/lib/foo.js
  8. 0  {packages/seed → }/fixtures/basic/package.json
  9. 0  {packages/seed → }/fixtures/basic/packages/foo/lib/bar.js
  10. 0  {packages/seed → }/fixtures/basic/packages/foo/lib/baz.js
  11. 0  {packages/seed → }/fixtures/basic/packages/foo/lib/index.js
  12. 0  {packages/seed → }/fixtures/basic/packages/foo/package.json
  13. 0  {packages/seed → }/fixtures/basic/packages/foopkg/lib/index.js
  14. 0  {packages/seed → }/fixtures/basic/packages/foopkg/package.json
  15. 0  {packages/seed → }/fixtures/demo_repository/config.json
  16. 0  {packages/seed → }/fixtures/demo_repository/packages/bar-3.2.1/lib/index.js
  17. 0  {packages/seed → }/fixtures/demo_repository/packages/bar-3.2.1/package.json
  18. 0  {packages/seed → }/fixtures/demo_repository/packages/foo-1.2.1/lib/index.js
  19. +7 −0 fixtures/demo_repository/packages/foo-1.2.1/package.json
  20. 0  {packages/seed → }/fixtures/demo_repository/packages/foo-2.0.0/lib/index.js
  21. +7 −0 fixtures/demo_repository/packages/foo-2.0.0/package.json
  22. +11 −0 fixtures/installing/package.json
  23. +7 −0 fixtures/installing/scripts/setup.js
  24. +7 −0 fixtures/installing/scripts/teardown.js
  25. +8 −8 packages/seed/tests/package/pathForModule.js → index.js
  26. +10 −0 {packages/seed → }/lib/co.js
  27. +189 −0 lib/commands.js
  28. +7 −0 {packages/seed → }/lib/config.js
  29. +40 −0 lib/index.js
  30. +89 −0 lib/loader.js
  31. +123 −17 {packages/seed → }/lib/package.js
  32. +29 −1 {packages/seed → }/lib/repository.js
  33. +1 −1  {packages/seed → }/lib/resource.js
  34. +24 −20 {packages/seed → }/lib/sandbox.js
  35. +126 −16 packages/seed/lib/index.js → lib/seed.js
  36. 0  {packages/seed → }/lib/semver.js
  37. +18 −0 package.json
  38. +0 −7 packages.json
  39. +0 −4 packages/seed/fixtures/demo_repository/packages/foo-1.2.1/package.json
  40. +0 −4 packages/seed/fixtures/demo_repository/packages/foo-2.0.0/package.json
  41. +0 −5 packages/seed/package.json
  42. +11 −0 {packages/seed → }/tests/co/path.js
  43. +38 −0 tests/commands/collectPluginInfo.js
  44. 0  {packages/seed → }/tests/common.js
  45. +6 −5 {packages/seed → }/tests/package/info.js
  46. 0  {packages/seed → }/tests/package/open.js
  47. 0  {packages/seed → }/tests/package/openGlobalConfig.js
  48. +73 −0 tests/package/setup_teardown.js
  49. 0  {packages/seed → }/tests/repository/compatiblePackage.js
  50. 0  {packages/seed → }/tests/repository/open.js
  51. +2 −2 {packages/seed → }/tests/resource.js
  52. +2 −2 {packages/seed/tests/index → tests/seed}/canonical.js
  53. +78 −0 tests/seed/packageList.js
  54. 0  {packages/seed/tests/index → tests/seed}/require.js
  55. 0  {packages/seed → }/tests/semver.js
View
60 REPOSITORY
@@ -1,56 +1,10 @@
-Repository lives at:
+A repository contains packages. Seed will search repositories when it can't find a module in the local package or in nested (frozen) packages.
-~/.seeds
-/usr/local/seeds
+By default, seed looks for a repository at ~/.seeds and /usr/local/seeds.
+You can change this by adding a local.json file to the seed package itself.
-Use .seeds/config.json to change settings
-
---
-
-The repository has a config file then one or more git repositories and then
-checkouts for specific versions
-
-~/.seeds/
- config.json // JSON config file
- packages.json // all known packages by version in repo
- packages/ // checked out package
- sproutcore-1.0.1046/ versioned package
-
---
-
-You can actually have multiple seed installs on your machine. When you start
-an app, the seed.HOME [discovered by walking up the chain looking for a ]
-
---
-
-== Canonical Module ID
-
-A canonical module ID is used to uniquely identify a package to the system.
-
-::repo:packageId:vers:moduleId
-
-example:
-
-::root:1.1.0:sproutcore/runtime:core
-
-- The first :: indicates that this is a canonical id.
-- The next segment indicates the source repository. root refers to packages loaded directly from disk and not out of a repository. Alternatively this may be a repository name or path
-
-::user:1.1.0:sproutcore/runtime:core
-
-canonical moduleIds are used to maintain module caches but otherwise aren't
-usually required.
-
-== How Packages are Resolved
-
-When you require() a module from package other than the current one, Seed uses
-an algorithm to try to locate the package:
-
-- first we look for a packageId in the local packages directory. If the packageId contains slashes, we look inside nested packages. i.e. for sproutcore/runtime we will look inside packages/sproutcore/packages/runtime
-
-- if not found there, we look in the packages directory of the owner package. we perform this search recursively until we reach a top-level package.
-
-- if a package is found in a local dir this way, we check to make sure the version is compatible with whatever is required by the current package, if anything. if it is not, we throw an error
-
-- if no package is found locally, we consult any built-in repositories. The repository is simply required to try to locate a version of the package that matches the requirement.
+== Package Installation
+Whenever a package is installed, it's contents are copied into the
+repository's directory and then if there are any scripts named in the package
+config's "scripts.install" property they will be run
View
8 bin/seed
@@ -0,0 +1,8 @@
+#!/usr/bin/env node
+
+var seed = require('seed');
+var commands = seed.require('seed:commands');
+
+// first two args are 'node' and path to this binary
+var args = Array.prototype.slice.call(process.argv, 2);
+commands.invokeSync(args.shift(), args);
View
26 bootstrap/seed.js
@@ -1,26 +0,0 @@
-/*globals process require __filename */
-
-/**
- @file
-
- This bootstrap module will actually locate the local seed package and
- bootstrap it, allowing the rest of the seed library to be used like normal.
-
-*/
-
-var path = require('path'),
- sys = require('sys'),
- fs = require('fs'),
- SEED_PATH, seed ;
-
-// if this file is still inside the "bootstrap" directory then it has not
-// been installed yet and we need to look locally.
-if (__filename.match(/seed.bootstrap.seed\.js$/)) {
- SEED_PATH = path.normalize(path.join(__filename, '..', '..'));
-} else {
- SEED_PATH = path.normalize(path.join(process.env.HOME, '.seeds'));
-}
-
-SEED_PATH = path.join(SEED_PATH, 'packages', 'seed', 'lib', 'index');
-module.exports = require(SEED_PATH); // load seed and map in exports
-
View
0  packages/seed/default.json → default.json
File renamed without changes
View
0  packages/seed/fixtures/basic/lib/bar.js → fixtures/basic/lib/bar.js
File renamed without changes
View
0  packages/seed/fixtures/basic/lib/bar/baz.js → fixtures/basic/lib/bar/baz.js
File renamed without changes
View
0  packages/seed/fixtures/basic/lib/foo.js → fixtures/basic/lib/foo.js
File renamed without changes
View
0  packages/seed/fixtures/basic/package.json → fixtures/basic/package.json
File renamed without changes
View
0  packages/seed/fixtures/basic/packages/foo/lib/bar.js → fixtures/basic/packages/foo/lib/bar.js
File renamed without changes
View
0  packages/seed/fixtures/basic/packages/foo/lib/baz.js → fixtures/basic/packages/foo/lib/baz.js
File renamed without changes
View
0  ...ges/seed/fixtures/basic/packages/foo/lib/index.js → fixtures/basic/packages/foo/lib/index.js
File renamed without changes
View
0  ...ges/seed/fixtures/basic/packages/foo/package.json → fixtures/basic/packages/foo/package.json
File renamed without changes
View
0  .../seed/fixtures/basic/packages/foopkg/lib/index.js → fixtures/basic/packages/foopkg/lib/index.js
File renamed without changes
View
0  .../seed/fixtures/basic/packages/foopkg/package.json → fixtures/basic/packages/foopkg/package.json
File renamed without changes
View
0  packages/seed/fixtures/demo_repository/config.json → fixtures/demo_repository/config.json
File renamed without changes
View
0  ...s/demo_repository/packages/bar-3.2.1/lib/index.js → ...s/demo_repository/packages/bar-3.2.1/lib/index.js
File renamed without changes
View
0  ...s/demo_repository/packages/bar-3.2.1/package.json → ...s/demo_repository/packages/bar-3.2.1/package.json
File renamed without changes
View
0  ...s/demo_repository/packages/foo-1.2.1/lib/index.js → ...s/demo_repository/packages/foo-1.2.1/lib/index.js
File renamed without changes
View
7 fixtures/demo_repository/packages/foo-1.2.1/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "foo",
+ "version": "1.2.1",
+ "seed": {
+ "from": "foo-1.2.1"
+ }
+}
View
0  ...s/demo_repository/packages/foo-2.0.0/lib/index.js → ...s/demo_repository/packages/foo-2.0.0/lib/index.js
File renamed without changes
View
7 fixtures/demo_repository/packages/foo-2.0.0/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "foo",
+ "version": "2.0.0",
+ "seed": {
+ "from": "foo-2.0.0"
+ }
+}
View
11 fixtures/installing/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "installing",
+ "version": "1.0.0",
+
+ "description": "used to test installing a package into a repository",
+
+ "scripts": {
+ "setup": "scripts/setup.js",
+ "teardown": "scripts/teardown.js"
+ }
+}
View
7 fixtures/installing/scripts/setup.js
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path'),
+ fs = require('fs');
+
+var out = path.normalize(path.join(__dirname, '..', 'SETUP.out'));
+fs.writeFileSync(out, 'setup '+process.cwd());
View
7 fixtures/installing/scripts/teardown.js
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path'),
+ fs = require('fs');
+
+var out = path.normalize(path.join(__dirname, '..', 'TEARDOWN.out'));
+fs.writeFileSync(out, 'teardown '+ process.cwd());
View
16 packages/seed/tests/package/pathForModule.js → index.js
@@ -3,14 +3,14 @@
// Copyright: ©2009-2010 Apple Inc. All rights reserved.
// License: Licened under MIT license (see __preamble__.js)
// ==========================================================================
-/*global process path sys assert libDir */
-process.mixin(require('../common'));
+/**
+ @file
-var Package = require('package');
-var pkgDir = path.dirname(libDir);
+ Bootstraps the seed package manager for node. Place the seed directory
+ into your .node_libraries folder. When you require('seed') you will get
+ this file back [which really just forwards to the package index].
+
+*/
-var pkg = new Package(pkgDir);
-
-sys.puts(pkg.pathForModule('package'));
-sys.puts(pkg.pathForModule('foo'));
+exports = module.exports = require('./lib/index');
View
10 packages/seed/lib/co.js → lib/co.js
@@ -3,6 +3,7 @@
// Copyright: ©2009-2010 Apple Inc. All rights reserved.
// License: Licened under MIT license (see __preamble__.js)
// ==========================================================================
+/*globals process */
/**
@file
@@ -714,6 +715,15 @@ Co.path.exists = function(path, done) {
});
};
+// extend normalize to understand ~
+var _normalize = Co.path.normalize;
+Co.path.normalize = function(path) {
+ if (path.match(/^~[\/\\]/)) {
+ path = Co.path.join(process.env.HOME, path.slice(1));
+ }
+ return _normalize(path);
+};
+
/**
Create the named directory, including any other components in the path
above it. If the directory already exists, does nothing.
View
189 lib/commands.js
@@ -0,0 +1,189 @@
+// ==========================================================================
+// Project: Seed - Flexible Package Manager
+// Copyright: ©2009-2010 Apple Inc. All rights reserved.
+// License: Licened under MIT license (see __preamble__.js)
+// ==========================================================================
+
+var Co = require('./co');
+var semver = require('./semver');
+
+var seed = require.seed || require('./index'); // depends on how we're invoked
+var Cmds = exports;
+
+// ..........................................................
+// LIST COMMAND
+//
+
+Cmds.list = function(cmd, args, done) {
+ seed.packageList(function(err, list) {
+ if (err) return done(err);
+ Co.sys.puts(Object.keys(list).sort().map(function(packageId) {
+ var vers = list[packageId];
+ vers = vers.sort(function(a,b) { return semver.compare(a,b); });
+ return packageId+' ('+vers.join(',')+')';
+ }).join("\n"));
+ return done();
+ });
+};
+Cmds.list.summary = "Lists installed packages and their versions";
+Cmds.list.usage = "list [PACKAGE] [VERSION] --verbose";
+
+// ..........................................................
+// INSTALL COMMAND
+//
+
+Cmds.install = function(cmd, args, done) {
+ Co.sys.debug('Cmds.install ' + Co.sys.inspect(args));
+ return done();
+};
+Cmds.install.summary = "Install or update a package";
+
+// ..........................................................
+// REMOVE COMMAND
+//
+
+Cmds.remove = function(cmd, args, done) {
+ Co.sys.debug('Cmds.remove ' + Co.sys.inspect(args));
+ return done();
+};
+Cmds.remove.summary = "Remove an installed package";
+
+// ..........................................................
+// UPDATE COMMAND
+//
+
+Cmds.update = function(cmd, args, done) {
+ Co.sys.debug('Cmds.update ' + Co.sys.inspect(args));
+ return done();
+};
+Cmds.update.summary = "Update an installed package";
+
+// ..........................................................
+// HELP COMMAND
+//
+
+// cool trick...
+var SPACES_ARRAY = [];
+function spaces(cnt) {
+ SPACES_ARRAY.length = cnt+1;
+ return SPACES_ARRAY.join(' ');
+}
+
+Cmds.help = function(name, args, done) {
+ var text = [
+ "Seed v"+module.pkg.version() + ' Flexible Package Manager for Node.js',
+ "",
+ "usage: seed COMMAND [ARGS]",
+ "",
+ "Installed commands:"];
+
+ Cmds.commands(function(err, commands) {
+ if (err) return done(err);
+ var summaries = Object.keys(commands).sort().map(function(cmd) {
+ var packageId = commands[cmd];
+ var exports = require(packageId);
+ if (!exports || !exports[cmd]) {
+ return [cmd, 'not found in '+packageId];
+ } else {
+ return [cmd, exports[cmd].summary || 'no summary'];
+ }
+ });
+
+ // format into columns
+ var maxLen = summaries.reduce(function(prev, curStr) {
+ return Math.max(prev, curStr[0].length);
+ }, 0);
+
+ summaries.forEach(function(summary) {
+ text.push(' '+ summary[0] + spaces(3+maxLen-summary[0].length) + summary[1]);
+ });
+
+ text.push('');
+ Co.sys.puts(text.join("\n"));
+ return done();
+ });
+};
+Cmds.help.summary = "Show this help message";
+
+
+// ..........................................................
+// SUPPORT API
+//
+
+/**
+ Invokes callback with hash of plugin information
+*/
+Cmds.collectPluginInfo = Co.once(function(done) {
+ var seedPackage = module.pkg || seed.seedPackage;
+ seed.preferredPackageList(seedPackage, function(err, list) {
+ if (err) return done(err);
+ Co.reduce(Object.keys(list), {}, function(ret, packageId, done) {
+ seed.openPackage(packageId, function(err, pkg) {
+ if (err) return done(err);
+ var config = pkg.info('seed'); // look for a seed config
+ if (config) ret[packageId] = config;
+ return done(null, ret);
+ });
+ })(done);
+ });
+});
+
+/**
+ Invokes callback with hash of commands mapped to property paths
+*/
+Cmds.commands = Co.once(function(done) {
+ Cmds.collectPluginInfo(function(err, pluginInfo) {
+ if (err) return done(err);
+
+ var ret = Co.mixin({}, pluginInfo['seed'].commands);
+ Object.keys(pluginInfo).forEach(function(packageId) {
+ if (packageId === 'seed') return ; // skip since we put it there first
+
+ var commands = pluginInfo[packageId].commands;
+ if (!commands) return ; // nothing to do
+
+ for(var key in commands) {
+ if (!commands.hasOwnProperty(key)) continue;
+ var path = commands[key];
+ if (path.indexOf(':')<0) path = packageId + ':' + path; // namespace
+ ret[key.toLowerCase()] = path;
+ }
+ });
+
+ done(null, ret);
+ });
+});
+
+/**
+ Invokes a named command. This will first go find all commands installed
+ on the system.
+*/
+Cmds.invoke = function(cmd, args, done) {
+ if (arguments.length<2) throw "invoke() requires least cmd and callback";
+
+ Cmds.commands(function(err, commands) {
+ if (err) return done(err);
+ var packageId = commands[cmd.toLowerCase()];
+ if (!packageId) {
+ Cmds.unknown.apply(cmd, args, done);
+ } else {
+ var exports = require(packageId);
+ if (!exports) Cmds.unknown.apply(cmd, args, done);
+ else exports[cmd](cmd, args, done);
+ }
+ });
+};
+
+Cmds.invokeSync = function(cmd, args) {
+ return Co.wait(function(done) {
+ Cmds.invoke(cmd, args, done);
+ });
+};
+
+/**
+ Invoked whenever you call an unknown command
+*/
+Cmds.unknown = function(name, args, done) {
+ Co.sys.puts("Command Unknown: " + name);
+ Cmds.help(null, done);
+};
View
7 packages/seed/lib/config.js → lib/config.js
@@ -105,8 +105,15 @@ var Config = Co.extend(Resource, {
if (err) return done(err);
try {
+
+ // strip comments
+ content = content.split("\n").map(function(line) {
+ return line.match(/^\s*\/\//) ? '' : line;
+ }).join("\n");
+
config.db = JSON.parse(content);
} catch(e) {
+ e = 'parse error in '+config.path+' error: '+e;
return done(e);
}
View
40 lib/index.js
@@ -0,0 +1,40 @@
+// ==========================================================================
+// Project: Seed - Flexible Package Manager
+// Copyright: ©2009-2010 Apple Inc. All rights reserved.
+// License: Licened under MIT license (see __preamble__.js)
+// ==========================================================================
+/*globals __filename */
+
+var Co = require('./co'),
+ Seed = require('./seed'),
+ Package = require('./package'),
+ Repository = require('./repository'),
+ seed, path, seedPackage;
+
+// create a default seed. This is usually what people will work with
+seed = module.exports = new Seed('default');
+seed.Seed = Seed; // export class so it's easy to create your own
+
+// bootstrap in the current seed package and any default repositories
+// this has to be done sync before the require returns
+path = Co.path.normalize(Co.path.join(Co.path.dirname(__filename), '..'));
+
+Co.wait(function(done) {
+ Package.open(path, function(err, seedPackage) {
+ if (err) return done(err);
+ seed.register(seedPackage); // always fallback to ourself
+ seed.seedPackage = seedPackage ;
+
+ var repoPaths = seedPackage.info('seed');
+ if (repoPaths) repoPaths = repoPaths.repositories;
+ if (!repoPaths) repoPaths = [];
+
+ Co.each(repoPaths, function(path, done) {
+ Repository.open(path, function(err, repo) {
+ if (err) return done(err);
+ seed.register(repo, done);
+ });
+ })(done);
+ });
+});
+
View
89 lib/loader.js
@@ -0,0 +1,89 @@
+// ==========================================================================
+// Project: Seed - Flexible Package Manager
+// Copyright: ©2009-2010 Apple Inc. All rights reserved.
+// License: Licened under MIT license (see __preamble__.js)
+// ==========================================================================
+/*globals __filename */
+
+
+var Co = require('./co'),
+ Seed, Loader ;
+
+/**
+ A loader actually retrieves a module from disk and converts it into a
+ factory function. When you register new loaders, you provide a module
+ that implements the loadModule() method. You can extend the Loader class
+ if that makes your like easier.
+
+ Return null if you can't handle the named path.
+*/
+Loader = Co.extend({
+
+ /**
+ Loads an actual module.
+
+ @param {String} desc
+ Describes the module and its loading context. Contains at least
+ path and moduleId properties.
+
+ @param {Function} done
+ invoke with module factory or null if not handled
+
+ @returns {void}
+ */
+ loadModule: function(desc, done) {
+ if (Co.path.extname(desc.path) !== '.js') return done(); // not handled
+
+ var loader = this;
+
+ // TODO: implement pluggable coders
+ Co.fs.readFile(desc.path, function(err, text) {
+ if (err) return done(err);
+
+ loader.evaluate(text, desc, function(err, factory) {
+ if (err) return done(err);
+ factory.__filename = desc.path;
+ factory.__dirname = Co.path.dirname(desc.path);
+ loader.annotate(factory, text, desc, function(err) {
+ if (err) return done(err);
+ else return done(null, factory);
+ });
+ });
+ });
+ },
+
+ /**
+ Evaluates the loaded text of the module. Should return a factory
+ function. The function will be annotated later as needed.
+
+ Default implementation just wraps code in a wrapper.
+ */
+ evaluate: function(text, desc, done) {
+ if (!Seed) Seed = require('./seed');
+
+ var ret ;
+ try {
+ ret = Seed.evaluate(text, desc.path);
+ } catch(e) {
+ e = 'error during eval for ' + desc.path + ' error: ' + e;
+ return done(e);
+ }
+
+ return done(null, ret);
+ },
+
+ /**
+ Annotates the factory function with additional information that may be
+ used by other processors. Default just sets the moduleId. Invoke
+ callback when you are finished
+ */
+ annotate: function(factory, text, desc, done) {
+ factory.info = { id: desc.moduleId };
+ done();
+ }
+
+});
+
+exports = module.exports = new Loader();
+exports.Loader = Loader;
+
View
140 packages/seed/lib/package.js → lib/package.js
@@ -9,7 +9,7 @@ var Resource = require('./resource'),
Config = require('./config'),
Co = require('./co'),
semver = require('./semver'),
- Seed, Package;
+ Seed, Package, defaultLoader;
var IncompatibleVersionError = Co.extend(Error, {
@@ -82,9 +82,18 @@ Package = Co.extend(Resource, {
return done(err, null);
} else return done(null, foundPackage);
});
- },
+ },
/**
+ return true if the passed packageId and version is compatible
+ */
+ packageIsCompatible: function(packageId, vers) {
+ var required = this.info('dependencies');
+ if (required) required = required[packageId];
+ return required ? semver.compatible(required, vers) : true;
+ },
+
+ /**
Returns all packages directly nested underneath the current package.
This will open each package, disposing of any packages with duplicate
ids.
@@ -220,6 +229,21 @@ Package = Co.extend(Resource, {
});
},
+ /**
+ Returns a hash of packageId's, including nested package, visible to the
+ current package. The value of each packageId is an array of versions
+ for all known packages.
+ */
+ packageList: function(done) {
+ var ret = {};
+ ret[this.name()] = [this.version()]; // put in my own
+ this.openPackages(function(err, packages) {
+ if (err) return done(err);
+ packages.forEach(function(pkg) { ret[pkg.name()] = [pkg.version()]; });
+ return done(null, ret);
+ });
+ },
+
// ..........................................................
// MODULE LOADING
//
@@ -269,6 +293,9 @@ Package = Co.extend(Resource, {
Invokes callback with a boolean set to true if the named moduleId exists
in the current package.
+ @param {Seed} seed
+ the seed requesting whether the module exists or not
+
@param {String} moduleId
the module id to load
@@ -285,9 +312,20 @@ Package = Co.extend(Resource, {
},
/**
+ Returns the loaders supported by this package. Defaults to seed:loader
+ */
+ loaders: function() {
+ return this.info('loaders') || ['seed:loader'];
+ },
+
+ /**
Attempts to load the named module from the package. Returns a factory
function annotated with an info hash, __filename, and __dirname.
+ @param {Sandbox} sandbox
+ The sandbox requesting the module. Can be used to fetch other modules
+ as needed
+
@param {String} moduleId
the module id to load
@@ -297,28 +335,60 @@ Package = Co.extend(Resource, {
@returns {void}
*/
- loadModule: function(moduleId, done) {
+ loadModule: function(sandbox, moduleId, done) {
+ var loaders = this.loaders(),
+ loading = this._loading,
+ pkg = this, top;
+
+ // load the loaders - avoid cyclical references
+ loaders = loaders.map(function(loaderId) {
+ var ret ;
+
+ // there's always the money in the default loader...
+ if (loaderId === 'seed:loader') {
+ if (!defaultLoader) defaultLoader = require('./loader');
+ return defaultLoader;
+ } else {
+ if (!loading) {
+ top = true; // will need to cleanup when done
+ loading = this._loading = [];
+ }
+
+ if (loading.indexOf(loaderId)>=0) return null ; // skip this time
+ loading.push(loaderId);
+ ret = sandbox.require(loaderId);
+ loading[loading.indexOf(loaderId)] = null;
+ return ret ;
+ }
+ });
+ if (top) this._loading = null; // cleanup only at top
+
+ // ok we found the loaders, now let's try to load some modules...
this.findModulePath(moduleId, function(err, path) {
if (!err && !path) {
err = new Error(this.name() + ':' + moduleId + ' not found');
}
-
if (err) return done(err);
- // TODO: implement pluggable coders
- Co.fs.readFile(path, function(err, text) {
- if (err) return done(err);
-
- if (!Seed) Seed = require('./index');
- var factory = Seed.evaluate(text);
-
- // TODO: parse text for further build opts
- factory.info = { id: moduleId };
- factory.__filename = path;
- factory.__dirname = Co.path.dirname(path);
+ var desc = {
+ path: path,
+ moduleId: moduleId,
+ owner: this,
+ sandbox: sandbox
+ };
+
+ var factory ;
+
+ Co.find(loaders, function(loader, done) {
+ loader.loadModule(desc, function(err, loaderFactory) {
+ if (err) return done(err);
+ else {
+ factory = loaderFactory;
+ done(null, !!loaderFactory); // stop when not null
+ }
+ });
- return done(null, factory);
- });
+ })(function(err) { return done(err, factory); }); // ignore found loader
});
},
@@ -345,6 +415,42 @@ Package = Co.extend(Resource, {
},
// ..........................................................
+ // INSTALL/REMOVE COMMANDS
+ //
+
+ /**
+ Runs the install command if possible on the package. Calls done when
+ finished. This looks for a scripts.install config and runs that.
+ */
+ setup: function(done) {
+ var pkg = this;
+ this.open(function(err) {
+ if (err) return done(err);
+
+ var cmd = pkg.info('scripts');
+ if (cmd) cmd = cmd.setup;
+ if (cmd) return Co.sys.exec('cd '+pkg.path+'; '+ cmd, done);
+ else return done();
+ });
+ },
+
+ /**
+ Runs the remove command if possible on the package. Calls done when
+ finished. This looks for a scripts.remove config and runs that.
+ */
+ teardown: function(done) {
+ var pkg = this;
+ this.open(function(err) {
+ if (err) return done(err);
+
+ var cmd = pkg.info('scripts');
+ if (cmd) cmd = cmd.teardown;
+ if (cmd) return Co.sys.exec('cd '+pkg.path+'; '+ cmd, done);
+ else return done();
+ });
+ },
+
+ // ..........................................................
// RESOURCE PRIMITIVES
//
View
30 packages/seed/lib/repository.js → lib/repository.js
@@ -52,6 +52,11 @@ var Repository = Co.extend(Resource, {
});
},
+ infoForPath: function(path) {
+ var ret = Co.path.basename(path).match(/^(.+)\-([^\-]+\..+)$/);
+ return ret ? [ret[1],ret[2]] : [];
+ },
+
/**
Attempts to discover a compatible package installed in the receiver.
Invokes the passed callback with the found package instance or null if
@@ -67,13 +72,14 @@ var Repository = Co.extend(Resource, {
invoked when package is discovered or not
*/
compatiblePackage: function(packageId, vers, done) {
+ var repo = this;
this.findPackagePaths(packageId, function(err, paths) {
if (err) return done(err);
// find newest compatible package based on version
var ret, retVers ;
paths.forEach(function(path) {
- var curVersion = path.match(/\-([^\-]+\..+)$/)[1];
+ var curVersion = repo.infoForPath(path)[1];
if (semver.compatible(vers, curVersion)) {
if (!ret || (semver.compare(retVers, curVersion)<0)) {
ret = path;
@@ -109,6 +115,28 @@ var Repository = Co.extend(Resource, {
return ((value===undefined) && ('string' === typeof key)) ? ret : this;
},
+ /**
+ Returns a hash with all installed packages and version numbers
+ */
+ packageList: function(done) {
+ var repo = this,
+ path = Co.path.join(this.path, 'packages');
+ Co.fs.readdir_p(path, function(err, dirs) {
+ if (err) return done(err);
+ if (!dirs) return done(null, []);
+
+ var ret = {};
+ dirs.forEach(function(info) {
+ info = repo.infoForPath(Co.path.join(path, info));
+ var name = info[0], vers = info[1];
+ if (!ret[name]) ret[name] = [];
+ if (ret[name].indexOf(vers)<0) ret[name].push(vers);
+ });
+
+ done(null, ret);
+ });
+ },
+
// ..........................................................
// MANAGEMENT
//
View
2  packages/seed/lib/resource.js → lib/resource.js
@@ -40,7 +40,7 @@ var Co = require('./co');
var Resource = Co.extend({
init: function(path) {
- this.path = path;
+ this.path = Co.path.normalize(path);
},
state: 'start',
View
44 packages/seed/lib/sandbox.js → lib/sandbox.js
@@ -4,8 +4,6 @@
// License: Licened under MIT license (see __preamble__.js)
// ==========================================================================
-"use exports Sandbox";
-
var Co = require('./co');
var Sandbox ;
@@ -18,9 +16,9 @@ var Sandbox ;
for plugins.
To create a new Sandbox, you must pass in a Loader instance as well. Most
- of the time you can obtain a loader from the require.loader property.
+ of the time you can obtain a seed from the require.seed property.
- A new sandbox will inherit whatever modules are registered on the loader.
+ A new sandbox will inherit whatever modules are registered on the seed.
Modules will actually be reinstantiated however, when you require each of
them.
@@ -65,18 +63,18 @@ var Sandbox ;
@class
A sandbox defines a common space where modules can be instantiated and
- imported. Each loader comes with a default sandbox where modules are
+ imported. Each seed comes with a default sandbox where modules are
run though you can create additional sandboxes also if you wish.
Eventually this will form the basis of a secure system for giving
plugins limited access to your application code.
- To create a new sandbox just call the sandbox() method on a loader.
- This will create a sandbox attached to the named loader. Once you have
+ To create a new sandbox just call the sandbox() method on a seed.
+ This will create a sandbox attached to the named seed. Once you have
created a sandbox, you start running code by calling require().
*/
-Sandbox = function Sandbox(id, loader) {
+Sandbox = function Sandbox(id, seed) {
var allModules = {}, // instantiated module info.
usedModules = {}, // track exports that have been used already
modules = [], // names of instantiated modules
@@ -86,7 +84,7 @@ Sandbox = function Sandbox(id, loader) {
this.id = id ;
this.modules = modules;
- this.loader = loader ; // expose loader
+ this.seed = seed ;
// private clear method - causes all future requires to reload modules
function _clear() {
@@ -118,7 +116,13 @@ Sandbox = function Sandbox(id, loader) {
// this is the core require method. It will asynchronously fetch a
// package if needed. Invokes the callback
function _require(moduleId, packageId, curModuleId, curPackage, done) {
- var req, exports, moduleInfo, factory, idx, exp, seed, pkg;
+ var req, exports, moduleInfo, factory, idx, exp, pkg;
+
+ // special case - if you ask just for 'seed' or 'seed:index' then always
+ // return current seed object since it is equivalent.
+ if ((moduleId === 'seed') || (moduleId === 'seed:index')) {
+ return done(null, seed);
+ }
// substitute package if needed
if (packageId) {
@@ -128,10 +132,10 @@ Sandbox = function Sandbox(id, loader) {
}
// convert to canonical moduleId reference.
- loader.canonical(moduleId, curModuleId, curPackage, function(err, canonicalId) {
+ seed.canonical(moduleId, curModuleId, curPackage, function(err, canonicalId) {
if (!err && !canonicalId) err = "could not find module " + moduleId;
if (err) {
- Co.sys.debug('loader.canonical.error: ' + err);
+ Co.sys.debug('seed.canonical.error: ' + err);
return done(err, null);
}
@@ -153,7 +157,7 @@ Sandbox = function Sandbox(id, loader) {
var internalModuleId;
if (canonicalId.indexOf('::default:')===0) {
internalModuleId = canonicalId.slice(10);
- if (loader.NATIVE_MODULES.indexOf(internalModuleId)<0) {
+ if (seed.NATIVE_MODULES.indexOf(internalModuleId)<0) {
internalModuleId=null;
}
}
@@ -173,15 +177,15 @@ Sandbox = function Sandbox(id, loader) {
} else {
exports = {};
- // run module factory in loader
- loader.load(canonicalId, function(err, factory) {
+ // run module factory in seed
+ seed.load(sandbox, canonicalId, function(err, factory) {
if (!factory) err = "could not load function for " + moduleId;
if (err) return done(err);
allModules[canonicalId] = moduleInfo = {
id: moduleId,
exports: exports,
- pkg: pkg,
+ pkg: factory.pkg,
info: factory.info
};
@@ -194,11 +198,11 @@ Sandbox = function Sandbox(id, loader) {
return this;
};
- req.loader = loader ;
+ req.seed = seed ;
req.clear = _clear;
req.sandbox = this;
req.nodeRequire = nodeRequire;
-
+
factory.call(exports, req, exports, moduleInfo, factory.__filename, factory.__dirname);
// detect a circular require. if another module required this
@@ -267,8 +271,8 @@ Sandbox = function Sandbox(id, loader) {
};
-Sandbox.create = function(id, loader) {
- return new Sandbox(id, loader);
+Sandbox.create = function(id, seed) {
+ return new Sandbox(id, seed);
};
Sandbox.create.displayName = 'Sandbox.create';
View
142 packages/seed/lib/index.js → lib/seed.js
@@ -8,10 +8,9 @@
var Sandbox = require('./sandbox'),
Package = require('./package'),
- Repository = require('./repository'),
Co = require('./co'),
semver = require('./semver'),
- Seed, seed ;
+ Seed ;
// joins a packageId & a moduleId without alloc'ing new memory if possible
var joinPackageCache = {};
@@ -422,7 +421,7 @@ Seed = Co.extend({
Normally this is all invoked magically by the Sandbox require()
*/
- load: function(moduleId, curModuleId, curPackage, done) {
+ load: function(sandbox, moduleId, curModuleId, curPackage, done) {
if (!done && ('function' === typeof curModuleId)) {
done = curModuleId;
curModuleId = undefined;
@@ -463,7 +462,7 @@ Seed = Co.extend({
if (!pkg) {
return done("package not loaded for " + packageId);
} else {
- pkg.loadModule(moduleId, function(err, factory) {
+ pkg.loadModule(sandbox, moduleId, function(err, factory) {
if (factory) factory.pkg = pkg; // required for sandbox
return done(err, factory);
});
@@ -481,6 +480,114 @@ Seed = Co.extend({
},
// ..........................................................
+ // PACKAGES
+ //
+
+ /**
+ Returns an array of all installed packages on the system wrt a current
+ package. This will only include packages that are actually visible to
+ the calling package.
+ */
+ packageList: function(curPackage, done) {
+ if (done === undefined) {
+ done = curPackage;
+ curPackage = null;
+ }
+
+ var sources = this.sources.slice();
+ if (curPackage) sources.push(curPackage);
+
+ // map/reduce the package list
+ Co.map(sources, function(src, done) {
+ src.packageList(done);
+ })(function(err, packageLists) {
+ if (err) return done(err);
+ Co.reduce(packageLists, {}, function(ret, list, done) {
+ var key;
+
+ var iter = function(vers) {
+ if (ret[key].indexOf(vers)<0) ret[key].push(vers);
+ };
+
+ for(key in list) {
+ if (!list.hasOwnProperty(key)) continue;
+ if (!ret[key]) ret[key] = [];
+ list[key].forEach(iter);
+ }
+
+ done(null, ret);
+
+ })(done);
+ });
+ },
+
+ /**
+ Returns a list of package and version numbers that will actually be used
+ if you require() from the current package
+ */
+ preferredPackageList: function(curPackage, done) {
+ this.packageList(curPackage, function(err, list) {
+ if (err) return done(err);
+ var ret = {}, key;
+
+ // convert list into array so we can process in parallel
+ var iter = function(vers) {
+ if (curPackage.packageIsCompatible(key, vers)) {
+ if (!ret[key] || (semver.compare(ret[key][0],vers)<0)) {
+ ret[key]=[vers]; // array to match packageList
+ }
+ }
+ };
+
+ for(key in list) {
+ if (!list.hasOwnProperty(key)) continue;
+ list[key].forEach(iter);
+ }
+
+ done(null, ret);
+ });
+ },
+
+ /**
+ Opens a package with the given packageId. If you pass a version, opens
+ that specific version - otherwise uses the version for the current
+ package.
+ */
+ openPackage: function(packageId, vers, curPackage, done) {
+
+ // normalize. version and curPackage are optional
+ if (vers && ('string' !== typeof vers)) {
+ done = curPackage;
+ curPackage = vers;
+ vers = null;
+ }
+
+ if (done === undefined) {
+ done = curPackage;
+ curPackage = null;
+ }
+
+ // ok, let's find a matching package
+ var sources = this.sources.slice();
+ if (curPackage) sources.push(curPackage);
+ sources = sources.reverse();
+
+ var ret = null;
+ Co.find(sources, function(source, done) {
+ source.compatiblePackage(packageId, vers, function(err, pkg) {
+ // must be exact
+ if (pkg && vers && (pkg.version() !== vers)) pkg = null;
+ ret = pkg;
+ done(null, !!pkg);
+ });
+ })(function(err) {
+ if (err) return done(err);
+ ret.open(done);
+ });
+
+ },
+
+ // ..........................................................
// DEFAULT MODULE
//
@@ -546,7 +653,7 @@ Seed = Co.extend({
Co.fs.readFile(path, function(err, text) {
if (err) callback(err, null);
- var factory = seed.evaluate(text);
+ var factory = Seed.evaluate(text, path);
factory.info = { id: moduleId };
factory.__filename = path;
factory.__dirname = Co.path.dirname(path);
@@ -558,15 +665,6 @@ Seed = Co.extend({
});
-// ..........................................................
-// PUBLIC API
-//
-
-// export a default instance for use throughout the library
-seed = module.exports = new Seed('default');
-
-// also export the class itself so you can create a new instance if needed
-seed.Seed = Seed;
/**
Takes module text, wraps it in a factory function and evaluates it to
@@ -577,14 +675,26 @@ seed.Seed = Seed;
@param {String} moduleId the module id - used for debugging purposes
@returns {Function} factory function
*/
-seed.evaluate = function(moduleText) {
+Seed.evaluate = function(moduleText, path) {
var ret;
+
+ // if moduleText begins with #!, slice it off
+ if (moduleText.match(/^#!/)) {
+ moduleText = moduleText.slice(moduleText.indexOf('\n'));
+ }
MODULE_WRAPPER[1] = moduleText;
ret = MODULE_WRAPPER.join('');
- ret = eval(ret);
+ ret = process.compile(ret, path);
MODULE_WRAPPER[1] = null;
return ret;
};
+
+// ..........................................................
+// PUBLIC API
+//
+
+exports = module.exports = Seed;
+exports.Seed = Seed;
View
0  packages/seed/lib/semver.js → lib/semver.js
File renamed without changes
View
18 package.json
@@ -0,0 +1,18 @@
+{
+ "name": "seed",
+ "version": "0.1.1000",
+ "description": "Core package for handling seeds. The seed bootstrap used by node.js will actually look for the lib/index.js file here and load it",
+
+ // defines the locations for seed repositories on the local machine
+ // override with a local.json if you need to do something different
+ "seed": {
+ "repositories": ["~/.seeds", "/usr/local/seeds"],
+ "commands": {
+ "install": "seed:commands",
+ "remove": "seed:commands",
+ "list": "seed:commands",
+ "help": "seed:commands",
+ "update": "seed:commands"
+ }
+ }
+}
View
7 packages.json
@@ -1,7 +0,0 @@
-{
- "seed": {
- "1.0.0": {
- "path": "seed"
- }
- }
-}
View
4 packages/seed/fixtures/demo_repository/packages/foo-1.2.1/package.json
@@ -1,4 +0,0 @@
-{
- "name": "foo",
- "version": "1.2.1"
-}
View
4 packages/seed/fixtures/demo_repository/packages/foo-2.0.0/package.json
@@ -1,4 +0,0 @@
-{
- "name": "foo",
- "version": "2.0.0"
-}
View
5 packages/seed/package.json
@@ -1,5 +0,0 @@
-{
- "name": "seed",
- "version": "0.1.1000",
- "description": "Core package for handling seeds. The seed bootstrap used by node.js will actually look for the lib/index.js file here and load it"
-}
View
11 packages/seed/tests/co/path.js → tests/co/path.js
@@ -9,6 +9,9 @@ process.mixin(require('../common'));
var Co = require('co');
+// ..........................................................
+// EXISTS
+//
// make sure Co.path.exists() includes an 'err' param to callback.
sys.puts('exists ' + __filename);
@@ -23,3 +26,11 @@ Co.path.exists(path, function(err, exists) {
assert.equal(exists, false, 'should return false');
});
+
+// ..........................................................
+// NORMALIZE
+//
+
+// normalize should expand a ~
+var expected = Co.path.join(process.env.HOME, 'foo');
+assert.equal(Co.path.normalize('~/foo'), expected);
View
38 tests/commands/collectPluginInfo.js
@@ -0,0 +1,38 @@
+// ==========================================================================
+// Project: Seed - Flexible Package Manager
+// Copyright: ©2009-2010 Apple Inc. All rights reserved.
+// License: Licened under MIT license (see __preamble__.js)
+// ==========================================================================
+/*global process path sys assert libDir fixturesDir */
+
+process.mixin(require('../common'));
+
+var Seed = require('seed');
+var Repository = require('repository');
+
+var seed = new Seed();// use custom one to control what's loaded
+
+var demoRepoPath = path.join(fixturesDir, 'demo_repository');
+
+var repo = Repository.open(demoRepoPath);
+seed.register(require('index').sources[0]); // add seedPackage
+seed.register(repo);
+
+seed.require('seed:commands').collectPluginInfo(function(err, info) {
+ if (err) {
+ sys.puts(err);
+ throw err;
+ }
+
+ sys.puts(sys.inspect(info));
+});
+
+
+seed.require('seed:commands').commands(function(err, info) {
+ if (err) {
+ sys.puts(err);
+ throw err;
+ }
+
+ sys.puts(sys.inspect(info));
+});
View
0  packages/seed/tests/common.js → tests/common.js
File renamed without changes
View
11 packages/seed/tests/package/info.js → tests/package/info.js
@@ -10,10 +10,11 @@ process.mixin(require('../common'));
var Package = require('package');
var pkgDir = path.dirname(libDir);
-var pkg = new Package(pkgDir);
+Package.open(pkgDir, function(err, pkg) {
+ assert.equal(pkg.info('name'), 'seed', 'pkg.info(name)');
-assert.equal(pkg.info('name'), 'seed', 'pkg.info(name)');
+ assert.notEqual(pkg.info('description'), 'hello world');
+ pkg.info('description', 'hello world');
+ assert.equal(pkg.info('description'), 'hello world');
+});
-assert.notEqual(pkg.info('description'), 'hello world');
-pkg.info('description', 'hello world');
-assert.equal(pkg.info('description'), 'hello world');
View
0  packages/seed/tests/package/open.js → tests/package/open.js
File renamed without changes
View
0  packages/seed/tests/package/openGlobalConfig.js → tests/package/openGlobalConfig.js
File renamed without changes
View
73 tests/package/setup_teardown.js
@@ -0,0 +1,73 @@
+// ==========================================================================
+// Project: Seed - Flexible Package Manager
+// Copyright: ©2009-2010 Apple Inc. All rights reserved.
+// License: Licened under MIT license (see __preamble__.js)
+// ==========================================================================
+/*global process path sys assert libDir fixturesDir */
+
+process.mixin(require('../common'));
+
+var Package = require('package');
+var Co = require('co');
+var installingDir = path.join(fixturesDir, 'installing');
+
+var pkg = Package.open(installingDir);
+
+var cleanup = Co.parallel(['SETUP.out', 'TEARDOWN.out'], function(filename, done) {
+ filename = path.join(installingDir, filename);
+ Co.path.exists(filename, function(err, exists) {
+ if (err) return done(err);
+ if (exists) return Co.fs.rm(filename, done);
+ else done();
+ });
+});
+
+// first make sure the .out test files are gone
+Co.chain(
+
+ cleanup,
+
+ // open package
+ function(done) {
+ Package.open(installingDir, done);
+ },
+
+ // try setup
+ function(pkg, done) {
+ pkg.setup(function(err) {
+ if (err) throw err; // shouldn't happen
+
+ var filename = Co.path.join(installingDir, 'SETUP.out');
+ Co.path.exists(filename, function(err, exists) {
+ if (err) throw err;
+ assert.equal(exists, true);
+ Co.fs.readFile(filename, function(err, content) {
+ if (err) throw err;
+ assert.equal(content, 'setup '+installingDir); // should be cwd.
+ return done(null, pkg);
+ });
+ });
+ });
+ },
+
+ // try teardown
+ function(pkg, done) {
+ pkg.teardown(function(err) {
+ if (err) throw err; // shouldn't happen
+
+ var filename = Co.path.join(installingDir, 'TEARDOWN.out');
+ Co.path.exists(filename, function(err, exists) {
+ if (err) throw err;
+ assert.equal(exists, true);
+ Co.fs.readFile(filename, function(err, content) {
+ if (err) throw err;
+ assert.equal(content, 'teardown '+installingDir); // should be cwd.
+ return done();
+ });
+ });
+ });
+ },
+
+ // cleanup again
+ cleanup
+)(function(err) { assert.equal(err, null); });
View
0  packages/seed/tests/repository/compatiblePackage.js → tests/repository/compatiblePackage.js
File renamed without changes
View
0  packages/seed/tests/repository/open.js → tests/repository/open.js
File renamed without changes
View
4 packages/seed/tests/resource.js → tests/resource.js
@@ -18,7 +18,7 @@ var File = Co.extend(Resource, {
readContent: function(callback) {
if (this.readDelay) {
var file = this;
- setTimeout(function() { file._readContent(callback); }, this.readDelay);
+ setTimeout(function() { file._readContent(callback); }, file.readDelay);
} else this._readContent(callback);
},
@@ -26,7 +26,7 @@ var File = Co.extend(Resource, {
this.readCount++;
var repo = this;
- Co.fs.readFile(this.path)(function(err, content) {
+ Co.fs.readFile(repo.path, function(err, content) {
if (err) return callback(err);
repo.content = content;
callback(null); // ok!
View
4 packages/seed/tests/index/canonical.js → tests/seed/canonical.js
@@ -8,7 +8,7 @@
process.mixin(require('../common'));
-var seed = require('seed');
+var seed = require('index');
var basicPath = path.join(fixturesDir, 'basic');
// work in our own private version of seed
@@ -27,7 +27,7 @@ var basic = seed.register(basicPath); // lookup packages here
});
});
-seed.LOG_DEBUG = true;
+//seed.LOG_DEBUG = true;
// to be applied to tests
function doTest(moduleId, curModuleId, expectedPackageId, expectedModuleId) {
View
78 tests/seed/packageList.js
@@ -0,0 +1,78 @@
+// ==========================================================================
+// Project: Seed - Flexible Package Manager
+// Copyright: ©2009-2010 Apple Inc. All rights reserved.
+// License: Licened under MIT license (see __preamble__.js)
+// ==========================================================================
+/*global process path sys assert libDir fixturesDir */
+
+process.mixin(require('../common'));
+
+var Seed = require('seed');
+var Package = require('package');
+var Repository = require('repository');
+
+var seed = new Seed();// use custom one to control what's loaded
+var basicPath = path.join(fixturesDir, 'basic');
+var demoRepoPath = path.join(fixturesDir, 'demo_repository');
+
+
+var repo = Repository.open(demoRepoPath);
+seed.register(repo);
+
+Package.open(basicPath, function(err, pkg) {
+ if (err) throw err;
+
+ seed.packageList(pkg, function(err, list) {
+ if (err) throw err;
+ sys.debug(sys.inspect(list));
+
+ var expected = {
+ "bar": ["3.2.1"],
+ "foo": ["1.2.1", "2.0.0", "4.0.0"],
+ "basic": ["0.1.0"],
+ "foopkg": ["0.5.1"]
+ };
+
+ assert.deepEqual(list, expected);
+
+ seed.preferredPackageList(pkg, function(err, list) {
+ if (err) throw err;
+ sys.debug(sys.inspect(list));
+
+ var expected = {
+ "bar": ["3.2.1"],
+ "foo": ["4.0.0"],
+ "basic": ["0.1.0"],
+ "foopkg": ["0.5.1"]
+ };
+ assert.deepEqual(list, expected);
+
+ // test opening a specific package
+ seed.openPackage('foo', '1.2.1', pkg, function(err, fooPkg) {
+ if (err) throw err;
+ assert.ok(fooPkg);
+ assert.equal(fooPkg.version(), '1.2.1');
+ sys.debug(fooPkg.version());
+ });
+
+ // test opening any package
+ seed.openPackage('foo', pkg, function(err, fooPkg) {
+ if (err) throw err;
+ assert.ok(fooPkg);
+ assert.equal(fooPkg.version(), '4.0.0');
+ sys.debug(fooPkg.version());
+ });
+
+ // test opening package with no curPackage
+ seed.openPackage('foo', function(err, fooPkg) {
+ if (err) throw err;
+ assert.ok(fooPkg);
+ assert.equal(fooPkg.version(), '2.0.0');
+ sys.debug(fooPkg.version());
+ });
+
+ });
+
+ });
+});
+
View
0  packages/seed/tests/index/require.js → tests/seed/require.js
File renamed without changes
View
0  packages/seed/tests/semver.js → tests/semver.js
File renamed without changes
Please sign in to comment.
Something went wrong with that request. Please try again.