Merge branch 'devel' into fix-gems-benchmark

Conflicts:
	packages/constraint-solver/constraint-solver-tests.js
This commit is contained in:
David Greenspan
2014-11-14 21:37:15 -08:00
35 changed files with 1107 additions and 832 deletions

View File

@@ -3,6 +3,17 @@
* Spacebars: Allow curly braces to be escaped, with special
sequences `{{|` and `{{{|` to insert a literal `{{` or `{{{`.
* Corporate HTTP proxy support is now implemented using our websocket library's
new built-in implementation instead of a custom implementation. #2515
* Some packages are no longer released as part of the core release process:
amplify, backbone, bootstrap, d3, jquery-history, and jquery-layout.
* Rework how Meteor packages get loaded into the command-line tool
* Remove support for the undocumented earliestCompatibleVersion feature of the
package system.
* Upgraded dependencies:
- node: 0.10.33 (from 0.10.29)
- source-map-support: 0.2.8 (from 0.2.5)
@@ -15,6 +26,7 @@
- http-proxy: 1.6.0 (from a fork of 1.0.2)
- esprima: 1.2.2 (from an unreleased 1.1-era commit)
- openssl in mongo: 1.0.1j (from 1.0.1g)
- faye-websocket: 0.8.1 (from using websocket-driver instead)
- MongoDB: 2.4.12 (from 2.4.9)
## v1.0

View File

@@ -17,6 +17,7 @@ and removed with:
$ meteor remove <package_name>
Meteor Development Group maintains the following packages:
{{> pkg_appcache}}
{{> pkg_accounts_ui}}
{{> pkg_audit_argument_checks}}
{{> pkg_coffeescript}}

View File

@@ -0,0 +1,84 @@
<template name="pkg_appcache">
{{#markdown}}
## `appcache`
The `appcache` package stores the static parts of a Meteor application
(the client side Javascript, HTML, CSS, and images) in the browser's
[application cache](https://en.wikipedia.org/wiki/AppCache). To enable
caching simply add the `appcache` package to your project.
* Once a user has visited a Meteor application for the first time and
the application has been cached, on subsequent visits the web page
loads faster because the browser can load the application out of the
cache without contacting the server first.
* Hot code pushes are loaded by the browser in the background while the
app continues to run. Once the new code has been fully loaded the
browser is able to switch over to the new code quickly.
* The application cache allows the application to be loaded even when
the browser doesn't have an Internet connection, and so enables using
the app offline.
(Note however that the `appcache` package by itself doesn't make
*data* available offline: in an application loaded offline, a Meteor
Collection will appear to be empty in the client until the Internet
becomes available and the browser is able to establish a DDP
connection).
To turn AppCache off for specific browsers use:
Meteor.AppCache.config({
chrome: false,
firefox: false
});
The supported browsers that can be enabled or disabled include, but are
not limited to, `android`, `chrome`, `chromium`, `chromeMobileIOS`,
`firefox`, `ie`, `mobileSafari` and `safari`.
Browsers limit the amount of data they will put in the application
cache, which can vary due to factors such as how much disk space is
free. Unfortunately if your application goes over the limit rather
than disabling the application cache altogether and running the
application online, the browser will instead fail that particular
*update* of the cache, leaving your users running old code.
Thus it's best to keep the size of the cache below 5MB. The
`appcache` package will print a warning on the Meteor server console
if the total size of the resources being cached is over 5MB.
If you have files too large to fit in the cache you can disable
caching by URL prefix. For example,
Meteor.AppCache.config({onlineOnly: ['/online/']});
causes files in your `public/online` directory to not be cached, and
so they will only be available online. You can then move your large
files into that directory and refer to them at the new URL:
<img src="/online/bigimage.jpg">
If you'd prefer not to move your files, you can use the file names
themselves as the URL prefix:
Meteor.AppCache.config({
onlineOnly: [
'/bigimage.jpg',
'/largedata.json'
]
});
though keep in mind that since the exclusion is by prefix (this is a
limitation of the application cache manifest), excluding
`/largedata.json` will also exclude such URLs as
`/largedata.json.orig` and `/largedata.json/file1`.
For more information about how Meteor interacts with the application
cache, see the
[AppCache page](https://github.com/meteor/meteor/wiki/AppCache)
in the Meteor wiki.
{{/markdown}}
</template>

2
meteor
View File

@@ -1,6 +1,6 @@
#!/bin/bash
BUNDLE_VERSION=0.3.62
BUNDLE_VERSION=0.3.64 # 0.3.63 on the Windows branch
# OS Check. Put here because here is where we download the precompiled
# bundles that are arch specific.

View File

@@ -0,0 +1,738 @@
// "Benchmarks" here are just slow tests of the constraint solver.
// You can see roughly how long they take by looking at how long the
// test takes to run. Because they are slow, they don't run when you
// run tests unless you turn them on with an environment variable.
var runBenchmarks = !!process.env.CONSTRAINT_SOLVER_BENCHMARK;
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - sinatra", function (test) {
var r = new ConstraintSolver.PackagesResolver(getCatalogStub(sinatraGems));
var args = splitArgs({
'capistrano': '2.14.2',
'data-mapper': '1.2.0',
'dm-core': '1.2.0',
'dm-sqlite-adapter': '1.2.0',
'dm-timestamps': '1.2.0',
'haml': '3.1.7',
'sass': '3.2.1',
'shotgun': '0.9.0',
'sinatra': '1.3.5',
'sqlite3': '1.3.7'
});
r.resolve(args.dependencies, args.constraints);
});
// Add a few versions that are referenced by other versions but don't exist. We
// now require referenced versions to exist.
railsGems.push({name: "bcrypt", number: "3.0.0", dependencies: []});
railsGems.push({name: "mime-types", number: "1.16.0", dependencies: []});
railsGems.push({"name":"pyu-ruby-sasl","number":"0.3.1","platform":"ruby","dependencies":[]});
railsGems.push({"name":"backports","number":"3.0.0","platform":"ruby","dependencies":[]});
railsGems.push({"name":"diff-lcs","number":"1.1.0","platform":"ruby","dependencies":[]});
var railsCatalog = getCatalogStub(railsGems);
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - rails", function (test) {
var r = new ConstraintSolver.PackagesResolver(railsCatalog);
var args = splitArgs({
'rails': '4.0.4'
});
r.resolve(args.dependencies, args.constraints);
});
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - rails, gitlabhq", function (test) {
var r = new ConstraintSolver.PackagesResolver(railsCatalog);
var args = splitArgs({
'rails': '4.0.0',
'protected-attributes': null,
'rails-observers': null,
'actionpack-page-caching': null,
'actionpack-action-caching': null,
'default-value-for': '3.0.0',
'mysql2': null,
'devise': '3.0.4',
'devise-async': '0.8.0',
'omniauth': '1.1.3',
'omniauth-google-oauth2': null,
'omniauth-twitter': null,
'omniauth-github': null,
'gitlab-git': '5.7.1',
'gitlab-grack': '2.0.0',
'gitlab-omniauth-ldap': '1.0.4',
'gitlab-gollum-lib': '1.1.0',
'gitlab-linguist': '3.0.0',
'grape': '0.6.1',
'rack-cors': null,
'email-validator': '1.4.0',
'stamp': null,
'enumerize': null,
'kaminari': '0.15.1',
'haml-rails': null,
'carrierwave': null,
'fog': '1.3.1',
'six': null,
'seed-fu': null,
'redcarpet': '2.2.2',
'github-markup': null,
'asciidoctor': null,
'unicorn': '4.6.3',
'unicorn-worker-killer': null,
'state-machine': null,
'acts-as-taggable-on': null,
'slim': null,
'sinatra': null,
'sidekiq': null,
'httparty': null,
'colored': null,
'settingslogic': null,
'foreman': null,
'version-sorter': null,
'redis-rails': null,
'tinder': '1.9.2',
'hipchat': '0.14.0',
'gemnasium-gitlab-service': '0.2.1',
'slack-notifier': '0.2.0',
'd3-rails': '3.1.4',
'underscore-rails': '1.4.4',
'sanitize': null,
'rack-attack': null,
'ace-rails-ap': null,
'sass-rails': null,
'coffee-rails': null,
'uglifier': null,
'therubyracer': null,
'turbolinks': null,
'jquery-turbolinks': null,
'select2-rails': null,
'jquery-atwho-rails': '0.3.3',
'jquery-rails': '2.1.3',
'jquery-ui-rails': '2.0.2',
'modernizr': '2.6.2',
'raphael-rails': '2.1.2',
'bootstrap-sass': '3.0.0',
'font-awesome-rails': '3.2.0',
'gitlab-emoji': '0.0.1',
'gon': '5.0.0'
});
r.resolve(args.dependencies, args.constraints);
});
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - rails, gitlabhq, additions to the existing smaller solution", function (test) {
var r = new ConstraintSolver.PackagesResolver(railsCatalog);
var args = splitArgs({
'rails': '4.0.0',
'protected-attributes': null,
'rails-observers': null,
'actionpack-page-caching': null,
'actionpack-action-caching': null,
'default-value-for': '3.0.0',
'mysql2': null,
'devise': '3.0.4',
'devise-async': '0.8.0',
'omniauth': '1.1.3',
'omniauth-google-oauth2': null,
'omniauth-twitter': null,
'omniauth-github': null,
'gitlab-git': '5.7.1',
'gitlab-grack': '2.0.0',
'gitlab-omniauth-ldap': '1.0.4',
'gitlab-gollum-lib': '1.1.0',
'gitlab-linguist': '3.0.0',
'grape': '0.6.1',
'rack-cors': null,
'email-validator': '1.4.0',
'stamp': null,
'enumerize': null,
'kaminari': '0.15.1',
'haml-rails': null,
'carrierwave': null,
'fog': '1.3.1',
'six': null,
'seed-fu': null,
'redcarpet': '2.2.2',
'github-markup': null,
'asciidoctor': null,
'unicorn': '4.6.3',
'unicorn-worker-killer': null,
'state-machine': null,
'acts-as-taggable-on': null,
'slim': null,
'sinatra': null,
'sidekiq': null,
'httparty': null,
'colored': null,
'settingslogic': null,
'foreman': null,
'version-sorter': null,
'redis-rails': null,
'tinder': '1.9.2',
'hipchat': '0.14.0',
'gemnasium-gitlab-service': '0.2.1',
'slack-notifier': '0.2.0',
'd3-rails': '3.1.4',
'underscore-rails': '1.4.4',
'sanitize': null,
'rack-attack': null,
'ace-rails-ap': null,
'sass-rails': null,
'coffee-rails': null,
'uglifier': null,
'therubyracer': null,
'turbolinks': null,
'jquery-turbolinks': null,
'select2-rails': null,
'jquery-atwho-rails': '0.3.3',
'jquery-rails': '2.1.3',
'jquery-ui-rails': '2.0.2',
'modernizr': '2.6.2',
'raphael-rails': '2.1.2',
'bootstrap-sass': '3.0.0',
'font-awesome-rails': '3.2.0',
'gitlab-emoji': '0.0.1',
'gon': '5.0.0'
});
var previousSolution = {
"actionmailer": "4.0.0",
"actionpack": "4.0.0",
"activemodel": "4.0.0",
"activerecord": "4.0.0",
"activerecord-deprecated-finders": "1.0.3",
"activesupport": "4.0.0",
"arel": "4.0.2",
"asciidoctor": "0.1.4",
"bcrypt": "3.1.7",
"bcrypt-ruby": "3.1.5",
"builder": "3.1.4",
"carrierwave": "0.10.0",
"coffee-rails": "4.0.1",
"coffee-script": "2.2.0",
"coffee-script-source": "1.7.0",
"d3-rails": "3.1.4",
"default-value-for": "3.0.0",
"devise": "3.0.4",
"devise-async": "0.8.0",
"erubis": "2.7.0",
"execjs": "2.0.2",
"faraday": "0.9.0",
"github-markup": "1.1.0",
"haml": "4.0.5",
"haml-rails": "0.5.1",
"hashie": "2.0.3",
"hike": "1.2.3",
"httpauth": "0.2.1",
"i18n": "0.6.9",
"jquery-turbolinks": "2.0.2",
"json": "1.8.1",
"jwt": "0.1.10",
"kaminari": "0.15.1",
"mail": "2.5.4",
"mime-types": "1.25.1",
"minitest": "4.7.5",
"multi-json": "1.9.0",
"multipart-post": "2.0.0",
"oauth": "0.4.7",
"oauth2": "0.8.1",
"omniauth": "1.1.4",
"omniauth-github": "1.0.2",
"omniauth-google-oauth2": "0.2.2",
"omniauth-oauth": "1.0.1",
"omniauth-oauth2": "1.1.1",
"omniauth-twitter": "1.0.1",
"orm-adapter": "0.5.0",
"polyglot": "0.3.4",
"posix-spawn": "0.3.8",
"protected-attributes": "1.0.3",
"rack": "1.5.2",
"rack-test": "0.6.2",
"rails": "4.0.0",
"rails-observers": "0.1.2",
"railties": "4.0.0",
"rake": "10.1.1",
"redcarpet": "2.2.2",
"ref": "1.0.5",
"sass": "3.2.17",
"sass-rails": "4.0.2",
"seed-fu": "2.3.0",
"six": "0.2.0",
"sprockets": "2.11.0",
"sprockets-rails": "2.0.1",
"therubyracer": "0.12.1",
"thor": "0.19.1",
"thread-safe": "0.3.1",
"tilt": "1.4.1",
"treetop": "1.4.15",
"turbolinks": "2.2.0",
"tzinfo": "0.3.39",
"uglifier": "2.5.0",
"warden": "1.2.3"
};
var solution = r.resolve(args.dependencies, args.constraints, { previousSolution: previousSolution }).answer;
// check that root deps are the same
_.each(args.dependencies, function (dep) {
if (previousSolution[dep])
test.equal(solution[dep], previousSolution[dep], dep);
});
});
// Given a set of gems definitions returns a Catalog-like object
function getCatalogStub (gems) {
return {
getAllPackageNames: function () {
return _.uniq(_.pluck(gems, 'name'));
},
getPackage: function (name) {
return !!_.findWhere(gems, {name: name});
},
getSortedVersions: function (name) {
return _.chain(gems)
.filter(function (pv) { return pv.name === name; })
.pluck('number')
.map(function (version) {
var nv = exactVersion(version);
if (nv.length < version.length && version.split(".").length === 2)
return version;
return nv;
})
.filter(function (v) {
return PackageVersion.getValidServerVersion(v);
})
.sort(PackageVersion.compare)
.uniq(true)
.value();
},
getVersion: function (name, version) {
var gem = _.find(gems, function (pv) {
return pv.name === name && exactVersion(pv.number) === version;
});
var packageVersion = {
packageName: gem.name,
version: gem.number,
dependencies: {}
};
_.each(gem.dependencies, function (dep) {
var name = dep[0];
var constraint = dep[1];
packageVersion.dependencies[name] = {
constraint: constraint,
references: [{
"arch": "web"
}, {
"arch": "os" }]
};
});
return packageVersion;
}
};
}
// Naively converts ruby-gems style constraints string to either exact
// constraint or a regular constraint.
function convertConstraints (inp) {
var out = inp.split(",").map(function (s) {
return s.trim();
})
// remove the constraints we don't support
.filter(function (s) {
return !/</g.test(s) && !/!=/.test(s);
})
// convert 1.2.3.beta2 => 1.2.3
// and 0.2 => 0.2.0
.map(function (s) {
var x = s.split(" ");
return [x[0], exactVersion(x[1])].join(" ");
})
// convert '= 1.2.3' => '=1.2.3'
// '~>1.2.3' => '1.2.3'
// '>=1.2.3' => '1.2.3'
.map(function (s) {
if (s.indexOf(">= 0") === 0)
return "";
var x = s.split(' ');
if (x[0] === '~>' || x[0] === '>' || x[0] === '>=')
x[0] = '';
else if (x[0] === '=')
x[0] = '=';
else
throw new Error('unknown operator: ' + x[0]);
return x.join("");
});
return out;
}
function exactVersion (s) {
s = s.match(/\d+(\.\d+(\.\d+)?)?/)[0];
if (s.split('.').length < 3)
s += ".0";
if (s.split('.').length < 3)
s += ".0";
return s;
}
// XXX This test is supposed to reproduce issue #2968 by taking
// "forever" but it doesn't. Fix it (by remaking it).
/*runBenchmarks && Tinytest.add("issue 2968", function (test) {
var resolver = makeResolver([
["iron:router", '0.9.0', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'iron:layout': '0.3.0', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'ui': '1.0.0', }],
["meteor", '1.1.3+local', {'underscore': null, }],
["meteor", '1.0.0', {'underscore': null, }],
["meteor", '1.0.2', {'underscore': null, }],
["underscore", '1.0.1+local', {'meteor': null, }],
["underscore", '1.0.0', {'meteor': null, }],
["reactive-dict", '1.0.4+local', {'meteor': null, 'underscore': null, 'tracker': null, 'ejson': null, 'mongo': null, }],
["reactive-dict", '1.0.0', {'meteor': null, 'underscore': null, 'tracker': null, 'ejson': null, 'mongo': null, }],
["tracker", '1.0.3+local', {'meteor': null, }],
["tracker", '1.0.0', {'meteor': null, }],
["ejson", '1.0.4+local', {'meteor': null, 'json': null, 'underscore': null, 'base64': null, }],
["ejson", '1.0.0', {'meteor': null, 'json': null, 'underscore': null, 'base64': null, }],
["json", '1.0.1+local', {'meteor': null, }],
["base64", '1.0.1+local', {'meteor': null, }],
["mongo", '1.0.8+local', {'meteor': null, 'random': null, 'ejson': null, 'json': null, 'underscore': null, 'minimongo': null, 'logging': null, 'ddp': null, 'tracker': null, 'application-configuration': null, 'check': null, 'binary-heap': null, 'insecure': null, 'autopublish': null, 'disable-oplog': null, 'webapp': null, 'facts': null, 'callback-hook': null, }],
["random", '1.0.1+local', {'meteor': null, 'underscore': null, }],
["minimongo", '1.0.5+local', {'meteor': null, 'underscore': null, 'json': null, 'ejson': null, 'id-map': null, 'ordered-dict': null, 'tracker': null, 'random': null, 'geojson-utils': null, }],
["minimongo", '1.0.0', {'meteor': null, 'underscore': null, 'json': null, 'ejson': null, 'id-map': null, 'ordered-dict': null, 'tracker': null, 'random': null, 'geojson-utils': null, }],
["id-map", '1.0.1+local', {'meteor': null, 'underscore': null, 'json': null, 'ejson': null, }],
["ordered-dict", '1.0.1+local', {'meteor': null, 'underscore': null, }],
["geojson-utils", '1.0.1+local', {'meteor': null, }],
["id-map", '1.0.0', {'meteor': null, 'underscore': null, 'json': null, 'ejson': null, }],
["ordered-dict", '1.0.0', {'meteor': null, 'underscore': null, }],
["geojson-utils", '1.0.0', {'meteor': null, }],
["logging", '1.0.5+local', {'meteor': null, 'underscore': null, 'ejson': null, }],
["ddp", '1.0.11+local', {'meteor': null, 'check': null, 'random': null, 'ejson': null, 'json': null, 'underscore': null, 'tracker': null, 'logging': null, 'retry': null, 'webapp': null, 'routepolicy': null, 'audit-argument-checks': null, 'autopublish': null, 'facts': null, 'callback-hook': null, 'minimongo': null, 'reload': null, }],
["check", '1.0.2+local', {'meteor': null, 'underscore': null, 'ejson': null, }],
["retry", '1.0.1+local', {'meteor': null, 'underscore': null, 'random': null, }],
["webapp", '1.1.4+local', {'meteor': null, 'logging': null, 'underscore': null, 'routepolicy': null, 'boilerplate-generator': null, 'spacebars': null, 'htmljs': null, 'blaze': null, 'webapp-hashing': null, 'application-configuration': null, 'follower-livedata': null, }],
["webapp", '1.0.0', {'meteor': null, 'logging': null, 'underscore': null, 'routepolicy': null, 'boilerplate-generator': null, 'spacebars': null, 'htmljs': null, 'blaze': null, 'webapp-hashing': null, 'application-configuration': null, 'follower-livedata': null, }],
["routepolicy", '1.0.2+local', {'meteor': null, 'underscore': null, 'webapp': null, }],
["boilerplate-generator", '1.0.1+local', {'meteor': null, 'underscore': null, 'spacebars-compiler': null, 'spacebars': null, 'htmljs': null, 'ui': null, }],
["spacebars-compiler", '1.0.3+local', {'meteor': null, 'htmljs': null, 'html-tools': null, 'blaze-tools': null, 'underscore': null, 'minifiers': null, }],
["htmljs", '1.0.2+local', {'meteor': null, 'deps': null, }],
["deps", '1.0.5+local', {'meteor': null, 'tracker': null, }],
["deps", '1.0.0', {'meteor': null, 'tracker': null, }],
["html-tools", '1.0.2+local', {'meteor': null, 'htmljs': null, }],
["blaze-tools", '1.0.1+local', {'meteor': null, 'htmljs': null, 'underscore': null, }],
["minifiers", '1.1.2+local', {'meteor': null, 'underscore': null, }],
["spacebars", '1.0.3+local', {'meteor': null, 'htmljs': null, 'blaze': null, 'observe-sequence': null, 'templating': null, }],
["spacebars", '1.0.0', {'meteor': null, 'htmljs': null, 'blaze': null, 'observe-sequence': null, 'templating': null, }],
["blaze", '2.0.3+local', {'meteor': null, 'jquery': null, 'tracker': null, 'underscore': null, 'htmljs': null, 'observe-sequence': null, 'reactive-var': null, }],
["blaze", '2.0.0', {'meteor': null, 'jquery': null, 'tracker': null, 'underscore': null, 'htmljs': null, 'observe-sequence': null, 'reactive-var': null, }],
["blaze", '1.0.0', {'meteor': null, 'jquery': null, 'tracker': null, 'underscore': null, 'htmljs': null, 'observe-sequence': null, 'reactive-var': null, }],
["jquery", '1.0.1', {'meteor': null, }],
["jquery", '1.0.0', {'meteor': null, }],
["observe-sequence", '1.0.3+local', {'meteor': null, 'tracker': null, 'minimongo': null, 'underscore': null, 'random': null, }],
["reactive-var", '1.0.3+local', {'meteor': null, 'tracker': null, }],
["reactive-var", '1.0.0', {'meteor': null, 'tracker': null, }],
["templating", '1.0.9+local', {'meteor': null, 'underscore': null, 'blaze': null, }],
["templating", '1.0.0', {'meteor': null, 'underscore': null, 'blaze': null, }],
["ui", '1.0.4+local', {'meteor': null, 'blaze': null, }],
["ui", '1.0.0', {'meteor': null, 'blaze': null, }],
["webapp-hashing", '1.0.1+local', {'meteor': null, 'underscore': null, }],
["webapp-hashing", '1.0.0', {'meteor': null, 'underscore': null, }],
["application-configuration", '1.0.3+local', {'meteor': null, 'logging': null, 'underscore': null, 'ddp': null, 'ejson': null, 'follower-livedata': null, 'mongo': null, }],
["follower-livedata", '1.0.2+local', {'meteor': null, 'logging': null, 'underscore': null, 'ddp': null, 'ejson': null, }],
["audit-argument-checks", '1.0.1+local', {'meteor': null, }],
["autopublish", '1.0.1+local', {'meteor': null, }],
["facts", '1.0.2+local', {'meteor': null, 'underscore': null, 'autopublish': null, 'ddp': null, 'templating': null, 'mongo': null, }],
["callback-hook", '1.0.1+local', {'meteor': null, 'underscore': null, }],
["reload", '1.1.1+local', {'meteor': null, 'underscore': null, 'logging': null, 'json': null, }],
["binary-heap", '1.0.1+local', {'meteor': null, 'underscore': null, 'id-map': null, }],
["insecure", '1.0.1+local', {'meteor': null, }],
["disable-oplog", '1.0.1+local', {'meteor': null, }],
["iron:layout", '0.3.0', {'templating': '1.0.0', 'ui': '1.0.0', 'meteor': '1.0.0', 'underscore': '1.0.0', 'iron:core': '0.3.2', 'iron:dynamic-template': '0.3.0', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:core", '0.3.0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.0', 'cmather:iron-core': '0.2.0', }],
["cmather:iron-core", '0.1.0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.0', }],
["cmather:iron-core", '0.2.0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.0', }],
["iron:core", '0.3.1', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.0', 'cmather:iron-core': '0.2.0', }],
["iron:core", '0.3.2', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.0', 'cmather:iron-core': '0.2.0', }],
["iron:core", '0.3.3-rc0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.1-rc0', 'cmather:iron-core': '0.2.0', }],
["iron:core", '0.3.4-rc0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.1-rc0', 'cmather:iron-core': '0.2.0', }],
["iron:core", '0.3.4', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.1', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-pre0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.1-rc0', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-pre1', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-pre2', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-pre3', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-pre4', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-pre5', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0-rc.1', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:core", '1.0.0', {'meteor': null, 'underscore': '1.0.0', 'ejson': '1.0.2', 'cmather:iron-core': '0.2.0', }],
["iron:dynamic-template", '0.3.0', {'meteor': null, 'blaze': '1.0.0', 'underscore': '1.0.0', 'ui': '1.0.0', 'jquery': '1.0.0', 'deps': '1.0.0', 'templating': '1.0.0', 'iron:core': '0.3.2', }],
["iron:dynamic-template", '0.4.0-rc0', {'meteor': null, 'blaze': '2.0.0-rc0', 'underscore': '1.0.0', 'ui': '1.0.1-rc0', 'jquery': '1.0.0', 'deps': '1.0.2-rc1', 'templating': '1.0.5-rc0', 'iron:core': '0.3.2', }],
["iron:dynamic-template", '0.4.0-rc1', {'meteor': null, 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'ui': '1.0.1-rc0', 'jquery': '1.0.0', 'deps': '1.0.2-rc1', 'templating': '1.0.5-rc2', 'iron:core': '0.3.2', }],
["iron:dynamic-template", '0.4.0-rc2', {'meteor': null, 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'ui': '1.0.1-rc0', 'jquery': '1.0.0', 'deps': '1.0.2-rc1', 'templating': '1.0.5-rc2', 'iron:core': '0.3.3-rc0', }],
["iron:dynamic-template", '0.4.1-rc0', {'meteor': null, 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'ui': '1.0.1-rc0', 'jquery': '1.0.0', 'deps': '1.0.2-rc1', 'templating': '1.0.6-rc0', 'iron:core': '0.3.4-rc0', }],
["iron:dynamic-template", '0.4.1', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.1', 'jquery': '1.0.0', 'deps': '1.0.2', 'templating': '1.0.5', 'iron:core': '0.3.4', }],
["iron:dynamic-template", '1.0.0-pre0', {'meteor': null, 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'ui': '1.0.1-rc0', 'jquery': '1.0.0', 'tracker': '1.0.2-rc1', 'reactive-var': '1.0.1-rc0', 'templating': '1.0.6-rc0', 'iron:core': '1.0.0-pre0', }],
["iron:dynamic-template", '1.0.0-pre1', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'iron:core': '1.0.0-pre1', }],
["iron:dynamic-template", '1.0.0-pre2', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'iron:core': '1.0.0-pre2', }],
["iron:dynamic-template", '1.0.0-pre3', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'iron:core': '1.0.0-pre3', }],
["iron:dynamic-template", '1.0.0-pre4', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'random': '1.0.0', 'iron:core': '1.0.0-pre4', }],
["iron:dynamic-template", '1.0.0-pre5', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'random': '1.0.0', 'iron:core': '1.0.0-pre5', }],
["iron:dynamic-template", '1.0.0-rc.1', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'random': '1.0.0', 'iron:core': '1.0.0-rc.1', }],
["iron:dynamic-template", '1.0.0', {'meteor': null, 'blaze': '2.0.0', 'underscore': '1.0.0', 'ui': '1.0.2', 'jquery': '1.0.0', 'tracker': '1.0.2', 'reactive-var': '1.0.1', 'templating': '1.0.6', 'random': '1.0.0', 'iron:core': '1.0.0', }],
["cmather:blaze-layout", '0.0.1', {'meteor': null, }],
["cmather:blaze-layout", '0.1.0', {'meteor': null, }],
["cmather:blaze-layout", '0.2.0', {'meteor': null, }],
["cmather:blaze-layout", '0.2.1', {'meteor': null, }],
["cmather:blaze-layout", '0.2.2', {'meteor': null, }],
["cmather:blaze-layout", '0.2.3', {'meteor': null, }],
["cmather:blaze-layout", '0.2.4', {'meteor': null, }],
["cmather:blaze-layout", '0.2.5', {'meteor': null, 'templating': '1.0.0', 'ui': '1.0.0', 'reactive-dict': '1.0.0', 'underscore': '1.0.0' }], // We removed iron-router from here!
["cmather:iron-layout", '0.1.0', {'meteor': null, }],
["cmather:iron-layout", '0.1.1', {'meteor': null, }],
["cmather:iron-layout", '0.1.2', {'meteor': null, }],
["cmather:iron-layout", '0.2.0', {'templating': '1.0.0', 'ui': '1.0.0', 'meteor': '1.0.0', 'underscore': '1.0.0', 'cmather:iron-core': '0.2.0', 'cmather:iron-dynamic-template': '0.2.1', 'cmather:blaze-layout': '0.2.5', }],
["cmather:iron-dynamic-template", '0.1.0', {'meteor': null, }],
["cmather:iron-dynamic-template", '0.2.0', {'meteor': null, }],
["cmather:iron-dynamic-template", '0.2.1', {'meteor': null, 'blaze': '1.0.0', 'underscore': '1.0.0', 'ui': '1.0.0', 'spacebars': '1.0.0', 'jquery': '1.0.0', 'deps': '1.0.0', 'templating': '1.0.0', 'cmather:iron-core': '0.2.0', }],
["iron:layout", '0.4.0-rc0', {'meteor': null, 'templating': '1.0.5-rc0', 'blaze': '2.0.0-rc0', 'underscore': '1.0.0', 'iron:core': '0.3.2', 'iron:dynamic-template': '0.4.0-rc0', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '0.4.0-rc1', {'meteor': null, 'templating': '1.0.5-rc2', 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'iron:core': '0.3.2', 'iron:dynamic-template': '0.4.0-rc1', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '0.4.0-rc2', {'meteor': null, 'templating': '1.0.5-rc2', 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'iron:core': '0.3.3-rc0', 'iron:dynamic-template': '0.4.0-rc2', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '0.4.1-rc0', {'meteor': null, 'templating': '1.0.6-rc0', 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'iron:core': '0.3.4-rc0', 'iron:dynamic-template': '0.4.1-rc0', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '0.4.1', {'meteor': null, 'templating': '1.0.5', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '0.3.4', 'iron:dynamic-template': '0.4.1', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-pre0', {'meteor': null, 'templating': '1.0.6-rc0', 'blaze': '2.0.0-rc1', 'underscore': '1.0.0', 'iron:core': '1.0.0-pre0', 'iron:dynamic-template': '1.0.0-pre0', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-pre1', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0-pre1', 'iron:dynamic-template': '1.0.0-pre1', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-pre2', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0-pre2', 'iron:dynamic-template': '1.0.0-pre2', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-pre3', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0-pre3', 'iron:dynamic-template': '1.0.0-pre3', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-pre4', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0-pre4', 'iron:dynamic-template': '1.0.0-pre4', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-pre5', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0-pre5', 'iron:dynamic-template': '1.0.0-pre5', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0-rc.1', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0-rc.1', 'iron:dynamic-template': '1.0.0-rc.1', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["iron:layout", '1.0.0', {'meteor': null, 'templating': '1.0.6', 'blaze': '2.0.0', 'underscore': '1.0.0', 'iron:core': '1.0.0', 'iron:dynamic-template': '1.0.0', 'cmather:blaze-layout': '0.2.5', 'cmather:iron-layout': '0.2.0', }],
["cmather:iron-router", '0.5.3', {'meteor': null, }],
["cmather:iron-router", '0.5.4', {'meteor': null, }],
["cmather:iron-router", '0.6.0', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'templating': '1.0.0', 'handlebars': '1.0.0', 'jquery': '1.0.0', }],
["handlebars", '1.0.1+local', {'meteor': null, }],
["cmather:iron-router", '0.6.1', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'templating': '1.0.0', 'handlebars': '1.0.0', 'jquery': '1.0.0', }],
["cmather:iron-router", '0.6.2', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'templating': '1.0.0', 'handlebars': '1.0.0', 'jquery': '1.0.0', }],
["cmather:iron-router", '0.6.3', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'templating': '1.0.0', 'handlebars': '1.0.0', 'jquery': '1.0.0', }],
["cmather:iron-router", '0.6.4', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'templating': '1.0.0', 'handlebars': '1.0.0', 'jquery': '1.0.0', }],
["cmather:iron-router", '0.7.0', {'meteor': null, }],
["cmather:iron-router", '0.7.1', {'meteor': null, }],
["cmather:iron-router", '0.8.0', {'meteor': null, }],
["cmather:iron-router", '0.8.1', {'meteor': null, }],
["cmather:iron-router", '0.8.2', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'cmather:iron-layout': '0.2.0', 'webapp': '1.0.0', 'jquery': '1.0.0', 'ui': '1.0.0', }],
["iron:router", '0.9.1', {'meteor': null, 'reactive-dict': '1.0.0', 'deps': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'webapp': '1.0.0', 'iron:layout': '0.3.0', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'ui': '1.0.0', }],
["iron:router", '0.9.2-rc0', {'meteor': null, 'reactive-dict': '1.0.1-rc0', 'deps': '1.0.2-rc1', 'underscore': '1.0.0', 'ejson': '1.0.1-rc0', 'webapp': '1.0.3-rc0', 'iron:layout': '0.4.0-rc0', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'blaze': '2.0.0-rc0', }],
["iron:router", '0.9.2-rc2', {'meteor': null, 'reactive-dict': '1.0.1-rc1', 'deps': '1.0.2-rc1', 'underscore': '1.0.0', 'ejson': '1.0.1-rc0', 'webapp': '1.0.3-rc0', 'iron:layout': '0.4.0-rc2', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'blaze': '2.0.0-rc1', }],
["iron:router", '0.9.3-rc0', {'meteor': null, 'reactive-dict': '1.0.1-rc1', 'deps': '1.0.2-rc1', 'underscore': '1.0.0', 'ejson': '1.0.1-rc0', 'webapp': '1.1.0-rc1', 'iron:layout': '0.4.1-rc0', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'blaze': '2.0.0-rc1', }],
["iron:router", '0.9.3', {'meteor': null, 'reactive-dict': '1.0.1', 'deps': '1.0.2', 'underscore': '1.0.0', 'ejson': '1.0.1', 'webapp': '1.0.3', 'iron:layout': '0.4.1', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'blaze': '2.0.0', }],
["iron:router", '0.9.4', {'meteor': null, 'reactive-dict': '1.0.1', 'deps': '1.0.2', 'underscore': '1.0.0', 'ejson': '1.0.1', 'webapp': '1.0.3', 'iron:layout': '0.4.1', 'cmather:iron-router': '0.8.2', 'jquery': '1.0.0', 'blaze': '2.0.0', }],
["iron:router", '1.0.0-pre0', {'underscore': '1.0.0', 'webapp': '1.1.0-rc1', 'ui': '1.0.1-rc0', 'templating': '1.0.6-rc0', 'meteor': '1.1.0-rc0', 'iron:core': '1.0.0-pre0', 'iron:layout': '1.0.0-pre0', 'iron:middleware-stack': '1.0.0-pre0', 'iron:url': '1.0.0-pre0', 'iron:location': '1.0.0-pre0', 'iron:controller': '1.0.0-pre0', 'deps': '1.0.2-rc1', }],
["iron:middleware-stack", '1.0.0-pre0', {'meteor': null, 'iron:core': '1.0.0-pre0', 'iron:url': '1.0.0-pre0', }],
["iron:url", '1.0.0-pre0', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre0', }],
["iron:url", '1.0.0-pre1', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre1', }],
["iron:url", '1.0.0-pre2', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre2', }],
["iron:url", '1.0.0-pre3', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre3', }],
["iron:url", '1.0.0-pre4', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre4', }],
["iron:url", '1.0.0-pre5', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre5', }],
["iron:url", '1.0.0-rc.1', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-rc.1', }],
["iron:url", '1.0.0', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0', }],
["iron:middleware-stack", '1.0.0-pre1', {'meteor': null, 'iron:core': '1.0.0-pre1', 'iron:url': '1.0.0-pre1', }],
["iron:middleware-stack", '1.0.0-pre2', {'meteor': null, 'iron:core': '1.0.0-pre2', 'iron:url': '1.0.0-pre2', }],
["iron:middleware-stack", '1.0.0-pre3', {'meteor': null, 'iron:core': '1.0.0-pre3', 'iron:url': '1.0.0-pre3', }],
["iron:middleware-stack", '1.0.0-pre4', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre4', 'iron:url': '1.0.0-pre4', }],
["iron:middleware-stack", '1.0.0-pre5', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-pre5', 'iron:url': '1.0.0-pre5', }],
["iron:middleware-stack", '1.0.0-rc.1', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0-rc.1', 'iron:url': '1.0.0-rc.1', }],
["iron:middleware-stack", '1.0.0', {'meteor': null, 'underscore': '1.0.0', 'iron:core': '1.0.0', 'iron:url': '1.0.0', }],
["iron:location", '1.0.0-pre0', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2-rc1', 'jquery': '1.0.0', 'iron:core': '1.0.0-pre0', 'iron:url': '1.0.0-pre0', }],
["iron:location", '1.0.0-pre1', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0-pre1', 'iron:url': '1.0.0-pre1', }],
["iron:location", '1.0.0-pre2', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0-pre2', 'iron:url': '1.0.0-pre2', }],
["iron:location", '1.0.0-pre3', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0-pre3', 'iron:url': '1.0.0-pre3', }],
["iron:location", '1.0.0-pre4', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0-pre4', 'iron:url': '1.0.0-pre4', }],
["iron:location", '1.0.0-pre5', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0-pre5', 'iron:url': '1.0.0-pre5', 'appcache': '1.0.0-cordova1', }],
["appcache", '1.0.2+local', {'meteor': null, 'webapp': null, 'routepolicy': null, 'underscore': null, 'autoupdate': null, 'reload': null, }],
["autoupdate", '1.1.3+local', {'meteor': null, 'webapp': null, 'ddp': null, 'mongo': null, 'underscore': null, 'tracker': null, 'retry': null, 'reload': null, 'http': null, 'random': null, }],
["http", '1.0.8+local', {'meteor': null, 'underscore': null, 'url': null, }],
["url", '1.0.2+local', {'meteor': null, 'underscore': null, }],
["iron:location", '1.0.0-rc.1', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0-rc.1', 'iron:url': '1.0.0-rc.1', 'appcache': '1.0.0-cordova1', }],
["iron:location", '1.0.0', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'jquery': '1.0.0', 'iron:core': '1.0.0', 'iron:url': '1.0.0', 'appcache': '1.0.0-cordova1', }],
["iron:controller", '1.0.0-pre0', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2-rc1', 'reactive-dict': '1.0.1-rc1', 'iron:core': '1.0.0-pre0', 'iron:layout': '1.0.0-pre0', 'iron:dynamic-template': '1.0.0-pre0', }],
["iron:controller", '1.0.0-pre1', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'iron:core': '1.0.0-pre1', 'iron:layout': '1.0.0-pre1', 'iron:dynamic-template': '1.0.0-pre1', }],
["iron:controller", '1.0.0-pre2', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'iron:core': '1.0.0-pre2', 'iron:layout': '1.0.0-pre2', 'iron:dynamic-template': '1.0.0-pre2', }],
["iron:controller", '1.0.0-pre3', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'iron:core': '1.0.0-pre3', 'iron:layout': '1.0.0-pre3', 'iron:dynamic-template': '1.0.0-pre3', }],
["iron:controller", '1.0.0-pre4', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'templating': '1.0.6', 'iron:core': '1.0.0-pre4', 'iron:layout': '1.0.0-pre4', 'iron:dynamic-template': '1.0.0-pre4', }],
["iron:controller", '1.0.0-pre5', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'templating': '1.0.6', 'iron:core': '1.0.0-pre5', 'iron:layout': '1.0.0-pre5', 'iron:dynamic-template': '1.0.0-pre5', }],
["iron:controller", '1.0.0-rc.1', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'templating': '1.0.6', 'iron:core': '1.0.0-rc.1', 'iron:layout': '1.0.0-rc.1', 'iron:dynamic-template': '1.0.0-rc.1', }],
["iron:controller", '1.0.0', {'meteor': null, 'underscore': '1.0.0', 'tracker': '1.0.2', 'reactive-dict': '1.0.2', 'templating': '1.0.6', 'iron:core': '1.0.0', 'iron:layout': '1.0.0', 'iron:dynamic-template': '1.0.0', }],
["iron:router", '1.0.0-pre1', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'meteor': '1.1.0', 'iron:core': '1.0.0-pre1', 'iron:layout': '1.0.0-pre1', 'iron:middleware-stack': '1.0.0-pre1', 'iron:url': '1.0.0-pre1', 'iron:location': '1.0.0-pre1', 'iron:controller': '1.0.0-pre1', 'deps': '1.0.3', }],
["iron:router", '1.0.0-pre2', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'meteor': '1.1.0', 'iron:core': '1.0.0-pre2', 'iron:layout': '1.0.0-pre2', 'iron:middleware-stack': '1.0.0-pre2', 'iron:url': '1.0.0-pre2', 'iron:location': '1.0.0-pre2', 'iron:controller': '1.0.0-pre2', 'deps': '1.0.3', }],
["iron:router", '1.0.0-pre3', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'meteor': '1.1.0', 'iron:core': '1.0.0-pre3', 'iron:layout': '1.0.0-pre3', 'iron:middleware-stack': '1.0.0-pre3', 'iron:url': '1.0.0-pre3', 'iron:location': '1.0.0-pre3', 'iron:controller': '1.0.0-pre3', 'deps': '1.0.3', }],
["iron:router", '1.0.0-pre4', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'ejson': '1.0.2', 'meteor': '1.1.0', 'iron:core': '1.0.0-pre4', 'iron:layout': '1.0.0-pre4', 'iron:middleware-stack': '1.0.0-pre4', 'iron:url': '1.0.0-pre4', 'iron:location': '1.0.0-pre4', 'iron:controller': '1.0.0-pre4', 'deps': '1.0.3', }],
["iron:router", '1.0.0-pre5', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'ejson': '1.0.2', 'meteor': '1.1.0', 'iron:core': '1.0.0-pre5', 'iron:layout': '1.0.0-pre5', 'iron:middleware-stack': '1.0.0-pre5', 'iron:url': '1.0.0-pre5', 'iron:location': '1.0.0-pre5', 'iron:controller': '1.0.0-pre5', 'deps': '1.0.3', }],
["iron:router", '1.0.0-rc.0', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'ejson': '1.0.2', 'meteor': '1.1.0', 'iron:core': '1.0.0-pre5', 'iron:layout': '1.0.0-pre5', 'iron:middleware-stack': '1.0.0-pre5', 'iron:url': '1.0.0-pre5', 'iron:location': '1.0.0-pre5', 'iron:controller': '1.0.0-pre5', 'deps': '1.0.3', }],
["iron:router", '1.0.0-rc.1', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'ejson': '1.0.2', 'meteor': '1.1.0', 'iron:core': '1.0.0-rc.1', 'iron:layout': '1.0.0-rc.1', 'iron:middleware-stack': '1.0.0-rc.1', 'iron:url': '1.0.0-rc.1', 'iron:location': '1.0.0-rc.1', 'iron:controller': '1.0.0-rc.1', 'deps': '1.0.3', }],
["iron:router", '1.0.0', {'underscore': '1.0.0', 'webapp': '1.1.1', 'ui': '1.0.2', 'templating': '1.0.6', 'ejson': '1.0.2', 'meteor': '1.1.0', 'iron:core': '1.0.0', 'iron:layout': '1.0.0', 'iron:middleware-stack': '1.0.0', 'iron:url': '1.0.0', 'iron:location': '1.0.0', 'iron:controller': '1.0.0', 'deps': '1.0.3', }],
["matb33:collection-hooks", '0.7.3', {'meteor': '1.0.0', 'underscore': '1.0.0', 'ejson': '1.0.0', 'mongo-livedata': '1.0.0', 'minimongo': '1.0.0', 'deps': '1.0.0', 'accounts-base': '1.0.0', }],
["mongo-livedata", '1.0.6+local', {'meteor': null, 'mongo': null, }],
["mongo-livedata", '1.0.0', {'meteor': null, 'mongo': null, }],
["accounts-base", '1.1.2+local', {'meteor': null, 'underscore': null, 'check': null, 'random': null, 'ejson': null, 'callback-hook': null, 'service-configuration': null, 'ddp': null, 'mongo': null, 'autopublish': null, 'oauth-encryption': null, 'localstorage': null, 'tracker': null, 'blaze': null, }],
["accounts-base", '1.0.0', {'meteor': null, 'underscore': null, 'check': null, 'random': null, 'ejson': null, 'callback-hook': null, 'service-configuration': null, 'ddp': null, 'mongo': null, 'autopublish': null, 'oauth-encryption': null, 'localstorage': null, 'tracker': null, 'blaze': null, }],
["service-configuration", '1.0.2+local', {'meteor': null, 'accounts-base': null, 'mongo': null, }],
["oauth-encryption", '1.0.1+local', {'meteor': null, 'npm-node-aes-gcm': '=0.1.3', 'underscore': null, }],
["npm-node-aes-gcm", '0.1.3', {'meteor': null, }],
["localstorage", '1.0.1+local', {'meteor': null, 'random': null, }],
["matb33:collection-hooks", '0.7.5', {'meteor': null, 'mongo': '1.0.4', 'tracker': '1.0.2', 'underscore': '1.0.0', 'ejson': '1.0.0', 'minimongo': '1.0.1', 'accounts-base': '1.0.0', }],
["matb33:collection-hooks", '0.7.6', {'meteor': null, 'mongo': '1.0.4', 'tracker': '1.0.2', 'underscore': '1.0.0', 'ejson': '1.0.1', 'minimongo': '1.0.2', 'accounts-base': '1.0.1', }],
["mizzao:timesync", '0.1.0', {'meteor': null, 'coffeescript': '1.0.0', 'deps': '1.0.0', }],
["coffeescript", '1.0.4+local', {'meteor': null, }],
["coffeescript", '1.0.0', {'meteor': null, }],
["mizzao:timesync", '0.1.1', {'meteor': null, 'coffeescript': '1.0.0', 'deps': '1.0.0', }],
["mizzao:timesync", '0.1.2', {'meteor': null, 'coffeescript': '1.0.0', 'deps': '1.0.0', }],
["mizzao:timesync", '0.1.3', {'meteor': null, 'coffeescript': '1.0.0', 'deps': '1.0.0', }],
["mizzao:timesync", '0.1.4', {'meteor': null, 'webapp': '1.0.0', 'deps': '1.0.0', 'http': '1.0.0', }],
["mizzao:timesync", '0.1.5', {'meteor': null, 'webapp': '1.0.0', 'deps': '1.0.0', 'http': '1.0.0', }],
["mizzao:timesync", '0.1.6', {'meteor': null, 'webapp': '1.0.0', 'deps': '1.0.0', 'http': '1.0.0', }],
["mizzao:timesync", '0.2.0', {'meteor': null, 'webapp': '1.0.0', 'deps': '1.0.0', 'http': '1.0.0', }],
["mizzao:timesync", '0.2.1', {'meteor': null, 'webapp': '1.0.0', 'deps': '1.0.0', 'http': '1.0.0', }],
["mizzao:timesync", '0.2.2', {'meteor': null, 'webapp': '1.0.0', 'deps': '1.0.0', 'http': '1.0.0', }],
["mrt:jquery-ui-sortable", '1.10.3', {'meteor': null, 'jquery': '1.0.0', }],
["mrt:moment", '1.7.0', {'meteor': null, }],
["mrt:moment", '2.2.1', {'meteor': null, }],
["mrt:moment", '2.5.1', {'meteor': null, }],
["mrt:moment", '2.6.0', {'meteor': null, }],
["mrt:moment", '2.8.1', {'meteor': null, }],
["skinnygeek1010:parse-form", '0.1.0', {'meteor': null, 'jquery': '1.0.0', }],
["skinnygeek1010:parse-form", '0.2.0', {'meteor': null, 'jquery': '1.0.0', }],
["skinnygeek1010:parse-form", '0.2.1', {'meteor': null, 'jquery': '1.0.0', }],
["splendido:accounts-templates-semantic-ui", '0.0.1', {'meteor': null, }],
["splendido:accounts-templates-semantic-ui", '0.0.2', {'meteor': null, }],
["splendido:accounts-templates-semantic-ui", '0.0.3', {'meteor': null, }],
["splendido:accounts-templates-semantic-ui", '0.0.4', {'meteor': null, }],
["splendido:accounts-templates-semantic-ui", '0.0.20', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.20', 'templating': '1.0.4', 'less': '1.0.5', }],
["accounts-password", '1.0.4+local', {'meteor': null, 'npm-bcrypt': '=0.7.7', 'accounts-base': null, 'srp': null, 'sha': null, 'email': null, 'random': null, 'check': null, 'underscore': null, 'ddp': null, }],
["npm-bcrypt", '0.7.7', {'meteor': null, }],
["srp", '1.0.1+local', {'meteor': null, 'random': null, 'check': null, 'sha': null, 'underscore': null, }],
["sha", '1.0.1+local', {'meteor': null, }],
["email", '1.0.4+local', {'meteor': null, 'underscore': null, 'application-configuration': null, }],
["splendido:accounts-templates-core", '0.0.1', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.2', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.3', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.4', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.5', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.6', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.7', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.8', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.9', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.10', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.11', {'meteor': null, }],
["splendido:accounts-templates-core", '0.0.20', {'meteor': null, 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'mrt:accounts-t9n': '0.0.13', 'iron:router': '0.9.1', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["mrt:accounts-t9n", '0.0.1', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', 'mrt:just-i18n': '0.3.0', }],
["mrt:just-i18n", '0.1.0', {'meteor': null, 'underscore': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.1.1', {'meteor': null, 'underscore': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.2.0', {'meteor': null, 'underscore': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.2.1', {'meteor': null, 'underscore': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.2.2', {'meteor': null, 'underscore': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.2.3', {'meteor': null, 'underscore': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.2.4', {'meteor': null, 'underscore': '1.0.0', 'ui': '1.0.0', 'deps': '1.0.0', }],
["mrt:just-i18n", '0.3.0', {'meteor': null, 'underscore': '1.0.0', 'ui': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.2', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', 'mrt:just-i18n': '0.3.0', }],
["mrt:accounts-t9n", '0.0.3', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.4', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.7', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.10', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.11', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.12', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["mrt:accounts-t9n", '0.0.13', {'meteor': null, 'coffeescript': '1.0.0', 'handlebars': '1.0.0', 'deps': '1.0.0', }],
["splendido:accounts-templates-core", '0.0.21', {'meteor': null, 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'mrt:accounts-t9n': '0.0.13', 'iron:router': '0.9.1', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.0.22', {'meteor': null, 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'mrt:accounts-t9n': '0.0.13', 'iron:router': '0.9.1', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.0.23', {'meteor': null, 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'mrt:accounts-t9n': '0.0.13', 'iron:router': '0.9.1', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.0.24', {'meteor': null, 'mrt:accounts-t9n': '0.0.13', 'iron:router': '0.9.1', 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.0.25', {'meteor': null, 'mrt:accounts-t9n': '0.0.13', 'iron:router': '0.9.1', 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.0.26', {'meteor': null, 'softwarerero:accounts-t9n': '0.0.17', 'iron:router': '0.9.3', 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["softwarerero:accounts-t9n", '0.0.17', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["softwarerero:accounts-t9n", '0.0.18', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["softwarerero:accounts-t9n", '0.0.19', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["softwarerero:accounts-t9n", '0.0.20', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["softwarerero:accounts-t9n", '1.0.0', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["softwarerero:accounts-t9n", '1.0.1', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["softwarerero:accounts-t9n", '1.0.2', {'meteor': null, 'coffeescript': '1.0.2', 'deps': '1.0.1', }],
["splendido:accounts-templates-core", '0.0.27', {'meteor': null, 'softwarerero:accounts-t9n': '0.0.17', 'iron:router': '0.9.3', 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.0.28', {'meteor': null, 'softwarerero:accounts-t9n': '0.0.17', 'iron:router': '0.9.3', 'check': '1.0.0', 'deps': '1.0.1', 'accounts-base': '1.0.0', 'underscore': '1.0.0', 'minimongo': '1.0.1', 'mongo-livedata': '1.0.3', 'sha': '1.0.0', 'templating': '1.0.4', }],
["splendido:accounts-templates-core", '0.9.0', {'meteor': null, 'check': '1.0.0', 'accounts-base': '1.0.1', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '0.0.20', 'blaze': '2.0.0', 'reactive-dict': '1.0.1', 'sha': '1.0.0', 'templating': '1.0.5', }],
["splendido:accounts-templates-core", '0.9.1', {'meteor': null, 'check': '1.0.0', 'accounts-base': '1.0.1', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '0.0.20', 'blaze': '2.0.0', 'reactive-dict': '1.0.1', 'sha': '1.0.0', 'templating': '1.0.5', }],
["splendido:accounts-templates-core", '0.9.2', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'softwarerero:accounts-t9n': '0.0.20', 'iron:router': '0.9.3', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.3', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '0.0.20', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.4', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '0.0.20', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.5', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.6', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.7', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.8', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.9', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.10', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.11', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.12', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.13', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.14', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.15', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.3', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.16-iron-v1.1', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '1.0.0-pre4', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.9.16', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.4', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.10.0', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.4', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["splendido:accounts-templates-core", '0.11.0', {'meteor': null, 'accounts-base': '1.1.0', 'check': '1.0.0', 'underscore': '1.0.0', 'iron:router': '0.9.4', 'softwarerero:accounts-t9n': '1.0.0', 'blaze': '2.0.0', 'reactive-dict': '1.0.2', 'sha': '1.0.0', 'templating': '1.0.6', }],
["less", '1.0.11+local', {'meteor': null, }],
["splendido:accounts-templates-semantic-ui", '0.0.21', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.21', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.24', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.24', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.25', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.25', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.26', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.26', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.27', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.27', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.28-1', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.28', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.28', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.28', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.29', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.28', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.0.30', {'meteor': null, 'service-configuration': '1.0.0', 'accounts-password': '1.0.0', 'accounts-base': '1.0.0', 'splendido:accounts-templates-core': '0.0.28', 'templating': '1.0.4', 'less': '1.0.5', }],
["splendido:accounts-templates-semantic-ui", '0.9.4', {'meteor': null, 'splendido:accounts-templates-core': '0.9.4', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.5', {'meteor': null, 'splendido:accounts-templates-core': '0.9.5', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.6', {'meteor': null, 'splendido:accounts-templates-core': '0.9.6', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.7', {'meteor': null, 'splendido:accounts-templates-core': '0.9.7', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.8', {'meteor': null, 'splendido:accounts-templates-core': '0.9.8', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.9', {'meteor': null, 'splendido:accounts-templates-core': '0.9.9', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.10', {'meteor': null, 'splendido:accounts-templates-core': '0.9.10', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.11', {'meteor': null, 'splendido:accounts-templates-core': '0.9.11', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.12', {'meteor': null, 'splendido:accounts-templates-core': '0.9.12', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.13', {'meteor': null, 'splendido:accounts-templates-core': '0.9.13', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.14', {'meteor': null, 'splendido:accounts-templates-core': '0.9.14', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.15', {'meteor': null, 'splendido:accounts-templates-core': '0.9.15', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.16-iron-v1.1', {'meteor': null, 'splendido:accounts-templates-core': '0.9.16-iron-v1.1', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.9.16', {'meteor': null, 'splendido:accounts-templates-core': '0.9.16', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.10.0', {'meteor': null, 'splendido:accounts-templates-core': '0.10.0', 'less': '1.0.8', 'templating': '1.0.6', }],
["splendido:accounts-templates-semantic-ui", '0.11.0', {'meteor': null, 'splendido:accounts-templates-core': '0.11.0', 'less': '1.0.8', 'templating': '1.0.6', }],
["u2622:persistent-session", '0.1.0', {'meteor': null, 'amplify': '1.0.0', 'session': '1.0.0', 'underscore': '1.0.0', }],
["amplify", '1.0.0', {'jquery': '1.0.0', 'meteor': '1.0.2', }],
["session", '1.0.4+local', {'meteor': null, 'underscore': null, 'reactive-dict': null, 'ejson': null, 'reload': null, }],
["session", '1.0.0', {'meteor': null, 'underscore': null, 'reactive-dict': null, 'ejson': null, 'reload': null, }],
["u2622:persistent-session", '0.1.1', {'meteor': null, 'amplify': '1.0.0', 'session': '1.0.0', 'underscore': '1.0.0', }],
["u2622:persistent-session", '0.1.2', {'meteor': null, 'amplify': '1.0.0', 'session': '1.0.0', 'underscore': '1.0.0', }],
["u2622:persistent-session", '0.1.3', {'meteor': null, 'jquery': '1.0.0', 'amplify': '1.0.0', 'session': '1.0.0', 'underscore': '1.0.0', }],
["u2622:persistent-session", '0.1.4', {'meteor': null, 'jquery': '1.0.0', 'amplify': '1.0.0', 'session': '1.0.0', 'underscore': '1.0.0', }],
["u2622:persistent-session", '0.2.0', {'meteor': null, 'jquery': '1.0.0', 'amplify': '1.0.0', 'session': '1.0.1', 'underscore': '1.0.0', }],
["u2622:persistent-session", '0.2.1', {'meteor': null, 'jquery': '1.0.0', 'amplify': '1.0.0', 'session': '1.0.1', 'underscore': '1.0.0', }],
["ctl", '1.0.2+local', {'meteor': null, 'underscore': null, 'ddp': null, 'mongo': null, 'ctl-helper': null, 'application-configuration': null, 'follower-livedata': null, }],
["ctl-helper", '1.0.4+local', {'meteor': null, 'logging': null, 'underscore': null, 'ddp': null, 'mongo': null, 'follower-livedata': null, 'application-configuration': null, }],
]);
testWithResolver(test, resolver, function(t) {
t({ "iron:router": null,
"matb33:collection-hooks": null,
"mizzao:timesync" : null,
"mrt:jquery-ui-sortable": null,
"mrt:moment": null,
"skinnygeek1010:parse-form": null,
"splendido:accounts-templates-semantic-ui": null,
"u2622:persistent-session": null,
"ctl": null },
{}, {_testing: false}); // use real cost function!
});
});*/

View File

@@ -1,3 +1,4 @@
var makeResolver = function (data) {
var Packages = new LocalCollection;
var Versions = new LocalCollection;
@@ -6,9 +7,6 @@ var makeResolver = function (data) {
_.each(data, function (versionDescription) {
var packageName = versionDescription.shift();
var version = versionDescription.shift();
var ecv = (typeof versionDescription[0] === "string"
? versionDescription.shift()
: PackageVersion.defaultECV(version));
var deps = versionDescription.shift();
if (!Packages.findOne({name: packageName})) {
@@ -22,13 +20,12 @@ var makeResolver = function (data) {
references: [
{ arch: "os" },
{ arch: "web.browser"},
{ arch: "web.cordova"},
{ arch: "web.cordova"}
]
};
});
Versions.insert({ packageName: packageName, version: version,
earliestCompatibleVersion: ecv,
dependencies: constructedDeps });
dependencies: constructedDeps });
Builds.insert({ packageName: packageName, version: version,
buildArchitectures: "os+web.cordova+web.browser" });
});
@@ -65,23 +62,31 @@ var defaultResolver = makeResolver([
["sparky-forms", "1.1.2", {"forms": "=1.0.1", "sparkle": "=2.1.1"}],
["sparky-forms", "1.0.0", {"awesome-dropdown": "=1.4.0"}],
["forms", "1.0.1", {"sparkle": "2.1.0", "jquery-widgets": "1.0.0"}],
["sparkle", "2.1.0", "2.1.0", {"jquery": "1.8.2"}],
["sparkle", "2.1.1", "2.1.0", {"jquery": "1.8.2"}],
["sparkle", "2.1.0", {"jquery": "1.8.2"}],
["sparkle", "2.1.1", {"jquery": "1.8.2"}],
["sparkle", "1.0.0"],
["awesome-dropdown", "1.4.0", {"dropdown": "=1.2.2"}],
["awesome-dropdown", "1.5.0", {"dropdown": "=1.2.2"}],
["dropdown", "1.2.2", {"jquery-widgets": "1.0.0"}],
["jquery-widgets", "1.0.0", {"jquery": "1.8.0", "sparkle": "2.1.1"}],
["jquery-widgets", "1.0.2", {"jquery": "1.8.0", "sparkle": "2.1.1"}],
["jquery", "1.8.0", "1.8.0"],
["jquery", "1.8.2", "1.8.0"]
["jquery", "1.8.0"],
["jquery", "1.8.2"]
]);
var splitArgs = function (deps) {
// Take a map of `{ dependency: constraint }`, where `dependency`
// is a package name string and `constraint` is a constraint string,
// and return an array of dependencies (package name strings)
// and an array of constraint objects.
//
// If a constraint is prefixed with 'w', the dependency is a weak
// dependency, so it will generate a constraint but not a dependency
// in the returned arrays.
splitArgs = function (deps) {
var dependencies = [], constraints = [];
_.each(deps, function (constr, dep) {
if (constr && constr[0] === 'w') {
if (constr && constr.charAt(0) === 'w') {
constr = constr.slice(1);
} else {
dependencies.push(dep);
@@ -136,6 +141,7 @@ Tinytest.add("constraint solver - simple exact + regular deps", function (test)
});
});
Tinytest.add("constraint solver - non-exact direct dependency", function (test) {
testWithResolver(test, defaultResolver, function (t) {
// sparky-forms 1.0.0 won't be chosen because it depends on a very old
@@ -319,389 +325,3 @@ Tinytest.add("constraint solver - no constraint dependency - transitive dep stil
{ _testing: true }).answer;
test.equal(versions.sparkle, "2.1.1");
});
var runBenchmarks = !!process.env.CONSTRAINT_SOLVER_BENCHMARK;
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - sinatra", function (test) {
var r = new ConstraintSolver.PackagesResolver(getCatalogStub(sinatraGems));
var args = splitArgs({
'capistrano': '2.14.2',
'data-mapper': '1.2.0',
'dm-core': '1.2.0',
'dm-sqlite-adapter': '1.2.0',
'dm-timestamps': '1.2.0',
'haml': '3.1.7',
'sass': '3.2.1',
'shotgun': '0.9.0',
'sinatra': '1.3.5',
'sqlite3': '1.3.7'
});
r.resolve(args.dependencies, args.constraints);
});
// Add a few versions that are referenced by other versions but don't exist. We
// now require referenced versions to exist.
railsGems.push({name: "bcrypt", number: "3.0.0", dependencies: []});
railsGems.push({name: "mime-types", number: "1.16.0", dependencies: []});
railsGems.push({"name":"pyu-ruby-sasl","number":"0.3.1","platform":"ruby","dependencies":[]});
railsGems.push({"name":"backports","number":"3.0.0","platform":"ruby","dependencies":[]});
railsGems.push({"name":"diff-lcs","number":"1.1.0","platform":"ruby","dependencies":[]});
var railsCatalog = getCatalogStub(railsGems);
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - rails", function (test) {
var r = new ConstraintSolver.PackagesResolver(railsCatalog);
var args = splitArgs({
'rails': '4.0.4'
});
r.resolve(args.dependencies, args.constraints);
});
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - rails, gitlabhq", function (test) {
var r = new ConstraintSolver.PackagesResolver(railsCatalog);
var args = splitArgs({
'rails': '4.0.0',
'protected-attributes': null,
'rails-observers': null,
'actionpack-page-caching': null,
'actionpack-action-caching': null,
'default-value-for': '3.0.0',
'mysql2': null,
'devise': '3.0.4',
'devise-async': '0.8.0',
'omniauth': '1.1.3',
'omniauth-google-oauth2': null,
'omniauth-twitter': null,
'omniauth-github': null,
'gitlab-git': '5.7.1',
'gitlab-grack': '2.0.0',
'gitlab-omniauth-ldap': '1.0.4',
'gitlab-gollum-lib': '1.1.0',
'gitlab-linguist': '3.0.0',
'grape': '0.6.1',
'rack-cors': null,
'email-validator': '1.4.0',
'stamp': null,
'enumerize': null,
'kaminari': '0.15.1',
'haml-rails': null,
'carrierwave': null,
'fog': '1.3.1',
'six': null,
'seed-fu': null,
'redcarpet': '2.2.2',
'github-markup': null,
'asciidoctor': null,
'unicorn': '4.6.3',
'unicorn-worker-killer': null,
'state-machine': null,
'acts-as-taggable-on': null,
'slim': null,
'sinatra': null,
'sidekiq': null,
'httparty': null,
'colored': null,
'settingslogic': null,
'foreman': null,
'version-sorter': null,
'redis-rails': null,
'tinder': '1.9.2',
'hipchat': '0.14.0',
'gemnasium-gitlab-service': '0.2.1',
'slack-notifier': '0.2.0',
'd3-rails': '3.1.4',
'underscore-rails': '1.4.4',
'sanitize': null,
'rack-attack': null,
'ace-rails-ap': null,
'sass-rails': null,
'coffee-rails': null,
'uglifier': null,
'therubyracer': null,
'turbolinks': null,
'jquery-turbolinks': null,
'select2-rails': null,
'jquery-atwho-rails': '0.3.3',
'jquery-rails': '2.1.3',
'jquery-ui-rails': '2.0.2',
'modernizr': '2.6.2',
'raphael-rails': '2.1.2',
'bootstrap-sass': '3.0.0',
'font-awesome-rails': '3.2.0',
'gitlab-emoji': '0.0.1',
'gon': '5.0.0'
});
r.resolve(args.dependencies, args.constraints);
});
runBenchmarks && Tinytest.add("constraint solver - benchmark on gems - rails, gitlabhq, additions to the existing smaller solution", function (test) {
var r = new ConstraintSolver.PackagesResolver(railsCatalog);
var args = splitArgs({
'rails': '4.0.0',
'protected-attributes': null,
'rails-observers': null,
'actionpack-page-caching': null,
'actionpack-action-caching': null,
'default-value-for': '3.0.0',
'mysql2': null,
'devise': '3.0.4',
'devise-async': '0.8.0',
'omniauth': '1.1.3',
'omniauth-google-oauth2': null,
'omniauth-twitter': null,
'omniauth-github': null,
'gitlab-git': '5.7.1',
'gitlab-grack': '2.0.0',
'gitlab-omniauth-ldap': '1.0.4',
'gitlab-gollum-lib': '1.1.0',
'gitlab-linguist': '3.0.0',
'grape': '0.6.1',
'rack-cors': null,
'email-validator': '1.4.0',
'stamp': null,
'enumerize': null,
'kaminari': '0.15.1',
'haml-rails': null,
'carrierwave': null,
'fog': '1.3.1',
'six': null,
'seed-fu': null,
'redcarpet': '2.2.2',
'github-markup': null,
'asciidoctor': null,
'unicorn': '4.6.3',
'unicorn-worker-killer': null,
'state-machine': null,
'acts-as-taggable-on': null,
'slim': null,
'sinatra': null,
'sidekiq': null,
'httparty': null,
'colored': null,
'settingslogic': null,
'foreman': null,
'version-sorter': null,
'redis-rails': null,
'tinder': '1.9.2',
'hipchat': '0.14.0',
'gemnasium-gitlab-service': '0.2.1',
'slack-notifier': '0.2.0',
'd3-rails': '3.1.4',
'underscore-rails': '1.4.4',
'sanitize': null,
'rack-attack': null,
'ace-rails-ap': null,
'sass-rails': null,
'coffee-rails': null,
'uglifier': null,
'therubyracer': null,
'turbolinks': null,
'jquery-turbolinks': null,
'select2-rails': null,
'jquery-atwho-rails': '0.3.3',
'jquery-rails': '2.1.3',
'jquery-ui-rails': '2.0.2',
'modernizr': '2.6.2',
'raphael-rails': '2.1.2',
'bootstrap-sass': '3.0.0',
'font-awesome-rails': '3.2.0',
'gitlab-emoji': '0.0.1',
'gon': '5.0.0'
});
var previousSolution = {
"actionmailer": "4.0.0",
"actionpack": "4.0.0",
"activemodel": "4.0.0",
"activerecord": "4.0.0",
"activerecord-deprecated-finders": "1.0.3",
"activesupport": "4.0.0",
"arel": "4.0.2",
"asciidoctor": "0.1.4",
"bcrypt": "3.1.7",
"bcrypt-ruby": "3.1.5",
"builder": "3.1.4",
"carrierwave": "0.10.0",
"coffee-rails": "4.0.1",
"coffee-script": "2.2.0",
"coffee-script-source": "1.7.0",
"d3-rails": "3.1.4",
"default-value-for": "3.0.0",
"devise": "3.0.4",
"devise-async": "0.8.0",
"erubis": "2.7.0",
"execjs": "2.0.2",
"faraday": "0.9.0",
"github-markup": "1.1.0",
"haml": "4.0.5",
"haml-rails": "0.5.1",
"hashie": "2.0.3",
"hike": "1.2.3",
"httpauth": "0.2.1",
"i18n": "0.6.9",
"jquery-turbolinks": "2.0.2",
"json": "1.8.1",
"jwt": "0.1.10",
"kaminari": "0.15.1",
"mail": "2.5.4",
"mime-types": "1.25.1",
"minitest": "4.7.5",
"multi-json": "1.9.0",
"multipart-post": "2.0.0",
"oauth": "0.4.7",
"oauth2": "0.8.1",
"omniauth": "1.1.4",
"omniauth-github": "1.0.2",
"omniauth-google-oauth2": "0.2.2",
"omniauth-oauth": "1.0.1",
"omniauth-oauth2": "1.1.1",
"omniauth-twitter": "1.0.1",
"orm-adapter": "0.5.0",
"polyglot": "0.3.4",
"posix-spawn": "0.3.8",
"protected-attributes": "1.0.3",
"rack": "1.5.2",
"rack-test": "0.6.2",
"rails": "4.0.0",
"rails-observers": "0.1.2",
"railties": "4.0.0",
"rake": "10.1.1",
"redcarpet": "2.2.2",
"ref": "1.0.5",
"sass": "3.2.17",
"sass-rails": "4.0.2",
"seed-fu": "2.3.0",
"six": "0.2.0",
"sprockets": "2.11.0",
"sprockets-rails": "2.0.1",
"therubyracer": "0.12.1",
"thor": "0.19.1",
"thread-safe": "0.3.1",
"tilt": "1.4.1",
"treetop": "1.4.15",
"turbolinks": "2.2.0",
"tzinfo": "0.3.39",
"uglifier": "2.5.0",
"warden": "1.2.3"
};
var solution = r.resolve(args.dependencies, args.constraints, { previousSolution: previousSolution }).answer;
// check that root deps are the same
_.each(args.dependencies, function (dep) {
if (previousSolution[dep])
test.equal(solution[dep], previousSolution[dep], dep);
});
});
// Given a set of gems definitions returns a Catalog-like object
function getCatalogStub (gems) {
return {
getAllPackageNames: function () {
return _.uniq(_.pluck(gems, 'name'));
},
getPackage: function (name) {
return !!_.findWhere(gems, {name: name});
},
getSortedVersions: function (name) {
return _.chain(gems)
.filter(function (pv) { return pv.name === name; })
.pluck('number')
.map(function (version) {
var nv = exactVersion(version);
if (nv.length < version.length && version.split(".").length === 2)
return version;
return nv;
})
.filter(function (v) {
return PackageVersion.getValidServerVersion(v);
})
.sort(PackageVersion.compare)
.uniq(true)
.value();
},
getVersion: function (name, version) {
var gem = _.find(gems, function (pv) {
return pv.name === name && exactVersion(pv.number) === version;
});
var ecv = function (version) {
// hard-coded, because lots of the constraints are > or >= which we
// don't support anymore. But constant ECV means that "compatible-with"
// is interpreted as >=.
return "0.0.0";
};
var packageVersion = {
packageName: gem.name,
version: gem.number,
earliestCompatibleVersion: PackageVersion.defaultECV(gem.number),
dependencies: {}
};
_.each(gem.dependencies, function (dep) {
var name = dep[0];
var constraints = dep[1];
packageVersion.dependencies[name] = {
constraint: constraints,
references: [{
"arch": "web"
}, {
"arch": "os" }]
};
});
return packageVersion;
}
};
}
// Naively converts ruby-gems style constraints string to either exact
// constraint or a regular constraint.
function convertConstraints (inp) {
var out = inp.split(",").map(function (s) {
return s.trim();
})
// remove the constraints we don't support
.filter(function (s) {
return !/</g.test(s) && !/!=/.test(s);
})
// convert 1.2.3.beta2 => 1.2.3
// and 0.2 => 0.2.0
.map(function (s) {
var x = s.split(" ");
return [x[0], exactVersion(x[1])].join(" ");
})
// convert '= 1.2.3' => '=1.2.3'
// '~>1.2.3' => '1.2.3'
// '>=1.2.3' => '1.2.3'
.map(function (s) {
if (s.indexOf(">= 0") === 0)
return "";
var x = s.split(' ');
if (x[0] === '~>' || x[0] === '>' || x[0] === '>=')
x[0] = '';
else if (x[0] === '=')
x[0] = '=';
else
throw new Error('unknown operator: ' + x[0]);
return x.join("");
});
return out;
}
function exactVersion (s) {
s = s.match(/\d+(\.\d+(\.\d+)?)?/)[0];
if (s.split('.').length < 3)
s += ".0";
if (s.split('.').length < 3)
s += ".0";
return s;
}

View File

@@ -1,4 +1,8 @@
// Copied from archinfo.matches() in tools/
//
// archMatches("os", "os") => true
// archMatches("web.cordova", "web") => true
// archMatches("web.cordova", "web.cordova") => true
var archMatches = function (arch, baseArch) {
return arch.substr(0, baseArch.length) === baseArch &&
(arch.length === baseArch.length ||
@@ -73,8 +77,7 @@ ConstraintSolver.PackagesResolver.prototype._loadPackageInfo = function (
_.each(allArchs, function (arch) {
var unitName = packageName + "#" + arch;
unibuilds[unitName] = new ConstraintSolver.UnitVersion(
unitName, version, versionDef.earliestCompatibleVersion);
unibuilds[unitName] = new ConstraintSolver.UnitVersion(unitName, version);
self.resolver.addUnitVersion(unibuilds[unitName]);
});
@@ -122,19 +125,6 @@ ConstraintSolver.PackagesResolver.prototype._loadPackageInfo = function (
});
});
});
// We need to be aware of the earliestCompatibleVersion values for any
// packages that are overridden by local packages, in order to evaluate
// 'compatible-with' constraints that name that version.
// (Some of the test fixtures don't bother to implement this method.)
if (self.catalog.getForgottenECVs) {
_.each(self.catalog.getForgottenECVs(packageName), function (ecv, version) {
_.each(allArchs, function (arch) {
var unitName = packageName + '#' + arch;
self.resolver.addExtraECV(unitName, version, ecv);
});
});
}
};
// dependencies - an array of string names of packages (not slices)
@@ -394,8 +384,7 @@ ConstraintSolver.PackagesResolver.prototype._getResolverOptions =
PackageVersion.versionMagnitude(uv.version) -
PackageVersion.versionMagnitude(prev.version);
var isCompatible =
prev.earliestCompatibleVersion === uv.earliestCompatibleVersion;
var isCompatible = prev.majorVersion === uv.majorVersion;
if (isRootDep[uv.name]) {
// root dependency
@@ -468,7 +457,7 @@ ConstraintSolver.PackagesResolver.prototype._getResolverOptions =
var earliestMatching = mori.first(alternatives);
var isCompatible =
prev.earliestCompatibleVersion === earliestMatching.earliestCompatibleVersion;
prev.majorVersion === earliestMatching.majorVersion;
if (! isCompatible) {
cost[VMAJOR]++;
return;

View File

@@ -127,7 +127,7 @@ ConstraintSolver.ConstraintsList.prototype.toString = function (options) {
strs.push(c.toString({removeUnibuild: options.removeUnibuild}));
});
strs.sort();
strs = _.uniq(strs);
return "<constraints list: " + strs.join(", ") + ">";
};

View File

@@ -21,6 +21,7 @@ Package.on_test(function (api) {
// data for big benchmarky tests
api.add_files('test-data.js', ['server']);
api.add_files('constraint-solver-tests.js', ['server']);
api.add_files('benchmark-tests.js', ['server']);
api.add_files('resolver-tests.js', ['server']);
api.use('underscore');
});

View File

@@ -13,16 +13,15 @@ Tinytest.add("constraint solver - resolver, get exact deps", function (test) {
// \ \-> D => E
// \-> \-> F
var resolver = new ConstraintSolver.Resolver();
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0", "1.0.0");
var B100 = new ConstraintSolver.UnitVersion("b", "1.0.0", "1.0.0");
var C100 = new ConstraintSolver.UnitVersion("c", "1.0.0", "1.0.0");
var D110 = new ConstraintSolver.UnitVersion("d", "1.1.0", "1.0.0");
var E100 = new ConstraintSolver.UnitVersion("e", "1.0.0", "1.0.0");
var F120 = new ConstraintSolver.UnitVersion("f", "1.2.0", "1.0.0");
// Ensure that the resolver knows that these versions exist and have ECV =
// 1.0.0.
var F100 = new ConstraintSolver.UnitVersion("f", "1.0.0", "1.0.0");
var F110 = new ConstraintSolver.UnitVersion("f", "1.1.0", "1.0.0");
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0");
var B100 = new ConstraintSolver.UnitVersion("b", "1.0.0");
var C100 = new ConstraintSolver.UnitVersion("c", "1.0.0");
var D110 = new ConstraintSolver.UnitVersion("d", "1.1.0");
var E100 = new ConstraintSolver.UnitVersion("e", "1.0.0");
var F120 = new ConstraintSolver.UnitVersion("f", "1.2.0");
// Ensure that the resolver knows that these versions exist.
var F100 = new ConstraintSolver.UnitVersion("f", "1.0.0");
var F110 = new ConstraintSolver.UnitVersion("f", "1.1.0");
resolver.addUnitVersion(A100);
resolver.addUnitVersion(B100);
@@ -61,12 +60,12 @@ Tinytest.add("constraint solver - resolver, get exact deps", function (test) {
Tinytest.add("constraint solver - resolver, cost function - pick latest", function (test) {
var resolver = new ConstraintSolver.Resolver();
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0", "1.0.0");
var A110 = new ConstraintSolver.UnitVersion("a", "1.1.0", "1.0.0");
var B100 = new ConstraintSolver.UnitVersion("b", "1.0.0", "1.0.0");
var C100 = new ConstraintSolver.UnitVersion("c", "1.0.0", "1.0.0");
var C110 = new ConstraintSolver.UnitVersion("c", "1.1.0", "1.0.0");
var C120 = new ConstraintSolver.UnitVersion("c", "1.2.0", "1.0.0");
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0");
var A110 = new ConstraintSolver.UnitVersion("a", "1.1.0");
var B100 = new ConstraintSolver.UnitVersion("b", "1.0.0");
var C100 = new ConstraintSolver.UnitVersion("c", "1.0.0");
var C110 = new ConstraintSolver.UnitVersion("c", "1.1.0");
var C120 = new ConstraintSolver.UnitVersion("c", "1.2.0");
resolver.addUnitVersion(A100);
resolver.addUnitVersion(A110);
@@ -108,11 +107,11 @@ Tinytest.add("constraint solver - resolver, cost function - pick latest", functi
Tinytest.add("constraint solver - resolver, cost function - avoid upgrades", function (test) {
var resolver = new ConstraintSolver.Resolver();
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0", "1.0.0");
var A110 = new ConstraintSolver.UnitVersion("a", "1.1.0", "1.0.0");
var B100 = new ConstraintSolver.UnitVersion("b", "1.0.0", "1.0.0");
var B110 = new ConstraintSolver.UnitVersion("b", "1.1.0", "1.0.0");
var C100 = new ConstraintSolver.UnitVersion("c", "1.0.0", "1.0.0");
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0");
var A110 = new ConstraintSolver.UnitVersion("a", "1.1.0");
var B100 = new ConstraintSolver.UnitVersion("b", "1.0.0");
var B110 = new ConstraintSolver.UnitVersion("b", "1.1.0");
var C100 = new ConstraintSolver.UnitVersion("c", "1.0.0");
resolver.addUnitVersion(A100);
resolver.addUnitVersion(A110);
@@ -148,8 +147,8 @@ Tinytest.add("constraint solver - resolver, cost function - avoid upgrades", fun
Tinytest.add("constraint solver - resolver, don't pick rcs", function (test) {
var resolver = new ConstraintSolver.Resolver();
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0", "1.0.0");
var A100rc1 = new ConstraintSolver.UnitVersion("a", "1.0.0-rc1", "1.0.0");
var A100 = new ConstraintSolver.UnitVersion("a", "1.0.0");
var A100rc1 = new ConstraintSolver.UnitVersion("a", "1.0.0-rc1");
resolver.addUnitVersion(A100rc1);
resolver.addUnitVersion(A100);

View File

@@ -26,16 +26,6 @@ ConstraintSolver.Resolver = function (options) {
// Refs to all constraints. Mapping String -> instance
self._constraints = {};
// Let's say that we that package P is available from source at version X.Y.Z.
// Then that's the only version that can actually be chosen by the resolver,
// and so it's the only version included as a UnitVersion. But let's say
// another unit depends on it with a 'compatible-with' dependency "@A.B.C". We
// need to be able to figure out the earliestCompatibleVersion of A.B.C, even
// though A.B.C is not a valid (selectable) UnitVersion. We store them here.
//
// Maps String unitName -> String version -> String earliestCompatibleVersion
self._extraECVs = {};
};
ConstraintSolver.Resolver.prototype.addUnitVersion = function (unitVersion) {
@@ -86,36 +76,6 @@ ConstraintSolver.Resolver.prototype.getConstraint =
new ConstraintSolver.Constraint(name, versionConstraint);
};
ConstraintSolver.Resolver.prototype.addExtraECV = function (
unitName, version, earliestCompatibleVersion) {
var self = this;
check(unitName, String);
check(version, String);
check(earliestCompatibleVersion, String);
if (!_.has(self._extraECVs, unitName)) {
self._extraECVs[unitName] = {};
}
self._extraECVs[unitName][version] = earliestCompatibleVersion;
};
ConstraintSolver.Resolver.prototype.getEarliestCompatibleVersion = function (
unitName, version) {
var self = this;
var uv = self.getUnitVersion(unitName, version);
if (uv) {
return uv.earliestCompatibleVersion;
}
if (!_.has(self._extraECVs, unitName)) {
return null;
}
if (!_.has(self._extraECVs[unitName], version)) {
return null;
}
return self._extraECVs[unitName][version];
};
// options: Object:
// - costFunction: function (state, options) - given a state evaluates its cost
// - estimateCostFunction: function (state) - given a state, evaluates the
@@ -300,12 +260,11 @@ ConstraintSolver.Resolver.prototype._stateNeighbors = function (
// UnitVersion
////////////////////////////////////////////////////////////////////////////////
ConstraintSolver.UnitVersion = function (name, unitVersion, ecv) {
ConstraintSolver.UnitVersion = function (name, unitVersion) {
var self = this;
check(name, String);
check(unitVersion, String);
check(ecv, String);
check(self, ConstraintSolver.UnitVersion);
self.name = name;
@@ -315,7 +274,7 @@ ConstraintSolver.UnitVersion = function (name, unitVersion, ecv) {
self.dependencies = [];
self.constraints = new ConstraintSolver.ConstraintsList();
// a string in a form of "1.2.0"
self.earliestCompatibleVersion = ecv;
self.majorVersion = PackageVersion.majorVersion(unitVersion);
};
_.extend(ConstraintSolver.UnitVersion.prototype, {
@@ -369,7 +328,6 @@ ConstraintSolver.Constraint = function (name, versionString) {
removeBuildIDs: true,
archesOK: true
}));
};
ConstraintSolver.Constraint.prototype.toString = function (options) {
@@ -437,19 +395,10 @@ ConstraintSolver.Constraint.prototype.isSatisfied = function (
if (PackageVersion.lessThan(candidateUV.version, currConstraint.version))
return false;
var myECV = resolver.getEarliestCompatibleVersion(
self.name, currConstraint.version);
// If the constraint is "@1.2.3" and 1.2.3 doesn't exist, then nothing can
// match. This is because we don't know the ECV (compatibility class) of
// 1.2.3!
if (!myECV)
return false;
// To be compatible, the two versions must have the same
// earliestCompatibleVersion. If the earliestCompatibleVersions haven't been
// overridden from their default, this means that the two versions have the
// same major version number.
return myECV === candidateUV.earliestCompatibleVersion;
// To be compatible, the two versions must have the same major version
// number.
return candidateUV.majorVersion ===
PackageVersion.majorVersion(currConstraint.version);
});
};

View File

@@ -1,21 +1,20 @@
{
"dependencies": {
"sockjs": {
"version": "0.3.9",
"faye-websocket": {
"version": "0.8.1",
"dependencies": {
"node-uuid": {
"version": "1.3.3"
},
"faye-websocket": {
"version": "0.7.2"
"websocket-driver": {
"version": "0.4.0"
}
}
},
"tunnel-agent": {
"version": "0.4.0"
},
"websocket-driver": {
"version": "0.3.6"
"sockjs": {
"version": "0.3.11",
"dependencies": {
"node-uuid": {
"version": "1.4.1"
}
}
}
}
}

View File

@@ -3,18 +3,17 @@ Package.describe({
version: '1.0.11'
});
// We use Faye's 'websocket-driver' for connections in server-to-server DDP,
// mostly because it's the same library used as a server in sockjs, and it's
// easiest to deal with a single websocket implementation. (Plus, its
// maintainer is easy to work with on pull requests.)
// We use 'faye-websocket' for connections in server-to-server DDP, mostly
// because it's the same library used as a server in sockjs, and it's easiest to
// deal with a single websocket implementation. (Plus, its maintainer is easy
// to work with on pull requests.)
//
// (By listing websocket-driver first, it's more likely that npm deduplication
// will prevent a second copy of websocket-driver from being installed inside
// (By listing faye-websocket first, it's more likely that npm deduplication
// will prevent a second copy of faye-websocket from being installed inside
// sockjs.)
Npm.depends({
"websocket-driver": "0.3.6",
sockjs: "0.3.9",
"tunnel-agent": "0.4.0"
"faye-websocket": "0.8.1",
sockjs: "0.3.11"
});
Package.on_use(function (api) {

View File

@@ -36,7 +36,7 @@ _.extend(LivedataTest.ClientStream.prototype, {
send: function (data) {
var self = this;
if (self.currentStatus.connected) {
self.client.messages.write(data);
self.client.send(data);
}
},
@@ -111,6 +111,17 @@ _.extend(LivedataTest.ClientStream.prototype, {
}
},
_getProxyUrl: function (targetUrl) {
var self = this;
// Similar to code in tools/http-helpers.js.
var proxy = process.env.HTTP_PROXY || process.env.http_proxy || null;
// if we're going to a secure url, try the https_proxy env variable first.
if (targetUrl.match(/^wss:/)) {
proxy = process.env.HTTPS_PROXY || process.env.https_proxy || proxy;
}
return proxy;
},
_launchConnection: function () {
var self = this;
self._cleanup(); // cleanup the old socket, if there was one.
@@ -118,15 +129,24 @@ _.extend(LivedataTest.ClientStream.prototype, {
// Since server-to-server DDP is still an experimental feature, we only
// require the module if we actually create a server-to-server
// connection.
var websocketDriver = Npm.require('websocket-driver');
var FayeWebSocket = Npm.require('faye-websocket');
var targetUrl = toWebsocketUrl(self.endpoint);
var fayeOptions = { headers: self.headers };
var proxyUrl = self._getProxyUrl(targetUrl);
if (proxyUrl) {
fayeOptions.proxy = { origin: proxyUrl };
};
// We would like to specify 'ddp' as the subprotocol here. The npm module we
// used to use as a client would fail the handshake if we ask for a
// subprotocol and the server doesn't send one back (and sockjs doesn't).
// Faye doesn't have that behavior; it's unclear from reading RFC 6455 if
// Faye is erroneous or not. So for now, we don't specify protocols.
var wsUrl = toWebsocketUrl(self.endpoint);
var client = self.client = websocketDriver.client(wsUrl);
var subprotocols = [];
var client = self.client = new FayeWebSocket.Client(
targetUrl, subprotocols, fayeOptions);
self._clearConnectionTimer();
self.connectionTimer = Meteor.setTimeout(
@@ -136,22 +156,6 @@ _.extend(LivedataTest.ClientStream.prototype, {
},
self.CONNECT_TIMEOUT);
var onConnect = function () {
client.start();
};
var stream = self._createSocket(wsUrl, onConnect);
if (!self.client) {
// We hit a connection timeout or other issue while yielding in
// _createSocket. Drop the connection.
stream.end();
return;
}
_.each(self.headers, function (header, name) {
client.setHeader(name, header);
});
self.client.on('open', Meteor.bindEnvironment(function () {
return self._onConnect(client);
}, "stream connect callback"));
@@ -165,131 +169,29 @@ _.extend(LivedataTest.ClientStream.prototype, {
}, description));
};
var finalize = Meteor.bindEnvironment(function () {
if (stream.unpipe) {
stream.unpipe(client.io);
}
stream.on('data', function () {
stream.destroy();
});
stream.end();
if (client === self.client) {
self._lostConnection();
}
}, "finalizing stream");
stream.on('end', finalize);
stream.on('close', finalize);
client.on('close', finalize);
var onError = function (message) {
clientOnIfCurrent('error', 'stream error callback', function (error) {
if (!self.options._dontPrintErrors)
Meteor._debug("driver error", message);
Meteor._debug("stream error", error.message);
// Faye's 'error' object is not a JS error (and among other things,
// doesn't stringify well). Convert it to one.
self._lostConnection(new DDP.ConnectionError(message));
};
clientOnIfCurrent('error', 'driver error callback', function (error) {
onError(error.message);
self._lostConnection(new DDP.ConnectionError(error.message));
});
clientOnIfCurrent('close', 'stream close callback', function () {
self._lostConnection();
});
stream.on('error', Meteor.bindEnvironment(function (error) {
if (client === self.client) {
onError('Network error: ' + wsUrl + ': ' + error.message);
}
stream.end();
}));
clientOnIfCurrent('message', 'stream message callback', function (message) {
// Ignore binary frames, where data is a Buffer
// Ignore binary frames, where message.data is a Buffer
if (typeof message.data !== "string")
return;
_.each(self.eventCallbacks.message, function (callback) {
callback(message.data);
});
});
stream.pipe(self.client.io);
self.client.io.pipe(stream);
},
_createSocket: function (wsUrl, onConnect) {
var self = this;
var urlModule = Npm.require('url');
var parsedTargetUrl = urlModule.parse(wsUrl);
var targetUrlPort = +parsedTargetUrl.port;
if (!targetUrlPort) {
targetUrlPort = parsedTargetUrl.protocol === 'wss:' ? 443 : 80;
}
// Corporate proxy tunneling support.
var proxyUrl = self._getProxyUrl(parsedTargetUrl.protocol);
if (proxyUrl) {
var targetProtocol =
(parsedTargetUrl.protocol === 'wss:' ? 'https' : 'http');
var parsedProxyUrl = urlModule.parse(proxyUrl);
var proxyProtocol =
(parsedProxyUrl.protocol === 'https:' ? 'Https' : 'Http');
var proxyUrlPort = +parsedProxyUrl.port;
if (!proxyUrlPort) {
proxyUrlPort = parsedProxyUrl.protocol === 'https:' ? 443 : 80;
}
var tunnelFnName = targetProtocol + 'Over' + proxyProtocol;
var tunnelAgent = Npm.require('tunnel-agent');
var proxyOptions = {
host: parsedProxyUrl.hostname,
port: proxyUrlPort,
headers: {
host: parsedTargetUrl.host + ':' + targetUrlPort
}
};
if (parsedProxyUrl.auth) {
proxyOptions.proxyAuth = Npm.require('querystring').unescape(
parsedProxyUrl.auth);
}
var tunneler = tunnelAgent[tunnelFnName]({proxy: proxyOptions});
var events = Npm.require('events');
var fakeRequest = new events.EventEmitter();
var Future = Npm.require('fibers/future');
var fut = new Future;
fakeRequest.on('error', function (e) {
fut.isResolved() || fut.throw(e);
});
tunneler.createSocket({
host: parsedTargetUrl.host,
port: targetUrlPort,
request: fakeRequest
}, function (socket) {
socket.on('close', function () {
tunneler.removeSocket(socket);
});
process.nextTick(onConnect);
fut.return(socket);
});
return fut.wait();
}
if (parsedTargetUrl.protocol === 'wss:') {
return Npm.require('tls').connect(
targetUrlPort, parsedTargetUrl.hostname, onConnect);
} else {
var stream = Npm.require('net').createConnection(
targetUrlPort, parsedTargetUrl.hostname);
stream.on('connect', onConnect);
return stream;
}
},
_getProxyUrl: function (protocol) {
var self = this;
// Similar to code in tools/http-helpers.js.
var proxy = process.env.HTTP_PROXY || process.env.http_proxy || null;
// if we're going to a secure url, try the https_proxy env variable first.
if (protocol === 'wss:') {
proxy = process.env.HTTPS_PROXY || process.env.https_proxy || proxy;
}
return proxy;
}
});

View File

@@ -148,7 +148,7 @@ testAsyncMulti("stream - /websocket is a websocket endpoint", [
_.each(['/websocket', '/websocket/'], function(path) {
HTTP.get(Meteor._relativeToSiteRootUrl(path), expect(function(error, result) {
test.isNotNull(error);
test.equal('Can "Upgrade" only to "WebSocket".', result.content);
test.equal('Not a valid websocket request', result.content);
}));
});
@@ -164,12 +164,12 @@ testAsyncMulti("stream - /websocket is a websocket endpoint", [
test.equal(pageContent, result.content);
});
HTTP.get(Meteor._relativeToSiteRootUrl('/'), expect(function(error, result) {
HTTP.get(Meteor.absoluteUrl('/'), expect(function(error, result) {
test.isNull(error);
pageContent = result.content;
_.each(['/websockets', '/websockets/'], function(path) {
HTTP.get(Meteor._relativeToSiteRootUrl(path), wrappedCallback);
HTTP.get(Meteor.absoluteUrl(path), wrappedCallback);
});
}));
}

View File

@@ -136,7 +136,7 @@ Tinytest.add("Smart Package version string parsing - or", function (test) {
FAIL("foo@1.0.0-rc|1.0.0");
// This is the current implementation, but is arguably not great.
FAIL("foo@1.0.0 ");
FAIL("foo@1.0.0 "); // trailing space
});
Tinytest.add(

View File

@@ -71,6 +71,54 @@ umask 022
mkdir build
cd build
TEMP_PREFIX="$DIR/build/prefix"
mkdir -p $TEMP_PREFIX
# Add $DIR/bin and $TEMP_PREFIX/bin to $PATH so that we can use tools
# installed earlier when building later tools (namely, autoconf and
# automake for watchman, and node and npm for the various NPM packages we
# install below).
export PATH="$DIR/bin:$PATH"
PATH="$TEMP_PREFIX/bin:$PATH"
# Build reliable versions of m4, autoconf, and automake for watchman and
# potentially other projects.
M4_VERSION="1.4.17"
curl "http://ftp.gnu.org/gnu/m4/m4-$M4_VERSION.tar.gz" | gzip -d | tar x
pushd "m4-$M4_VERSION"
./configure --prefix="$TEMP_PREFIX"
make install
popd
AUTOCONF_VERSION="2.69"
curl "http://ftp.gnu.org/gnu/autoconf/autoconf-$AUTOCONF_VERSION.tar.gz" | gzip -d | tar x
pushd "autoconf-$AUTOCONF_VERSION"
./configure --prefix="$TEMP_PREFIX"
make install
popd
AUTOMAKE_VERSION="1.14"
curl "http://ftp.gnu.org/gnu/automake/automake-$AUTOMAKE_VERSION.tar.gz" | gzip -d | tar x
pushd "automake-$AUTOMAKE_VERSION"
./configure --prefix="$TEMP_PREFIX"
make install
popd
WATCHMAN_VERSION="3.0.0"
curl "https://codeload.github.com/facebook/watchman/tar.gz/v$WATCHMAN_VERSION" | gzip -d | tar x
pushd "watchman-$WATCHMAN_VERSION"
./autogen.sh
./configure --prefix="$DIR" --without-pcre
make install
strip "$DIR/bin/watchman"
popd
# Clean up some unnecessary megabytes of docs.
rm -rf "$DIR/share/doc" "$DIR/share/man"
which watchman
# ios-sim is used to run iPhone simulator from the command-line. Doesn't make
# sense to build it for linux.
if [ "$OS" == "osx" ]; then
@@ -110,9 +158,6 @@ make install PORTABLE=1
# PORTABLE=1 is a node hack to make npm look relative to itself instead
# of hard coding the PREFIX.
# export path so we use our new node for later builds
export PATH="$DIR/bin:$PATH"
which node
which npm
@@ -180,6 +225,8 @@ rm -rf node_modules/browserstack-webdriver/lib/test
npm install node-inspector@0.7.4
npm install sane@1.0.0-rc1
npm install chalk@0.5.1
npm install sqlite3@3.0.2

View File

@@ -1,18 +1,10 @@
var path = require('path');
var files = require(path.join(__dirname, 'files.js'));
var watch = require('./watch.js');
var files = require('./files.js');
var NpmDiscards = require('./npm-discards.js');
var fs = require('fs');
var _ = require('underscore');
var sha1 = function (contents) {
var crypto = require('crypto');
var hash = crypto.createHash('sha1');
hash.update(contents);
return hash.digest('hex');
};
// Builder encapsulates much of the file-handling logic need to create
// "bundles" (directory trees such as site archives, programs, or
// packages). It can create a temporary directory in which to build
@@ -499,7 +491,4 @@ _.extend(Builder.prototype, {
}
});
// static convenience method
Builder.sha1 = sha1;
module.exports = Builder;

View File

@@ -293,7 +293,7 @@ _.extend(File.prototype, {
hash: function () {
var self = this;
if (! self._hash)
self._hash = Builder.sha1(self.contents());
self._hash = watch.sha1(self.contents());
return self._hash;
},
@@ -1171,7 +1171,7 @@ _.extend(ClientTarget.prototype, {
path: dataFile,
where: 'internal',
type: type,
hash: Builder.sha1(dataBuffer)
hash: watch.sha1(dataBuffer)
});
}
});
@@ -1449,7 +1449,7 @@ _.extend(JsImage.prototype, {
loadItem.assets = {};
_.each(item.assets, function (data, relPath) {
var sha = Builder.sha1(data);
var sha = watch.sha1(data);
if (_.has(assetFilesBySha, sha)) {
loadItem.assets[relPath] = assetFilesBySha[sha];
} else {

View File

@@ -332,7 +332,6 @@ _.extend(LocalCatalog.prototype, {
testName: packageSource.testName,
version: version,
publishedBy: null,
earliestCompatibleVersion: packageSource.earliestCompatibleVersion,
description: packageSource.metadata.summary,
dependencies: packageSource.getDependencyMetadata(),
source: null,

View File

@@ -32,7 +32,7 @@ catalog.Refresh.OnceAtStart.prototype.beforeCommand = function () {
if (self.options.ignoreErrors) {
Console.debug("Failed to update package catalog, but will continue.");
} else {
Console.error(catalog.refreshError);
Console.printError(catalog.refreshError);
Console.error("This command requires an up-to-date package catalog. Exiting.");
// Avoid circular dependency.
throw new (require('./main.js').ExitWithCode)(1);
@@ -161,22 +161,6 @@ _.extend(LayeredCatalog.prototype, {
return self.otherCatalog[f].apply(self.otherCatalog, splittedArgs);
},
// Returns the map from version to earliestCompatibleVersion for all versions
// overridden by a local package. If there's no local package, returns an
// empty object.
getForgottenECVs: function (packageName) {
var self = this;
if (! self.localCatalog.getPackage(packageName))
return {};
var versions = self.otherCatalog.getSortedVersions(packageName);
var forgottenECVs = {};
_.each(versions, function (v) {
var vr = self.otherCatalog.getVersion(packageName, v);
forgottenECVs[v] = vr.earliestCompatibleVersion;
});
return forgottenECVs;
},
// Doesn't download packages. Downloading should be done at the time
// that .meteor/versions is updated.
getLoadPathForPackage: function (name, version, constraintSolverOpts) {

View File

@@ -2714,57 +2714,6 @@ main.registerCommand({
});
main.registerCommand({
name: 'admin set-earliest-compatible-version',
minArgs: 2,
maxArgs: 2,
catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: false })
}, function (options) {
// We want the most recent information.
//refreshOfficialCatalogOrDie();
var package = options.args[0].split('@');
var name = package[0];
var version = package[1];
if (!version) {
Console.error('\n Must specify release version (track@version)');
return 1;
}
var ecv = options.args[1];
// Now let's get down to business! Fetching the thing.
var record = catalog.official.getPackage(name);
if (!record) {
Console.error('\n There is no package named ' + name);
return 1;
}
try {
var conn = packageClient.loggedInPackagesConnection();
} catch (err) {
packageClient.handlePackageServerConnectionError(err);
return 1;
}
try {
Console.info(
"Setting earliest compatible version on "
+ options.args[0] + " to " + ecv + "...");
var versionInfo = { name : name,
version : version };
packageClient.callPackageServer(conn,
'_setEarliestCompatibleVersion', versionInfo, ecv);
Console.info("Done!");
} catch (err) {
packageClient.handlePackageServerConnectionError(err);
return 1;
}
conn.close();
refreshOfficialCatalogOrDie();
return 0;
});
main.registerCommand({
name: 'admin change-homepage',
minArgs: 2,

View File

@@ -727,7 +727,10 @@ var buildCommand = function (options) {
var localPath = path.join(options.appDir, '.meteor', 'local');
var mobilePlatforms = project.getCordovaPlatforms();
var mobilePlatforms = [];
if (! options._serverOnly) {
mobilePlatforms = project.getCordovaPlatforms();
}
var appName = path.basename(options.appDir);
if (! _.isEmpty(mobilePlatforms) && ! options._serverOnly) {
@@ -777,27 +780,22 @@ var buildCommand = function (options) {
var buildDir = path.join(localPath, 'build_tar');
var outputPath = path.resolve(options.args[0]); // get absolute path
if (! _.isEmpty(mobilePlatforms)) {
// XXX: Create helper function? Maybe fs.resolve to follow symlinks?
var appDir = path.resolve(options.appDir);
if (appDir.substr(-1) !== path.sep) {
appDir += path.sep;
}
var outputDir = path.resolve(outputPath);
if (outputDir.substr(-1) !== path.sep) {
outputDir += path.sep;
}
if (outputDir.indexOf(appDir) == 0) {
// Unless we're just making a tarball, warn if people try to build inside the
// app directory.
if (options.directory || ! _.isEmpty(mobilePlatforms)) {
var relative = path.relative(options.appDir, outputPath);
// We would like the output path to be outside the app directory, which
// means the first step to getting there is going up a level.
if (relative.substr(0, 3) !== ('..' + path.sep)) {
Console.warn("");
Console.warn("Warning: The output directory is under your source tree.");
Console.warn(" This causes issues when building with mobile platforms.");
Console.warn(" Your generated files may get interpreted as source code!");
Console.warn(" Consider building into a different directory instead (" + Console.command("meteor build ../output") + ")");
Console.warn("");
}
}
var bundlePath = options['directory'] ?
var bundlePath = options.directory ?
(options._serverOnly ? outputPath : path.join(outputPath, 'bundle')) :
path.join(buildDir, 'bundle');
@@ -841,7 +839,7 @@ var buildCommand = function (options) {
if (! options._serverOnly)
files.mkdir_p(outputPath);
if (! options['directory']) {
if (! options.directory) {
try {
var outputTar = options._serverOnly ? outputPath :
path.join(outputPath, appName + '.tar.gz');

View File

@@ -1057,7 +1057,6 @@ compiler.compile = function (packageSource, options) {
name: packageSource.name,
metadata: packageSource.metadata,
version: packageSource.version,
earliestCompatibleVersion: packageSource.earliestCompatibleVersion,
isTest: packageSource.isTest,
plugins: plugins,
pluginWatchSet: pluginWatchSet,

View File

@@ -516,12 +516,42 @@ _.extend(Console.prototype, {
setPretty: function (pretty) {
var self = this;
if (FORCE_PRETTY === undefined) {
self._pretty = pretty;
}
// If we're being forced, do nothing.
if (FORCE_PRETTY !== undefined)
return;
// If no change, do nothing.
if (self._pretty === pretty)
return;
self._pretty = pretty;
self._updateProgressDisplay();
},
// Runs f with the progress display visible (ie, with progress display enabled
// and pretty). Resets both flags to their original values after f runs.
withProgressDisplayVisible: function (f) {
var self = this;
var originalPretty = self._pretty;
var originalProgressDisplayEnabled = self._progressDisplayEnabled;
// Turn both flags on.
self._pretty = self._progressDisplayEnabled = true;
// Update the screen if anything changed.
if (!originalPretty || !originalProgressDisplayEnabled)
self._updateProgressDisplay();
try {
return f();
} finally {
// Reset the flags.
self._pretty = originalPretty;
self._progressDisplayEnabled = originalProgressDisplayEnabled;
// Update the screen if anything changed.
if (!originalPretty || !originalProgressDisplayEnabled)
self._updateProgressDisplay();
}
},
setVerbose: function (verbose) {
var self = this;
self.verbose = verbose;
@@ -745,6 +775,9 @@ _.extend(Console.prototype, {
enabled = true;
}
if (self._progressDisplayEnabled === enabled)
return;
self._progressDisplayEnabled = enabled;
self._updateProgressDisplay();
},

View File

@@ -234,7 +234,6 @@ var Isopack = function () {
self.name = null;
self.metadata = {};
self.version = null;
self.earliestCompatibleVersion = null;
self.isTest = false;
self.debugOnly = false;
@@ -311,7 +310,6 @@ _.extend(Isopack.prototype, {
self.name = options.name;
self.metadata = options.metadata;
self.version = options.version;
self.earliestCompatibleVersion = options.earliestCompatibleVersion;
self.isTest = options.isTest;
self.plugins = options.plugins;
self.cordovaDependencies = options.cordovaDependencies;
@@ -637,7 +635,6 @@ _.extend(Isopack.prototype, {
summary: mainJson.summary
};
self.version = mainJson.version;
self.earliestCompatibleVersion = mainJson.earliestCompatibleVersion;
self.isTest = mainJson.isTest;
self.debugOnly = !!mainJson.debugOnly;
}
@@ -727,8 +724,6 @@ _.extend(Isopack.prototype, {
JSON.stringify(resource.type));
});
self.cordovaDependencies = mainJson.cordovaDependencies || null;
self.unibuilds.push(new Unibuild(self, {
name: unibuildMeta.name,
arch: unibuildMeta.arch,
@@ -738,11 +733,12 @@ _.extend(Isopack.prototype, {
nodeModulesPath: nodeModulesPath,
prelinkFiles: prelinkFiles,
packageVariables: unibuildJson.packageVariables || [],
resources: resources,
cordovaDependencies: unibuildJson.cordovaDependencies
resources: resources
}));
});
self.cordovaDependencies = mainJson.cordovaDependencies || null;
_.each(mainJson.tools, function (toolMeta) {
toolMeta.rootDir = dir;
// XXX check for overlap
@@ -775,7 +771,6 @@ _.extend(Isopack.prototype, {
name: self.name,
summary: self.metadata.summary,
version: self.version,
earliestCompatibleVersion: self.earliestCompatibleVersion,
isTest: self.isTest,
builds: [],
plugins: []
@@ -812,8 +807,7 @@ _.extend(Isopack.prototype, {
pluginProviderPackages: self.pluginProviderPackageDirs,
source: options.buildOfPath || undefined,
buildTimeDirectDependencies: buildTimeDirectDeps,
buildTimePluginDependencies: buildTimePluginDeps,
cordovaDependencies: self.cordovaDependencies
buildTimePluginDependencies: buildTimePluginDeps
};
}

View File

@@ -371,22 +371,18 @@ var springboard = function (rel, options) {
// XXX split better
try {
Console.setPretty(true);
Console.enableProgressDisplay(true);
buildmessage.enterJob({
title: "Downloading tools package " + toolsPkg + "@" + toolsVersion
}, function () {
tropohouse.default.maybeDownloadPackageForArchitectures({
packageName: toolsPkg,
version: toolsVersion,
architectures: [archinfo.host()],
definitelyNotLocal: true
Console.withProgressDisplayVisible(function () {
buildmessage.enterJob({
title: "Downloading tools package " + toolsPkg + "@" + toolsVersion
}, function () {
tropohouse.default.maybeDownloadPackageForArchitectures({
packageName: toolsPkg,
version: toolsVersion,
architectures: [archinfo.host()],
definitelyNotLocal: true
});
});
});
Console.enableProgressDisplay(false);
Console.setPretty(false);
} catch (err) {
// We have failed to download the tool that we are supposed to springboard
// to! That's bad. Let's exit.
@@ -795,11 +791,9 @@ Fiber(function () {
// Somehow we have a catalog that doesn't have any releases on the
// default track. Try syncing, at least. (This is a pretty unlikely
// error case, since you should always start with a non-empty catalog.)
Console.setPretty(true);
Console.enableProgressDisplay(true);
alreadyRefreshed = catalog.refreshOrWarn();
Console.enableProgressDisplay(false);
Console.setPretty(false);
Console.withProgressDisplayVisible(function () {
alreadyRefreshed = catalog.refreshOrWarn();
});
releaseName = release.latestKnown();
}
if (!releaseName) {
@@ -855,11 +849,9 @@ Fiber(function () {
}
// ATTEMPT 3: modern release, troposphere sync needed.
Console.setPretty(true);
Console.enableProgressDisplay(true);
alreadyRefreshed = catalog.refreshOrWarn();
Console.enableProgressDisplay(false);
Console.setPretty(false);
Console.withProgressDisplayVisible(function () {
alreadyRefreshed = catalog.refreshOrWarn();
});
// Try to load the release even if the refresh failed, since it might
// have failed on a later page than the one we needed.
@@ -1296,7 +1288,6 @@ commandName + ": You're not in a Meteor project directory.\n" +
require('./profile-require.js').printReport();
Console.setPretty(command.pretty);
Console.enableProgressDisplay(true);
// Run the command!

View File

@@ -580,7 +580,6 @@ exports.publishPackage = function (packageSource, compileResult, conn, options)
version: version,
description: packageSource.metadata.summary,
git: packageSource.metadata.git,
earliestCompatibleVersion: packageSource.earliestCompatibleVersion,
compilerVersion: compiler.BUILT_BY,
containsPlugins: packageSource.containsPlugins(),
debugOnly: packageSource.debugOnly,

View File

@@ -223,10 +223,6 @@ var PackageSource = function (catalog) {
// with names have versions? certainly the reverse is true
self.version = null;
// The earliest version for which this package is supposed to be a
// compatible replacement. Set if and only if version is set.
self.earliestCompatibleVersion = null;
// Available architectures of this package. Array of SourceArch.
self.architectures = [];
@@ -452,7 +448,7 @@ _.extend(PackageSource.prototype, {
var packageJsPath = path.join(self.sourceRoot, 'package.js');
var code = fs.readFileSync(packageJsPath);
var packageJsHash = Builder.sha1(code);
var packageJsHash = watch.sha1(code);
var releaseRecords = [];
var hasTests = false;
@@ -476,7 +472,6 @@ _.extend(PackageSource.prototype, {
// Set package metadata. Options:
// - summary: for 'meteor list' & package server
// - version: package version string
// - earliestCompatibleVersion: version string
// There used to be a third option documented here,
// 'environments', but it was never implemented and no package
// ever used it.
@@ -510,8 +505,6 @@ _.extend(PackageSource.prototype, {
// XXX validate that version parses -- and that it doesn't
// contain a +!
self.version = value;
} else if (key === "earliestCompatibleVersion") {
self.earliestCompatibleVersion = value;
} else if (key === "name" && !self.isTest) {
if (!self.name) {
self.name = value;
@@ -970,11 +963,6 @@ _.extend(PackageSource.prototype, {
}
}
if (self.version !== null && ! self.earliestCompatibleVersion) {
self.earliestCompatibleVersion =
packageVersionParser.defaultECV(self.version);
}
// source files used
var sources = {};

View File

@@ -90,7 +90,7 @@ var prereleaseIdentifierToFraction = function (prerelease) {
if (prerelease.length === 0)
return 0;
return _.reduce(prerelease, function (memo, part, index) {
return __.reduce(prerelease, function (memo, part, index) {
var digit;
if (typeof part === 'number') {
digit = part+1;
@@ -124,16 +124,18 @@ PV.lessThan = function (versionOne, versionTwo) {
return PV.compare(versionOne, versionTwo) < 0;
};
// Given a string version, computes its default ECV (not counting any overrides).
// Given a string version, returns its major version (the first section of the
// semver), as an integer. Two versions are compatible if they have the same
// version number.
//
// versionString: valid meteor version string.
PV.defaultECV = function (versionString) {
PV.majorVersion = function (versionString) {
var version = extractSemverPart(versionString).semver;
var parsed = semver.parse(version);
if (! parsed)
throwVersionParserError("not a valid version: " + version);
return parsed.major + ".0.0";
}
throwVersionParserError("not a valid version: " + version);
return parsed.major;
};
// Takes in two meteor versions. Returns 0 if equal, 1 if v1 is greater, -1 if
// v2 is greater.

View File

@@ -430,8 +430,9 @@ _.extend(Project.prototype, {
if (!oldVersion) {
return;
}
var oldECV = oldVersion.earliestCompatibleVersion;
if (oldECV !== newRec.earliestCompatibleVersion) {
var oldMajorVersion = packageVersionParser.majorVersion(oldV);
var newMajorVersion = packageVersionParser.majorVersion(newV);
if (oldMajorVersion !== newMajorVersion) {
incompatibleUpdates.push({
name: package,
description: "(" + oldV + "->" + newV + ") " + newRec.description

View File

@@ -682,7 +682,6 @@ _.extend(Sandbox.prototype, {
stubCatalog.collections.versions.push({
packageName: toolPackageName,
version: toolPackage.version,
earliestCompatibleVersion: toolPackage.version,
containsPlugins: false,
description: toolPackage.metadata.summary,
dependencies: {},
@@ -758,7 +757,6 @@ _.extend(Sandbox.prototype, {
stubCatalog.collections.versions.push({
packageName: name,
version: versionRec.version,
earliestCompatibleVersion: versionRec.earliestCompatibleVersion,
containsPlugins: false,
description: "warehouse test",
dependencies: {},

View File

@@ -57,7 +57,8 @@ _.extend(exports.Tropohouse.prototype, {
}
var relativePath = path.join(config.getPackagesDirectoryName(),
packageName, version);
utils.escapePackageNameForPath(packageName),
version);
return relative ? relativePath : path.join(self.root, relativePath);
},
@@ -70,7 +71,7 @@ _.extend(exports.Tropohouse.prototype, {
var packageRootDir = path.join(self.root, packagesDirectoryName);
try {
var packages = fs.readdirSync(packageRootDir);
var escapedPackages = fs.readdirSync(packageRootDir);
} catch (e) {
// No packages at all? We're done.
if (e.code === 'ENOENT')
@@ -80,9 +81,9 @@ _.extend(exports.Tropohouse.prototype, {
// We want to be careful not to break the 'meteor' symlink inside the
// tropohouse. Hopefully nobody deleted/modified that package!
var latestToolPackage = null;
var latestToolPackageEscaped = null;
var latestToolVersion = null;
var currentToolPackage = null;
var currentToolPackageEscaped = null;
var currentToolVersion = null;
// Warning: we can't examine release.current here, because we might be
// currently processing release.load!
@@ -91,7 +92,8 @@ _.extend(exports.Tropohouse.prototype, {
// /home/user/.meteor/packages/meteor-tool/.1.0.17.ut200e++os.osx.x86_64+web.browser+web.cordova/meteor-tool-os.osx.x86_64
var toolsDir = files.getCurrentToolsDir();
// eg, 'meteor-tool'
currentToolPackage = path.basename(path.dirname(path.dirname(toolsDir)));
currentToolPackageEscaped =
path.basename(path.dirname(path.dirname(toolsDir)));
// eg, '.1.0.17-xyz1.2.ut200e++os.osx.x86_64+web.browser+web.cordova'
var toolVersionDir = path.basename(path.dirname(toolsDir));
var toolVersionWithDotAndRandomBit = toolVersionDir.split('++')[0];
@@ -104,13 +106,13 @@ _.extend(exports.Tropohouse.prototype, {
packagesDirectoryName + path.sep)) {
var rest = latestMeteorSymlink.substr(packagesDirectoryName.length + path.sep.length);
var pieces = rest.split(path.sep);
latestToolPackage = pieces[0];
latestToolPackageEscaped = pieces[0];
latestToolVersion = pieces[1];
}
}
_.each(packages, function (package) {
var packageDir = path.join(packageRootDir, package);
_.each(packagesEscaped, function (packageEscaped) {
var packageDir = path.join(packageRootDir, packageEscaped);
try {
var versions = fs.readdirSync(packageDir);
} catch (e) {
@@ -119,7 +121,7 @@ _.extend(exports.Tropohouse.prototype, {
return;
throw e;
}
_.each(fs.readdirSync(packageDir), function (version) {
_.each(versions, function (version) {
// Is this a pre-0.9.0 "warehouse" version with a hash name?
if (/^[a-f0-9]{3,}$/.test(version))
return;
@@ -127,7 +129,7 @@ _.extend(exports.Tropohouse.prototype, {
// Skip the currently-latest tool (ie, don't break top-level meteor
// symlink). This includes both the symlink with its name and the thing
// it points to.
if (package === latestToolPackage &&
if (packageEscaped === latestToolPackageEscaped &&
(version === latestToolVersion ||
utils.startsWith(version, '.' + latestToolVersion + '.'))) {
return;
@@ -135,7 +137,7 @@ _.extend(exports.Tropohouse.prototype, {
// Skip the currently-executing tool (ie, don't break the current
// operation).
if (package === currentToolPackage &&
if (packageEscaped === currentToolPackageEscaped &&
(version === currentToolVersion ||
utils.startsWith(version, '.' + currentToolVersion + '.'))) {
return;

View File

@@ -668,3 +668,11 @@ exports.mobileServerForRun = function (options) {
protocol: "http://"
};
};
exports.escapePackageNameForPath = function (packageName) {
return packageName.replace(":", "_");
};
exports.unescapePackageNameForPath = function (escapedPackageName) {
return escapedPackageName.replace("_", ":");
};

View File

@@ -573,5 +573,6 @@ _.extend(exports, {
isUpToDate: isUpToDate,
readAndWatchDirectory: readAndWatchDirectory,
readAndWatchFile: readAndWatchFile,
readAndWatchFileWithHash: readAndWatchFileWithHash
readAndWatchFileWithHash: readAndWatchFileWithHash,
sha1: sha1
});