diff --git a/.travis.yml b/.travis.yml index e41c369129..5ec40272b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "0.10" + - "4.0" cache: directories: - "dev_bundle" @@ -9,3 +9,11 @@ cache: install: ./meteor --get-ready script: TEST_PACKAGES_EXCLUDE="less" ./packages/test-in-console/run.sh sudo: false +env: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 diff --git a/History.md b/History.md index 000392d572..84f0b7520f 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,47 @@ ## v.NEXT +## v1.4 + +* Node has been upgraded to 4.4.7. + +* The `meteor-babel` npm package has been upgraded to 0.11.7. + +* The `reify` npm package has been upgraded to 0.3.6. + +* The `bcrypt` npm package has been upgraded to 0.8.7. + +* Nested `import` declarations are now enabled for package code as well as + application code. 699cf1f38e9b2a074169515d23983f74148c7223 + +* Meteor has been upgraded to support Mongo 3.2 by default (the bundled version + used by `meteor run` has been upgraded). Internally it now uses the 2.2.4 + version of the `mongodb` npm driver, and has been tested against at Mongo 3.2 + server. [Issue #6957](https://github.com/meteor/meteor/issues/6957) + + Mongo 3.2 defaults to the new WiredTiger storage engine. You can update your + database following the instructions here: + https://docs.mongodb.com/v3.0/release-notes/3.0-upgrade/. + In development, you can also just use `meteor reset` to remove your old + database, and Meteor will create a new WiredTiger database for you. The Mongo + driver will continue to work with the old MMAPv1 storage engine however. + + The new version of the Mongo driver has been tested with MongoDB versions from + 2.6 up. Mongo 2.4 has now reached end-of-life + (https://www.mongodb.com/support-policy), and is no longer supported. + +* Custom Mongo options can now be specified using the + `Mongo.setConnectionOptions(options)` API. + [#7277](https://github.com/meteor/meteor/pull/7277) + +* On the server, cursor.count() now takes a single argument `applySkipLimit` + (see the corresponding [Mongo documentation] + (http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#count)) + +* Fix for regression caused by #5837 which incorrectly rewrote + network-path references (e.g. `//domain.com/image.gif`) in CSS URLs. + [#7416](https://github.com/meteor/meteor/issues/7416) +* Added Angular2 boilerplate example [#7364](https://github.com/meteor/meteor/pull/7363) + ## v1.3.5.1 * This release fixed a small bug in 1.3.5 that prevented updating apps @@ -95,6 +137,9 @@ * `App.appendToConfig` allows adding custom tags to config.xml. [#7307](https://github.com/meteor/meteor/pull/7307) +* When using `ROOT_URL` with a path, relative CSS URLs are rewriten + accordingly. [#5837](https://github.com/meteor/meteor/issues/5837) + * Fixed bugs: [#7149](https://github.com/meteor/meteor/issues/7149) [#7296](https://github.com/meteor/meteor/issues/7296) diff --git a/meteor b/meteor index 407a317f2f..0ab07e0073 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=0.6.19 +BUNDLE_VERSION=4.1.4 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/packages/accounts-base/accounts_server.js b/packages/accounts-base/accounts_server.js index dbffd61e64..b81dd40482 100644 --- a/packages/accounts-base/accounts_server.js +++ b/packages/accounts-base/accounts_server.js @@ -1260,9 +1260,9 @@ Ap.insertUserDoc = function (options, user) { // https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day if (e.name !== 'MongoError') throw e; if (e.code !== 11000) throw e; - if (e.err.indexOf('emails.address') !== -1) + if (e.errmsg.indexOf('emails.address') !== -1) throw new Meteor.Error(403, "Email already exists."); - if (e.err.indexOf('username') !== -1) + if (e.errmsg.indexOf('username') !== -1) throw new Meteor.Error(403, "Username already exists."); // XXX better error reporting for services.facebook.id duplicate, etc throw e; diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index 187699576e..a64b9a6611 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.2.8" + version: "1.2.9" }); Package.onUse(function (api) { diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index 7417a8d3e9..01ea4278df 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -1,10 +1,10 @@ Package.describe({ summary: "Password support for accounts", - version: "1.1.13" + version: "1.2.12" }); Package.onUse(function(api) { - api.use('npm-bcrypt@=0.8.6_3'); + api.use('npm-bcrypt@=0.8.7'); api.use([ 'accounts-base', diff --git a/packages/accounts-twitter/package.js b/packages/accounts-twitter/package.js index 3894997db8..63bb4aa397 100644 --- a/packages/accounts-twitter/package.js +++ b/packages/accounts-twitter/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Login service for Twitter accounts", - version: "1.0.10" + version: "1.1.11" }); Package.onUse(function(api) { diff --git a/packages/autoupdate/package.js b/packages/autoupdate/package.js index 5738196a10..c4b13bde2d 100644 --- a/packages/autoupdate/package.js +++ b/packages/autoupdate/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Update the client when new client code is available", - version: '1.2.11' + version: '1.3.11' }); Package.onUse(function (api) { diff --git a/packages/babel-compiler/babel-compiler.js b/packages/babel-compiler/babel-compiler.js index 1a56802a08..485ecb8aa9 100644 --- a/packages/babel-compiler/babel-compiler.js +++ b/packages/babel-compiler/babel-compiler.js @@ -76,22 +76,6 @@ BCp.processOneFileForTarget = function (inputFile, source) { extraFeatures.jscript = targetCouldBeInternetExplorer8; } - if (inputFile.isPackageFile()) { - // When compiling package files, handle import/export syntax using - // the official Babel plugin, so that package authors won't publish - // code that relies on module.import and module.export, because such - // code would fail on Meteor versions before 1.3.3. When compiling - // application files, however, it's fine to rely on module.import - // and module.export, and the developer experience will be much - // better for it: faster compilation, real variables, import - // statements inside conditional statements, etc. - // - // TODO Remove this once we are confident enough developers have - // updated to a version of Meteor that supports module.import and - // module.export. - extraFeatures.legacyModules = true; - } - var babelOptions = Babel.getDefaultOptions(extraFeatures); this.inferExtraBabelOptions(inputFile, babelOptions, cacheDeps); diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index ef5e4fca12..1a6c4306d2 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.8.5' + version: '6.9.0' }); Npm.depends({ diff --git a/packages/babel-runtime/package.js b/packages/babel-runtime/package.js index 5999385441..8f68486e18 100644 --- a/packages/babel-runtime/package.js +++ b/packages/babel-runtime/package.js @@ -1,7 +1,7 @@ Package.describe({ name: "babel-runtime", summary: "Runtime support for output of Babel transpiler", - version: '0.1.9_1', + version: '0.1.10', documentation: 'README.md' }); diff --git a/packages/caching-compiler/package.js b/packages/caching-compiler/package.js index 10cbd84dbe..06b1d6d4cd 100644 --- a/packages/caching-compiler/package.js +++ b/packages/caching-compiler/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'caching-compiler', - version: '1.0.6', + version: '1.1.6', summary: 'An easy way to make compiler plugins cache', documentation: 'README.md' }); diff --git a/packages/coffeescript/package.js b/packages/coffeescript/package.js index 37d6d16196..7f339ed356 100644 --- a/packages/coffeescript/package.js +++ b/packages/coffeescript/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Javascript dialect with fewer braces and semicolons", - version: "1.1.4" + version: "1.2.3" }); Package.registerBuildPlugin({ diff --git a/packages/constraint-solver/package.js b/packages/constraint-solver/package.js index 466e92e17e..f4655d7309 100644 --- a/packages/constraint-solver/package.js +++ b/packages/constraint-solver/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Given the set of the constraints, picks a satisfying configuration", - version: "1.0.27" + version: "1.1.0" }); Package.onUse(function (api) { diff --git a/packages/ddp-client/.npm/package/npm-shrinkwrap.json b/packages/ddp-client/.npm/package/npm-shrinkwrap.json index 33aa36859e..9007897712 100644 --- a/packages/ddp-client/.npm/package/npm-shrinkwrap.json +++ b/packages/ddp-client/.npm/package/npm-shrinkwrap.json @@ -1,19 +1,19 @@ { "dependencies": { "faye-websocket": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.4.tgz", - "from": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.4.tgz", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.0.tgz", + "from": "faye-websocket@0.11.0", "dependencies": { "websocket-driver": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.5.4.tgz", - "from": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.5.4.tgz", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.4.tgz", + "from": "websocket-driver@>=0.5.1", "dependencies": { "websocket-extensions": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", - "from": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz" + "from": "websocket-extensions@>=0.1.1" } } } @@ -27,7 +27,7 @@ "permessage-deflate": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.3.tgz", - "from": "https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.3.tgz" + "from": "permessage-deflate@0.1.3" } } } diff --git a/packages/ddp-client/package.js b/packages/ddp-client/package.js index 42f7db47a7..cc0cb2a6d3 100644 --- a/packages/ddp-client/package.js +++ b/packages/ddp-client/package.js @@ -1,11 +1,11 @@ Package.describe({ summary: "Meteor's latency-compensated distributed data client", - version: '1.2.9', + version: '1.3.0', documentation: null }); Npm.depends({ - "faye-websocket": "0.9.4", + "faye-websocket": "0.11.0", "lolex": "1.4.0", "permessage-deflate": "0.1.3" }); diff --git a/packages/ddp-server/livedata_server_tests.js b/packages/ddp-server/livedata_server_tests.js index f323ec6729..10203f319b 100644 --- a/packages/ddp-server/livedata_server_tests.js +++ b/packages/ddp-server/livedata_server_tests.js @@ -211,7 +211,7 @@ Tinytest.addAsync( Meteor.methods({ testResolvedPromise(arg) { const invocation1 = DDP._CurrentInvocation.get(); - return new Promise.resolve(arg).then(result => { + return Promise.resolve(arg).then(result => { const invocation2 = DDP._CurrentInvocation.get(); // This equality holds because Promise callbacks are bound to the // dynamic environment where .then was called. @@ -223,7 +223,7 @@ Meteor.methods({ }, testRejectedPromise(arg) { - return new Promise.resolve(arg).then(result => { + return Promise.resolve(arg).then(result => { throw new Meteor.Error(result + " raised Meteor.Error"); }); } diff --git a/packages/ddp-server/package.js b/packages/ddp-server/package.js index e0194906a3..c2a7731e23 100644 --- a/packages/ddp-server/package.js +++ b/packages/ddp-server/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's latency-compensated distributed data server", - version: '1.2.10', + version: '1.3.9', documentation: null }); diff --git a/packages/ecmascript-runtime/package.js b/packages/ecmascript-runtime/package.js index c56f531e2f..b014f46c7d 100644 --- a/packages/ecmascript-runtime/package.js +++ b/packages/ecmascript-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "ecmascript-runtime", - version: "0.2.12", + version: "0.3.12", summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set", git: "https://github.com/meteor/ecmascript-runtime", documentation: "README.md" diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 5bd970e945..252280c8be 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.4.8', + version: '0.5.7', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/email/package.js b/packages/email/package.js index ce32322d3a..ad1dc37e5d 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Send email messages", - version: "1.0.16" + version: "1.1.16" }); Npm.depends({ diff --git a/packages/es5-shim/package.js b/packages/es5-shim/package.js index fe81b86495..30e5b6451a 100644 --- a/packages/es5-shim/package.js +++ b/packages/es5-shim/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "es5-shim", - version: "4.5.13", + version: "4.6.13", summary: "Shims and polyfills to improve ECMAScript 5 support", documentation: "README.md" }); diff --git a/packages/http/package.js b/packages/http/package.js index 204bea1a66..745d6bc218 100644 --- a/packages/http/package.js +++ b/packages/http/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Make HTTP calls to remote servers", - version: '1.1.8' + version: '1.2.8' }); Npm.depends({ diff --git a/packages/jshint/package.js b/packages/jshint/package.js index 22dff3944c..50c54dc46f 100644 --- a/packages/jshint/package.js +++ b/packages/jshint/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'jshint', - version: '1.0.5', + version: '1.1.5', summary: 'Lint all your JavaScript files with JSHint.', documentation: 'README.md' }); diff --git a/packages/less/package.js b/packages/less/package.js index a79b7b9ae5..589d8bf262 100644 --- a/packages/less/package.js +++ b/packages/less/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'less', - version: '2.6.5', + version: '2.7.4', summary: 'Leaner CSS language', documentation: 'README.md' }); diff --git a/packages/logging/package.js b/packages/logging/package.js index 473194385b..c3a9806e24 100644 --- a/packages/logging/package.js +++ b/packages/logging/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Logging facility.", - version: '1.0.14' + version: '1.1.14' }); Npm.depends({ diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 7eaa9c328a..dca5e85d20 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.3.5_1' + version: '1.4.0' }); Package.includeTool(); diff --git a/packages/meteor/package.js b/packages/meteor/package.js index 57e2871a17..f4067cf16e 100644 --- a/packages/meteor/package.js +++ b/packages/meteor/package.js @@ -2,7 +2,7 @@ Package.describe({ summary: "Core Meteor environment", - version: '1.1.16' + version: '1.2.16' }); Package.registerBuildPlugin({ diff --git a/packages/minifier-css/minifier.js b/packages/minifier-css/minifier.js index bd88ede21d..0994ee6fc8 100644 --- a/packages/minifier-css/minifier.js +++ b/packages/minifier-css/minifier.js @@ -136,8 +136,9 @@ var rewriteRules = function (rules, mergedCssPath) { // We don't rewrite URLs starting with a protocol definition such as - // http, https, or data. - if (resource.protocol !== null) { + // http, https, or data, or those with network-path references + // i.e. //img.domain.com/cat.gif + if (resource.protocol !== null || resource.href.startsWith('//')) { continue; } diff --git a/packages/minifier-css/package.js b/packages/minifier-css/package.js index 7163d04566..3de369f110 100644 --- a/packages/minifier-css/package.js +++ b/packages/minifier-css/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "CSS minifier", - version: "1.1.13" + version: "1.2.13" }); Npm.depends({ diff --git a/packages/minifier-css/urlrewriting-tests.js b/packages/minifier-css/urlrewriting-tests.js index 804e81786e..8626267909 100644 --- a/packages/minifier-css/urlrewriting-tests.js +++ b/packages/minifier-css/urlrewriting-tests.js @@ -78,6 +78,7 @@ Tinytest.add("minifier-css - url rewriting with media queries (ast rule recursio t("'/image.png'", "'image.png'", 'single quoted url'); t('"./../image.png"', '"packages/image.png"', 'quoted parent directory'); t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL'); + t('//i.imgur.com/fBcdJIh.gif', '//i.imgur.com/fBcdJIh.gif', 'network-path reference'); t('"http://i.imgur.com/fBcdJIh.gif"', '"http://i.imgur.com/fBcdJIh.gif"', 'complete quoted URL'); t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI'); t('http://', 'http://', 'malformed URL'); @@ -90,6 +91,7 @@ Tinytest.add("minifier-css - url rewriting with media queries (ast rule recursio t('"/image.png"', '"image.png"', 'double quoted url'); t("'/image.png'", "'image.png'", 'single quoted url'); t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL'); + t('//i.imgur.com/fBcdJIh.gif', '//i.imgur.com/fBcdJIh.gif', 'network-path reference'); t('"http://i.imgur.com/fBcdJIh.gif"', '"http://i.imgur.com/fBcdJIh.gif"', 'complete quoted URL'); t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI'); t('http://', 'http://', 'malformed URL'); diff --git a/packages/minifier-js/package.js b/packages/minifier-js/package.js index 7938b2096d..afb5f8b6c9 100644 --- a/packages/minifier-js/package.js +++ b/packages/minifier-js/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "JavaScript minifier", - version: "1.1.13" + version: "1.2.13" }); Npm.depends({ diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index d12e368a80..9ef594d341 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules-runtime", - version: "0.6.5", + version: "0.7.5", summary: "CommonJS module system", git: "https://github.com/benjamn/install", documentation: "README.md" diff --git a/packages/modules/package.js b/packages/modules/package.js index c24ecdfb64..2315ab1943 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.6.5", + version: "0.7.5", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 253a71d754..68192fefc5 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -317,7 +317,7 @@ _.extend(Mongo.Collection.prototype, { }, /** - * @summary Finds the first document that matches the selector, as ordered by sort and skip options. + * @summary Finds the first document that matches the selector, as ordered by sort and skip options. Returns `undefined` if no matching document is found. * @locus Anywhere * @method findOne * @memberOf Mongo.Collection @@ -537,7 +537,7 @@ Mongo.Collection.prototype.insert = function insert(doc, callback) { } /** - * @summary Modify one or more documents in the collection. Returns the number of affected documents. + * @summary Modify one or more documents in the collection. Returns the number of matched documents. * @locus Anywhere * @method update * @memberOf Mongo.Collection diff --git a/packages/mongo/connection_options.js b/packages/mongo/connection_options.js new file mode 100644 index 0000000000..c061513e0f --- /dev/null +++ b/packages/mongo/connection_options.js @@ -0,0 +1,10 @@ +/** + * @summary Allows for user specified connection options + * @example http://mongodb.github.io/node-mongodb-native/2.1/reference/connecting/connection-settings/ + * @locus Server + * @param {Object} options User specified Mongo connection options + */ +Mongo.setConnectionOptions = function setConnectionOptions (options) { + check(options, Object); + Mongo._connectionOptions = options; +} diff --git a/packages/mongo/mongo_driver.js b/packages/mongo/mongo_driver.js index 9c17458fee..567c349e4c 100644 --- a/packages/mongo/mongo_driver.js +++ b/packages/mongo/mongo_driver.js @@ -130,7 +130,8 @@ MongoConnection = function (url, options) { self._observeMultiplexers = {}; self._onFailoverHook = new Hook; - var mongoOptions = {db: {safe: true}, server: {}, replSet: {}}; + var mongoOptions = _.extend({db: {safe: true}, server: {}, replSet: {}}, + Mongo._connectionOptions); // Set autoReconnect to true, unless passed on the URL. Why someone // would want to set autoReconnect to false, I'm not really sure, but @@ -151,8 +152,8 @@ MongoConnection = function (url, options) { mongoOptions.db.native_parser = false; } - // XXX maybe we should have a better way of allowing users to configure the - // underlying Mongo driver + // Internally the oplog connections specify their own poolSize + // which we don't want to overwrite with any user defined value if (_.has(options, 'poolSize')) { // If we just set this for "server", replSet will override it. If we just // set it for replSet, it will be ignored if we're not using a replSet. @@ -180,8 +181,10 @@ MongoConnection = function (url, options) { } // First, figure out what the current primary is, if any. - if (db.serverConfig._state.master) - self._primary = db.serverConfig._state.master.name; + if (db.serverConfig.isMasterDoc) { + self._primary = db.serverConfig.isMasterDoc.primary; + } + db.serverConfig.on( 'joined', Meteor.bindEnvironment(function (kind, doc) { if (kind === 'primary') { @@ -408,8 +411,11 @@ MongoConnection.prototype._remove = function (collection_name, selector, try { var collection = self.rawCollection(collection_name); + var wrappedCallback = function(err, driverResult) { + callback(err, transformResult(driverResult).numberAffected); + }; collection.remove(replaceTypes(selector, replaceMeteorAtomWithMongo), - {safe: true}, callback); + {safe: true}, wrappedCallback); } catch (e) { write.committed(); throw e; @@ -553,19 +559,24 @@ MongoConnection.prototype._update = function (collection_name, selector, mod, } else { collection.update( mongoSelector, mongoMod, mongoOpts, - bindEnvironmentForWrite(function (err, result, extra) { + bindEnvironmentForWrite(function (err, result) { if (! err) { - if (result && options._returnObject) { - result = { numberAffected: result }; + var meteorResult = transformResult(result); + if (meteorResult && options._returnObject) { // If this was an upsert() call, and we ended up // inserting a new doc and we know its id, then // return that id as well. - if (options.upsert && knownId && - ! extra.updatedExisting) - result.insertedId = knownId; + + if (options.upsert && meteorResult.insertedId && knownId) { + meteorResult.insertedId = knownId; + } + callback(err, meteorResult); + } else { + callback(err, meteorResult.numberAffected); } + } else { + callback(err); } - callback(err, result); })); } } catch (e) { @@ -591,6 +602,29 @@ var isModificationMod = function (mod) { return isModify; }; +var transformResult = function (driverResult) { + var meteorResult = { numberAffected: 0 }; + if (driverResult) { + mongoResult = driverResult.result; + + // On updates with upsert:true, the inserted values come as a list of + // upserted values -- even with options.multi, when the upsert does insert, + // it only inserts one element. + if (mongoResult.upserted) { + meteorResult.numberAffected += mongoResult.upserted.length; + + if (mongoResult.upserted.length == 1) { + meteorResult.insertedId = mongoResult.upserted[0]._id; + } + } else { + meteorResult.numberAffected = mongoResult.n; + } + } + + return meteorResult; +}; + + var NUM_OPTIMISTIC_TRIES = 3; // exposed for testing @@ -599,13 +633,13 @@ MongoConnection._isCannotChangeIdError = function (err) { // checks should work, but just to be safe... if (err.code === 13596) return true; - if (err.err.indexOf("cannot change _id of a document") === 0) + if (err.errmsg.indexOf("cannot change _id of a document") === 0) return true; // Now look for what it looks like in Mongo 2.6. We don't use the error code // here, because the error code we observed it producing (16837) appears to be // a far more generic error code based on examining the source. - if (err.err.indexOf("The _id field cannot be changed") === 0) + if (err.errmsg.indexOf("The _id field cannot be changed") === 0) return true; return false; @@ -691,14 +725,15 @@ var simulateUpsertWithInsertedId = function (collection, selector, mod, } else { collection.update(selector, mod, mongoOptsForUpdate, bindEnvironmentForWrite(function (err, result) { - if (err) + if (err) { callback(err); - else if (result) + } else if (result && result.result.n != 0) { callback(null, { - numberAffected: result + numberAffected: result.result.n }); - else + } else { doConditionalInsert(); + } })); } }; @@ -720,8 +755,8 @@ var simulateUpsertWithInsertedId = function (collection, selector, mod, } } else { callback(null, { - numberAffected: result, - insertedId: insertedId + numberAffected: result.result.upserted.length, + insertedId: insertedId, }); } })); @@ -1054,9 +1089,9 @@ _.extend(SynchronousCursor.prototype, { return self.map(_.identity); }, - count: function () { + count: function (applySkipLimit: false) { var self = this; - return self._synchronousCount().wait(); + return self._synchronousCount(applySkipLimit).wait(); }, // This method is NOT wrapped in Cursor. diff --git a/packages/mongo/mongo_livedata_tests.js b/packages/mongo/mongo_livedata_tests.js index 1ebb537e12..cf06c5033d 100644 --- a/packages/mongo/mongo_livedata_tests.js +++ b/packages/mongo/mongo_livedata_tests.js @@ -310,6 +310,16 @@ Tinytest.addAsync("mongo-livedata - basics, " + idGeneration, function (test, on test.equal(coll.findOne({run: run}, {sort: {x: -1}, skip: 1}).x, 1); + // Regression test for https://github.com/meteor/meteor/issues/7436 + // - ensure applySkipLimit defaults to false for count() + // Note that the current behavior is inconsistent on the client. + // (https://github.com/meteor/meteor/issues/1201) + if (Meteor.isServer) { + test.equal(coll.find({run: run}, {limit: 1}).count(), 2); + test.equal(coll.find({run: run}, {limit: 1}).count(true), 1); + test.equal(coll.find({run: run}, {limit: 1}).count(false), 2); + } + var cur = coll.find({run: run}, {sort: ["x"]}); var total = 0; var index = 0; @@ -3236,7 +3246,7 @@ Meteor.isServer && Tinytest.add( Meteor.isServer && Tinytest.add("mongo-livedata - npm modules", function (test) { // Make sure the version number looks like a version number. - test.matches(MongoInternals.NpmModules.mongodb.version, /^1\.(\d+)\.(\d+)/); + test.matches(MongoInternals.NpmModules.mongodb.version, /^2\.(\d+)\.(\d+)/); test.equal(typeof(MongoInternals.NpmModules.mongodb.module), 'function'); test.equal(typeof(MongoInternals.NpmModules.mongodb.module.connect), 'function'); @@ -3345,3 +3355,87 @@ if (Meteor.isClient) { } }); } + +if (Meteor.isServer) { + Tinytest.add('mongo update/upsert - returns nMatched as numberAffected', function (test, onComplete) { + var collName = Random.id(); + var coll = new Mongo.Collection('update_nmatched'+collName); + + coll.insert({animal: 'cat', legs: 4}); + coll.insert({animal: 'dog', legs: 4}); + coll.insert({animal: 'echidna', legs: 4}); + coll.insert({animal: 'platypus', legs: 4}); + coll.insert({animal: 'starfish', legs: 5}); + + var affected = coll.update({legs: 4}, {$set: {category: 'quadruped'}}) + test.equal(affected, 1); + + //Changes only 3 but matched 4 documents + var affected = coll.update({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true}) + test.equal(affected, 4); + + //Again, changes nothing but returns nModified + var affected = coll.update({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true}) + test.equal(affected, 4); + + //upsert:true changes nothing, 4 modified + var affected = coll.update({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true, upsert:true}) + test.equal(affected, 4); + + //upsert method works as upsert:true + var result = coll.upsert({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true}) + test.equal(result.numberAffected, 4); + }); + + Tinytest.addAsync('mongo livedata - update/upsert callback returns nMatched as numberAffected', function (test, onComplete) { + var collName = Random.id(); + var coll = new Mongo.Collection('update_nmatched'+collName); + + coll.insert({animal: 'cat', legs: 4}); + coll.insert({animal: 'dog', legs: 4}); + coll.insert({animal: 'echidna', legs: 4}); + coll.insert({animal: 'platypus', legs: 4}); + coll.insert({animal: 'starfish', legs: 5}); + + var test1 = function () { + coll.update({legs: 4}, {$set: {category: 'quadruped'}}, function (err, result) { + test.equal(result, 1); + test2(); + }) + } + + var test2 = function () { + //Changes only 3 but matched 4 documents + coll.update({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true}, function (err, result) { + test.equal(result, 4); + test3(); + }); + } + + var test3 = function () { + //Again, changes nothing but returns nModified + coll.update({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true}, function (err, result) { + test.equal(result, 4); + test4(); + }); + } + + var test4 = function () { + //upsert:true changes nothing, 4 modified + coll.update({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true, upsert:true}, function (err, result) { + test.equal(result, 4); + test5(); + }); + } + + var test5 = function () { + //upsert method works as upsert:true + coll.upsert({legs: 4}, {$set: {category: 'quadruped'}}, {multi: true}, function (err, result) { + test.equal(result.numberAffected, 4); + onComplete(); + }); + } + + test1(); + }); +} diff --git a/packages/mongo/oplog_tailing.js b/packages/mongo/oplog_tailing.js index faa7712ad5..c4f3ddc237 100644 --- a/packages/mongo/oplog_tailing.js +++ b/packages/mongo/oplog_tailing.js @@ -207,12 +207,14 @@ _.extend(OplogHandle.prototype, { // Now, make sure that there actually is a repl set here. If not, oplog // tailing won't ever find anything! + // More on the isMasterDoc + // https://docs.mongodb.com/manual/reference/command/isMaster/ var f = new Future; self._oplogLastEntryConnection.db.admin().command( { ismaster: 1 }, f.resolver()); var isMasterDoc = f.wait(); - if (!(isMasterDoc && isMasterDoc.documents && isMasterDoc.documents[0] && - isMasterDoc.documents[0].setName)) { + + if (!(isMasterDoc && isMasterDoc.setName)) { throw Error("$MONGO_OPLOG_URL must be set to the 'local' database of " + "a Mongo replica set"); } @@ -321,5 +323,13 @@ _.extend(OplogHandle.prototype, { var sequencer = self._catchingUpFutures.shift(); sequencer.future.return(); } + }, + + //Methods used on tests to dinamically change TOO_FAR_BEHIND + _defineTooFarBehind: function(value) { + TOO_FAR_BEHIND = value; + }, + _resetTooFarBehind: function() { + TOO_FAR_BEHIND = process.env.METEOR_OPLOG_TOO_FAR_BEHIND || 2000; } }); diff --git a/packages/mongo/oplog_tests.js b/packages/mongo/oplog_tests.js index f41f437a23..4ea2958835 100644 --- a/packages/mongo/oplog_tests.js +++ b/packages/mongo/oplog_tests.js @@ -63,6 +63,14 @@ process.env.MONGO_OPLOG_URL && testAsyncMulti( // Fill collection with lots of irrelevant objects (red cats) and some // relevant ones (blue dogs). + + // After updating to mongo 3.2 with the 2.1.18 driver it was no longer + // possible to make this test fail with TOO_FAR_BEHIND = 2000. + // The documents waiting to be processed would hardly go beyond 1000 + // using mongo 3.2 with WiredTiger + MongoInternals.defaultRemoteCollectionDriver().mongo + ._oplogHandle._defineTooFarBehind(800); + self.IRRELEVANT_SIZE = 15000; self.RELEVANT_SIZE = 10; var docs = []; @@ -140,6 +148,10 @@ process.env.MONGO_OPLOG_URL && testAsyncMulti( var self = this; test.isTrue(self.skipped); + //This gets the TOO_FAR_BEHIND back to its initial value + MongoInternals.defaultRemoteCollectionDriver().mongo + ._oplogHandle._resetTooFarBehind(); + self.skipHandle.stop(); self.subHandle.stop(); self.collection.remove({}); diff --git a/packages/mongo/package.js b/packages/mongo/package.js index dbcfec4a04..34065c55ea 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.1.9_1' + version: '1.1.10' }); Npm.depends({ @@ -74,6 +74,7 @@ Package.onUse(function (api) { api.addFiles('local_collection_driver.js', ['client', 'server']); api.addFiles('remote_collection_driver.js', 'server'); api.addFiles('collection.js', ['client', 'server']); + api.addFiles('connection_options.js', 'server'); }); Package.onTest(function (api) { @@ -84,6 +85,7 @@ Package.onTest(function (api) { // XXX test order dependency: the allow_tests "partial allow" test // fails if it is run before mongo_livedata_tests. api.addFiles('mongo_livedata_tests.js', ['client', 'server']); + api.addFiles('upsert_compatibility_test.js', 'server'); api.addFiles('allow_tests.js', ['client', 'server']); api.addFiles('collection_tests.js', ['client', 'server']); api.addFiles('observe_changes_tests.js', ['client', 'server']); diff --git a/packages/mongo/upsert_compatibility_test.js b/packages/mongo/upsert_compatibility_test.js new file mode 100644 index 0000000000..4ed4c7e5a4 --- /dev/null +++ b/packages/mongo/upsert_compatibility_test.js @@ -0,0 +1,151 @@ +Tinytest.add('mongo livedata - native upsert - id type MONGO with MODIFIERS update', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'MONGO'}); + + coll.insert({foo: 1}); + var result = coll.upsert({foo: 1}, {$set: {foo:2}}); + var updated = coll.findOne({foo: 2}); + + test.equal(result.insertedId, undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(updated._id instanceof Mongo.ObjectID); + + delete updated['_id']; + test.equal(EJSON.equals(updated, {foo: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type MONGO with MODIFIERS insert', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'MONGO'}); + + var result = coll.upsert({foo: 1}, {$set: {bar:2}}); + var inserted = coll.findOne({foo: 1}); + + test.isTrue(result.insertedId !== undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(inserted._id instanceof Mongo.ObjectID); + test.equal(inserted._id, result.insertedId) + + delete inserted['_id']; + test.equal(EJSON.equals(inserted, {foo: 1, bar: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type MONGO PLAIN OBJECT update', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'MONGO'}); + + coll.insert({foo: 1, baz: 42}); + var result = coll.upsert({foo: 1}, {bar:2}); + var updated = coll.findOne({bar: 2}); + + test.isTrue(result.insertedId === undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(updated._id instanceof Mongo.ObjectID); + + delete updated['_id']; + test.equal(EJSON.equals(updated, {bar: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type MONGO PLAIN OBJECT insert', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'MONGO'}); + + var result = coll.upsert({foo: 1}, {bar:2}); + var inserted = coll.findOne({bar: 2}); + + test.isTrue(result.insertedId !== undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(inserted._id instanceof Mongo.ObjectID); + test.isTrue(result.insertedId instanceof Mongo.ObjectID); + test.equal(inserted._id, result.insertedId); + + delete inserted['_id']; + test.equal(EJSON.equals(inserted, {bar: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type STRING with MODIFIERS update', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'STRING'}); + + coll.insert({foo: 1}); + var result = coll.upsert({foo: 1}, {$set: {foo:2}}); + var updated = coll.findOne({foo: 2}); + + test.equal(result.insertedId, undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(typeof updated._id === 'string'); + + delete updated['_id']; + test.equal(EJSON.equals(updated, {foo: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type STRING with MODIFIERS insert', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'STRING'}); + + var result = coll.upsert({foo: 1}, {$set: {bar:2}}); + var inserted = coll.findOne({foo: 1}); + + test.isTrue(result.insertedId !== undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(typeof inserted._id === 'string'); + test.equal(inserted._id, result.insertedId); + + delete inserted['_id']; + test.equal(EJSON.equals(inserted, {foo: 1, bar: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type STRING PLAIN OBJECT update', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'STRING'}); + + coll.insert({foo: 1, baz: 42}); + var result = coll.upsert({foo: 1}, {bar:2}); + var updated = coll.findOne({bar: 2}); + + test.isTrue(result.insertedId === undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(typeof updated._id === 'string'); + + delete updated['_id']; + test.equal(EJSON.equals(updated, {bar: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - id type STRING PLAIN OBJECT insert', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'STRING'}); + + var result = coll.upsert({foo: 1}, {bar:2}); + var inserted = coll.findOne({bar: 2}); + + test.isTrue(result.insertedId !== undefined); + test.equal(result.numberAffected, 1); + + test.isTrue(typeof inserted._id === 'string'); + test.equal(inserted._id, result.insertedId); + + delete inserted['_id']; + test.equal(EJSON.equals(inserted, {bar: 2}), true); +}); + +Tinytest.add('mongo livedata - native upsert - MONGO passing id insert', function (test) { + var collName = Random.id(); + var coll = new Mongo.Collection('native_upsert_'+collName, {idGeneration: 'MONGO'}); + + var result = coll.upsert({foo: 1}, {_id: 'meu id'}); + var inserted = coll.findOne({_id: 'meu id'}); + + test.equal(result.insertedId, 'meu id'); + test.equal(result.numberAffected, 1); + + test.isTrue(typeof inserted._id === 'string'); + + test.equal(EJSON.equals(inserted, {_id: 'meu id'}), true); +}); diff --git a/packages/non-core/npm-bcrypt/.npm/package/npm-shrinkwrap.json b/packages/non-core/npm-bcrypt/.npm/package/npm-shrinkwrap.json index 3fe83751fc..9f8bfdb477 100644 --- a/packages/non-core/npm-bcrypt/.npm/package/npm-shrinkwrap.json +++ b/packages/non-core/npm-bcrypt/.npm/package/npm-shrinkwrap.json @@ -1,21 +1,19 @@ { "dependencies": { "bcrypt": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-0.8.6.tgz", - "from": "bcrypt@0.8.6", - "dependencies": { - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "from": "bindings@1.2.1" - }, - "nan": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.2.1.tgz", - "from": "nan@2.2.1" - } - } + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-0.8.7.tgz", + "from": "bcrypt@0.8.7" + }, + "bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "from": "bindings@1.2.1" + }, + "nan": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz", + "from": "nan@2.3.5" } } } diff --git a/packages/non-core/npm-bcrypt/.versions b/packages/non-core/npm-bcrypt/.versions index b96f61f81e..6697cb762c 100644 --- a/packages/non-core/npm-bcrypt/.versions +++ b/packages/non-core/npm-bcrypt/.versions @@ -1,3 +1,3 @@ meteor@1.1.16 -npm-bcrypt@0.8.6_3 +npm-bcrypt@0.8.7 underscore@1.0.9 diff --git a/packages/non-core/npm-bcrypt/package.js b/packages/non-core/npm-bcrypt/package.js index ff447db9ec..ecaa1f8af1 100644 --- a/packages/non-core/npm-bcrypt/package.js +++ b/packages/non-core/npm-bcrypt/package.js @@ -1,11 +1,11 @@ Package.describe({ summary: "Wrapper around the bcrypt npm package", - version: '0.8.6_3', + version: '0.8.7', documentation: null }); Npm.depends({ - bcrypt: '0.8.6' + bcrypt: '0.8.7' }); Package.onUse(function (api) { diff --git a/packages/non-core/npm-node-aes-gcm/.npm/package/npm-shrinkwrap.json b/packages/non-core/npm-node-aes-gcm/.npm/package/npm-shrinkwrap.json index 555c3cca84..eb10313104 100644 --- a/packages/non-core/npm-node-aes-gcm/.npm/package/npm-shrinkwrap.json +++ b/packages/non-core/npm-node-aes-gcm/.npm/package/npm-shrinkwrap.json @@ -1,14 +1,21 @@ { "dependencies": { - "node-aes-gcm": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/node-aes-gcm/-/node-aes-gcm-0.1.5.tgz", - "from": "node-aes-gcm@0.1.5", + "meteor-node-aes-gcm": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/meteor-node-aes-gcm/-/meteor-node-aes-gcm-0.1.7.tgz", + "from": "meteor-node-aes-gcm@0.1.7", "dependencies": { - "nan": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-1.9.0.tgz", - "from": "nan@>=1.7.0 <2.0.0" + "node-aes-gcm": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/node-aes-gcm/-/node-aes-gcm-0.1.7.tgz", + "from": "node-aes-gcm@0.1.7", + "dependencies": { + "nan": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.3.tgz", + "from": "nan@>=2.3.0 <2.4.0" + } + } } } } diff --git a/packages/non-core/npm-node-aes-gcm/package.js b/packages/non-core/npm-node-aes-gcm/package.js index 54237d224d..20a82e1adc 100644 --- a/packages/non-core/npm-node-aes-gcm/package.js +++ b/packages/non-core/npm-node-aes-gcm/package.js @@ -1,14 +1,15 @@ Package.describe({ summary: "Wrapper around the node-aes-gcm npm package", - version: '0.1.5_2', + version: '0.1.7_4', documentation: null }); Npm.depends({ - 'node-aes-gcm': '0.1.5' + 'meteor-node-aes-gcm': '0.1.7' }); Package.onUse(function (api) { + api.use("modules@0.6.1"); api.export('NpmModuleNodeAesGcm', 'server'); api.addFiles('wrapper.js', 'server'); }); diff --git a/packages/non-core/npm-node-aes-gcm/wrapper.js b/packages/non-core/npm-node-aes-gcm/wrapper.js index 252d8c612d..9e944ded31 100644 --- a/packages/non-core/npm-node-aes-gcm/wrapper.js +++ b/packages/non-core/npm-node-aes-gcm/wrapper.js @@ -1,14 +1,14 @@ try { - NpmModuleNodeAesGcm = Npm.require('node-aes-gcm'); + NpmModuleNodeAesGcm = require('meteor-node-aes-gcm'); } catch (err) { if (process.platform === "win32" && err.message.match(/specified module could not be found/)) { // the user probably doesn't have OpenSSL installed. throw new Error( -"Couldn't load the package 'npm-node-aes-gcm'. This is probably because you " + +"Couldn't load the package 'meteor-node-aes-gcm'. This is probably because you " + "don't have OpenSSL installed. See the README for details and directions: " + "https://github.com/meteor/meteor/blob/devel/packages/non-core/npm-node-aes-gcm/README.md"); } else { throw err; } -} \ No newline at end of file +} diff --git a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json index eba8926eec..e327314325 100644 --- a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json +++ b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json @@ -1,60 +1,64 @@ { "dependencies": { + "bson": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.2.tgz", + "from": "bson@>=0.5.1 <0.6.0" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0" + }, + "es6-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "from": "es6-promise@3.0.2" + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1" + }, "mongodb": { - "version": "1.4.39", - "resolved": "https://github.com/meteor/node-mongodb-native/tarball/9c7441e87fbec059dc0b70bbb70734404b994d71", - "from": "https://github.com/meteor/node-mongodb-native/tarball/9c7441e87fbec059dc0b70bbb70734404b994d71", - "dependencies": { - "bson": { - "version": "0.2.18", - "resolved": "https://github.com/meteor/js-bson/tarball/0103b53", - "from": "https://github.com/meteor/js-bson/tarball/0103b53", - "dependencies": { - "nan": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.1.tgz", - "from": "https://registry.npmjs.org/nan/-/nan-1.5.1.tgz" - } - } - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "process-nextick-args": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz", - "from": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - } - } - } + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.4.tgz", + "from": "mongodb@2.2.4" + }, + "mongodb-core": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.0.6.tgz", + "from": "mongodb-core@2.0.6" + }, + "readable-stream": { + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz", + "from": "readable-stream@1.0.31" + }, + "require_optional": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", + "from": "require_optional@>=1.0.0 <1.1.0" + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "from": "resolve-from@>=2.0.0 <3.0.0" + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "from": "semver@>=5.1.0 <6.0.0" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0" } } } diff --git a/packages/npm-mongo/package.js b/packages/npm-mongo/package.js index 559ab34995..92c312d7fe 100644 --- a/packages/npm-mongo/package.js +++ b/packages/npm-mongo/package.js @@ -3,17 +3,12 @@ Package.describe({ summary: "Wrapper around the mongo npm package", - version: '1.4.45', + version: '1.5.45', documentation: null }); Npm.depends({ - // 1.4.32 (and bson 0.2.18) with optional native dependencies (bson native - // piece and kerberos) ripped out, which means we don't have to do the - // publish-for-arch dance every time we make a Meteor release. - // XXX move the npm dependency into a non-core versioned package and allow - // it to use C++ bson - mongodb: "https://github.com/meteor/node-mongodb-native/tarball/9c7441e87fbec059dc0b70bbb70734404b994d71" + mongodb: "2.2.4" }); Package.onUse(function (api) { diff --git a/packages/oauth-encryption/package.js b/packages/oauth-encryption/package.js index 903ad21af3..14609f0702 100644 --- a/packages/oauth-encryption/package.js +++ b/packages/oauth-encryption/package.js @@ -1,10 +1,10 @@ Package.describe({ summary: "Encrypt account secrets stored in the database", - version: '1.0.13' + version: '1.1.13' }); Package.onUse(function (api) { - api.use("npm-node-aes-gcm@=0.1.5_2"); + api.use("npm-node-aes-gcm@=0.1.7_4"); api.export("OAuthEncryption", ["server"]); api.use([ diff --git a/packages/promise/package.js b/packages/promise/package.js index 393536ed51..a808ffae15 100644 --- a/packages/promise/package.js +++ b/packages/promise/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "promise", - version: "0.7.3", + version: "0.8.3", summary: "ECMAScript 2015 Promise polyfill with Fiber support", git: "https://github.com/meteor/promise", documentation: "README.md" diff --git a/packages/standard-minifier-css/package.js b/packages/standard-minifier-css/package.js index 3114cfa5e1..fc4129ed43 100644 --- a/packages/standard-minifier-css/package.js +++ b/packages/standard-minifier-css/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'standard-minifier-css', - version: '1.0.8', + version: '1.1.8', summary: 'Standard css minifier used with Meteor apps by default.', documentation: 'README.md' }); diff --git a/packages/standard-minifier-js/package.js b/packages/standard-minifier-js/package.js index fc610cd720..dcab86536c 100644 --- a/packages/standard-minifier-js/package.js +++ b/packages/standard-minifier-js/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'standard-minifier-js', - version: '1.0.8', + version: '1.1.8', summary: 'Standard javascript minifiers used with Meteor apps by default.', documentation: 'README.md' }); diff --git a/packages/static-html/package.js b/packages/static-html/package.js index c3c6da10bc..e8df227b46 100644 --- a/packages/static-html/package.js +++ b/packages/static-html/package.js @@ -1,5 +1,5 @@ Package.describe({ - version: '1.0.12', + version: '1.1.11', // Brief, one-line summary of the package. summary: 'Define static page content in .html files', git: 'https://github.com/meteor/meteor', diff --git a/packages/stylus/package.js b/packages/stylus/package.js index 2659367086..27946df7ac 100644 --- a/packages/stylus/package.js +++ b/packages/stylus/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Expressive, dynamic, robust CSS', - version: "2.512.5" + version: "2.513.4" }); Package.registerBuildPlugin({ diff --git a/packages/templating/package.js b/packages/templating/package.js index 1d76bc583c..31a8133d11 100644 --- a/packages/templating/package.js +++ b/packages/templating/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Allows templates to be defined in .html files", - version: '1.1.14' + version: '1.2.13' }); // Today, this package is closely intertwined with Handlebars, meaning diff --git a/packages/test-in-console/run.sh b/packages/test-in-console/run.sh index 4fe7da73ab..c1922dd9d1 100755 --- a/packages/test-in-console/run.sh +++ b/packages/test-in-console/run.sh @@ -10,7 +10,7 @@ export PATH=$METEOR_HOME:$PATH export URL='http://localhost:4096/' -exec 3< <(meteor test-packages --driver-package test-in-console -p 4096 --exclude $TEST_PACKAGES_EXCLUDE) +exec 3< <(meteor test-packages --driver-package test-in-console -p 4096 --exclude ${TEST_PACKAGES_EXCLUDE:-''}) EXEC_PID=$! sed '/test-in-console listening$/q' <&3 diff --git a/packages/tracker/package.js b/packages/tracker/package.js index c6e212a092..56a3709ffe 100644 --- a/packages/tracker/package.js +++ b/packages/tracker/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Dependency tracker to allow reactive callbacks", - version: '1.0.15' + version: '1.1.0' }); Package.onUse(function (api) { diff --git a/packages/twitter/package.js b/packages/twitter/package.js index 0c461ddbe4..4acf8c0b2e 100644 --- a/packages/twitter/package.js +++ b/packages/twitter/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Twitter OAuth flow", - version: '1.1.11' + version: '1.1.12' }); Package.onUse(function(api) { diff --git a/packages/webapp/package.js b/packages/webapp/package.js index 13aabb0067..5675570b12 100644 --- a/packages/webapp/package.js +++ b/packages/webapp/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Serves a Meteor app over HTTP", - version: '1.2.11' + version: '1.3.10' }); Npm.depends({connect: "2.30.2", diff --git a/packages/webapp/webapp_server.js b/packages/webapp/webapp_server.js index 4b82478825..3718a4bea3 100644 --- a/packages/webapp/webapp_server.js +++ b/packages/webapp/webapp_server.js @@ -222,8 +222,10 @@ WebApp._timeoutAdjustmentRequestCallback = function (req, res) { // Insert our new finish listener to run BEFORE the existing one which removes // the response from the socket. var finishListeners = res.listeners('finish'); - // XXX Apparently in Node 0.12 this event is now called 'prefinish'. + // XXX Apparently in Node 0.12 this event was called 'prefinish'. // https://github.com/joyent/node/commit/7c9b6070 + // But it has switched back to 'finish' in Node v4: + // https://github.com/nodejs/node/pull/1411 res.removeAllListeners('finish'); res.on('finish', function () { res.setTimeout(SHORT_SOCKET_TIMEOUT); diff --git a/packages/xmlbuilder/package.js b/packages/xmlbuilder/package.js index 36bcd5edb7..619eabb6ba 100644 --- a/packages/xmlbuilder/package.js +++ b/packages/xmlbuilder/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "An XML builder for node.js similar to java-xmlbuilder.", - version: '2.4.13' + version: '2.5.13' }); Npm.depends({ diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index d4966b2786..56fb5520a2 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.3.5.1-rc.1", + "version": "1.4-rc.2", "recommended": false, "official": false, "description": "Meteor" diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index f34a1073bc..996cb5ecf3 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.3.5.1", + "version": "1.4", "recommended": false, "official": true, "description": "The Official Meteor Distribution" diff --git a/scripts/admin/test-packages-with-mongo-versions.rb b/scripts/admin/test-packages-with-mongo-versions.rb index 959b5eb80e..6343991281 100755 --- a/scripts/admin/test-packages-with-mongo-versions.rb +++ b/scripts/admin/test-packages-with-mongo-versions.rb @@ -7,6 +7,7 @@ require 'tmpdir' mongo_install_urls = { + "3.2.6" => "https://fastdl.mongodb.org/osx/mongodb-osx-x86_64-3.2.6.tgz", "3.0.5" => "https://fastdl.mongodb.org/osx/mongodb-osx-x86_64-3.0.5.tgz", "2.6.10" => "http://downloads.mongodb.org/osx/mongodb-osx-x86_64-2.6.10.tgz", "2.4.14" => "http://downloads.mongodb.org/osx/mongodb-osx-x86_64-2.4.14.tgz" @@ -16,15 +17,19 @@ mongo_port = "12345" dirname = File.dirname(__FILE__) path_to_test_in_console = File.realpath File.join dirname, "..", "..", "packages", "test-in-console", "run.sh" -path_to_output = File.realpath File.join dirname, "..", "..", "mongo-test-output" +path_to_output = File.join dirname, "..", "..", "mongo-test-output" -unless Dir[path_to_output] +unless Dir[path_to_output] != [] Dir.mkdir path_to_output end +path_to_output = File.realpath path_to_output + puts "Putting output in: #{path_to_output}/" -["3.0.5", "2.6.10", "2.4.14"].each do |mongo_version| +test_env = "TEST_PACKAGES_EXCLUDE=\"less\"" + +["3.2.6", "3.0.5", "2.6.10", "2.4.14"].each do |mongo_version| puts "Installing and testing with Mongo #{mongo_version}..." Dir.mktmpdir "mongo_install" do |mongo_install_dir| @@ -43,7 +48,7 @@ puts "Putting output in: #{path_to_output}/" puts "Running test-in-console from: #{path_to_test_in_console}" puts "Passing #{mongo_env}" - `#{mongo_env} bash #{path_to_test_in_console} > #{path_to_output}/#{mongo_version}.txt` + `#{test_env} #{mongo_env} bash #{path_to_test_in_console} > #{path_to_output}/#{mongo_version}.txt` # Kill Mongo Process.kill "TERM", pid diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index de8c8b9576..325f6f4994 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -5,7 +5,8 @@ set -u UNAME=$(uname) ARCH=$(uname -m) -NODE_VERSION=0.10.46 +MONGO_VERSION=3.2.6 +NODE_VERSION=4.4.7 NPM_VERSION=3.10.5 if [ "$UNAME" == "Linux" ] ; then diff --git a/scripts/build-mongo-for-dev-bundle.sh b/scripts/build-mongo-for-dev-bundle.sh deleted file mode 100755 index 4d47ec7d23..0000000000 --- a/scripts/build-mongo-for-dev-bundle.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -u - -MONGO_VERSION="2.6.7" - -source "$(dirname $0)/build-dev-bundle-common.sh" -echo CHECKOUT DIR IS "$CHECKOUT_DIR" -echo BUILDING MONGO "v$MONGO_VERSION" IN "$DIR" - -# Checkout and build mongodb. -# We want to build a binary that includes SSL support but does not depend on a -# particular version of openssl on the host system. - -OPENSSL="openssl-1.0.2" -OPENSSL_URL="http://www.openssl.org/source/$OPENSSL.tar.gz" -wget $OPENSSL_URL || curl -O $OPENSSL_URL -tar xzf $OPENSSL.tar.gz - -cd $OPENSSL -if [ "$UNAME" == "Linux" ]; then - ./config --prefix="$DIR/build/openssl-out" no-shared -else - # This configuration line is taken from Homebrew formula: - # https://github.com/mxcl/homebrew/blob/master/Library/Formula/openssl.rb - ./Configure no-shared zlib-dynamic --prefix="$DIR/build/openssl-out" darwin64-x86_64-cc enable-ec_nistp_64_gcc_128 -fi -make install - -# To see the mongo changelog, go to http://www.mongodb.org/downloads, -# click 'changelog' under the current version, then 'release notes' in -# the upper right. -cd "$DIR/build" - -# We use Meteor fork since we added some changes to the building script. -# Our patches allow us to link most of the libraries statically. -git clone --branch "ssl-r$MONGO_VERSION" --depth 1 \ - git://github.com/meteor/mongo.git -cd mongo -rm -rf .git - -# Compile - -MONGO_FLAGS="--ssl --release -j4 " -MONGO_FLAGS+="--cpppath=$DIR/build/openssl-out/include --libpath=$DIR/build/openssl-out/lib " - -if [ "$OS" == "osx" ]; then - # NOTE: '--64' option breaks the compilation, even it is on by default on x64 mac: https://jira.mongodb.org/browse/SERVER-5575 - MONGO_FLAGS+="--openssl=$DIR/build/openssl-out/lib " - /usr/local/bin/scons $MONGO_FLAGS mongo mongod -elif [ "$OS" == "linux" ]; then - MONGO_FLAGS+="--no-glibc-check --prefix=./ " - if [ "$ARCH" == "x86_64" ]; then - MONGO_FLAGS+="--64" - fi - scons $MONGO_FLAGS mongo mongod -else - echo "We don't know how to compile mongo for this platform" - exit 1 -fi - -echo "Done with scons build" - -# Copy binaries -mkdir -p "$DIR/mongodb/bin" -cp mongo "$DIR/mongodb/bin/" -cp mongod "$DIR/mongodb/bin/" - -# Copy mongodb distribution information -find ./distsrc -maxdepth 1 -type f -exec cp '{}' ../mongodb \; - -cd "$DIR" -stripBinary mongodb/bin/mongo -stripBinary mongodb/bin/mongod - -echo BUNDLING - -cd "$DIR" -rm -rf build -tar czvf "${CHECKOUT_DIR}/mongo_${PLATFORM}_v${MONGO_VERSION}.tar.gz" . - -echo DONE diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 34db09a6b3..0649543971 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -29,12 +29,12 @@ var packageJson = { "source-map-support": "https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e", semver: "4.1.0", request: "2.47.0", - fstream: "https://github.com/meteor/fstream/tarball/d11b9ec4a13918447c8af7559c243c190744dd1c", + fstream: "https://github.com/meteor/fstream/tarball/cf4ea6c175355cec7bee38311e170d08c4078a5d", tar: "1.0.2", kexec: "2.0.2", "source-map": "0.5.3", "browserstack-webdriver": "2.41.1", - "node-inspector": "0.7.4", + "node-inspector": "0.12.8", chalk: "0.5.1", sqlite3: "3.1.3", netroute: "1.0.2", diff --git a/scripts/generate-dev-bundle.ps1 b/scripts/generate-dev-bundle.ps1 index 7ff52c3313..704e35c2f5 100644 --- a/scripts/generate-dev-bundle.ps1 +++ b/scripts/generate-dev-bundle.ps1 @@ -1,8 +1,8 @@ # determine the platform # use 32bit by default $PLATFORM = "windows_x86" -$MONGO_VERSION = "2.6.7" -$NODE_VERSION = "0.10.46" +$MONGO_VERSION = "3.2.6" +$NODE_VERSION = "4.4.7" $NPM_VERSION = "3.10.5" $PYTHON_VERSION = "2.7.10" # For node-gyp @@ -37,7 +37,7 @@ $shell = New-Object -com shell.application # download node # same node on 32bit vs 64bit? -$node_link = "http://nodejs.org/dist/v${NODE_VERSION}/node.exe" +$node_link = "http://nodejs.org/dist/v${NODE_VERSION}/win-x86/node.exe" $webclient.DownloadFile($node_link, "$DIR\bin\node.exe") # On Windows we provide a reliable version of python.exe for use by @@ -67,6 +67,10 @@ rm -Recurse -Force $npm_zip # add bin to the front of the path so we can use our own node for building $env:PATH = "${DIR}\bin;${env:PATH}" +# Make sure node-gyp knows how to find its build tools. +$env:PYTHON = "${DIR}\python\python.exe" +$env:GYP_MSVS_VERSION = "2015" + # Install the version of npm that we're actually going to expose from the # dev bundle. Note that we use npm@1.4.12 to install npm@${NPM_VERSION}. cd "${DIR}\lib" @@ -145,8 +149,8 @@ cd "$DIR\.." # rename the folder with the devbundle cmd /c rename "$DIR" "dev_bundle_${PLATFORM}_${BUNDLE_VERSION}" -cmd /c 7z.exe a -ttar dev_bundle.tar "dev_bundle_${PLATFORM}_${BUNDLE_VERSION}" -cmd /c 7z.exe a -tgzip "${CHECKOUT_DIR}\dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz" dev_bundle.tar +& "C:\Program Files*\7-zip\7z.exe" a -ttar dev_bundle.tar "dev_bundle_${PLATFORM}_${BUNDLE_VERSION}" +& "C:\Program Files*\7-zip\7z.exe" a -tgzip "${CHECKOUT_DIR}\dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz" dev_bundle.tar del dev_bundle.tar cmd /c rmdir "dev_bundle_${PLATFORM}_${BUNDLE_VERSION}" /s /q diff --git a/scripts/generate-dev-bundle.sh b/scripts/generate-dev-bundle.sh index 3d55b7e6a9..099a4a971d 100755 --- a/scripts/generate-dev-bundle.sh +++ b/scripts/generate-dev-bundle.sh @@ -24,18 +24,18 @@ NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_TGZ}" echo "Downloading Node from ${NODE_URL}" curl "${NODE_URL}" | tar zx --strip-components 1 -# Update these values after building the dev-bundle-mongo Jenkins project. -# Also make sure to update MONGO_VERSION in generate-dev-bundle.ps1. -MONGO_VERSION=2.6.7 -MONGO_BUILD_NUMBER=6 -MONGO_TGZ="mongo_${PLATFORM}_v${MONGO_VERSION}.tar.gz" -if [ -f "${CHECKOUT_DIR}/${MONGO_TGZ}" ] ; then - tar zxf "${CHECKOUT_DIR}/${MONGO_TGZ}" -else - MONGO_URL="https://${S3_HOST}/dev-bundle-mongo-${MONGO_BUILD_NUMBER}/${MONGO_TGZ}" - echo "Downloading Mongo from ${MONGO_URL}" - curl "${MONGO_URL}" | tar zx -fi +# Download Mongo from mongodb.com +MONGO_NAME="mongodb-${OS}-${ARCH}-${MONGO_VERSION}" +MONGO_TGZ="${MONGO_NAME}.tgz" +MONGO_URL="http://fastdl.mongodb.org/${OS}/${MONGO_TGZ}" +echo "Downloading Mongo from ${MONGO_URL}" +curl "${MONGO_URL}" | tar zx + +# Put Mongo binaries in the right spot (mongodb/bin) +mkdir -p mongodb/bin +mv "${MONGO_NAME}/bin/mongod" mongodb/bin +mv "${MONGO_NAME}/bin/mongo" mongodb/bin +rm -rf "${MONGO_NAME}" # export path so we use the downloaded node and npm export PATH="$DIR/bin:$PATH" diff --git a/tools/PERFORMANCE.md b/tools/PERFORMANCE.md index 36e6c2af74..7a8864bd84 100644 --- a/tools/PERFORMANCE.md +++ b/tools/PERFORMANCE.md @@ -213,9 +213,11 @@ the top level (probably because they are fired off asynchronously). Some initial work has been done to make constraint solving fast in the typical case where a previous solution exists in `APP/.meteor/versions`, but there is -possible room for improvement. For example, the previous solution could be -checked without invoking the logic solver at all, though the manual logic would -have to match closely. +possible room for improvement. + +For example, the previous solution could be checked without +invoking the logic solver at all, though the manual logic would have to +match closely. [Implemented](https://github.com/meteor/meteor/compare/ea236fc9da99a1679b6205dce3a7008617e660e5...69b100d21a33fd7ca58fc2fe2d8997ade4a36af6)! Time spent reading from the packages database (a SQLite file) could be understood better and improved by batching queries, reading less data, or using SQLite diff --git a/tools/cli/commands-packages.js b/tools/cli/commands-packages.js index 7339364972..701ebbd4d7 100644 --- a/tools/cli/commands-packages.js +++ b/tools/cli/commands-packages.js @@ -1408,10 +1408,12 @@ var maybeUpdateRelease = function (options) { // mention that fact. // XXX error handling. - // Figuring out which release to use to update the app is slightly more - // complicated, because we have to run the constraint solver. So, we need to - // try multiple releases, defined by the various options passed in. - var releaseVersionsToTry; + // Previously we attempted to figure out the newest release that is compatible + // with the users non-core version constraints. Now we simply update them + // to the newest and if they get a conflict, they are left with a + // .meteor/packages to work on to get a resolution (with more useful info) + + var releaseVersion; if (options.patch) { // Can't make a patch update if you are not running from a current // release. In fact, you are doing something wrong, so we should tell you @@ -1451,20 +1453,20 @@ var maybeUpdateRelease = function (options) { } // Great, we found a patch version. You can only have one latest patch for // a string of releases, so there is just one release to try. - releaseVersionsToTry = [updateTo]; + releaseVersion = updateTo; } else if (release.explicit) { // You have explicitly specified a release, and we have springboarded to // it. So, we will use that release to update you to itself, if we can. - releaseVersionsToTry = [release.current.getReleaseVersion()]; + releaseVersion = release.current.getReleaseVersion(); } else { // We are not doing a patch update, or a specific release update, so we need // to try all recommended releases on our track, whose order key is greater // than the app's. - releaseVersionsToTry = getLaterReleaseVersions( + releaseVersion = getLaterReleaseVersions( projectContext.releaseFile.releaseTrack, - projectContext.releaseFile.releaseVersion); + projectContext.releaseFile.releaseVersion)[0]; - if (! releaseVersionsToTry.length) { + if (! releaseVersion) { // We could not find any releases newer than the one that we are on, on // that track, so we are done. Console.info( @@ -1475,48 +1477,7 @@ var maybeUpdateRelease = function (options) { } } - var didPrintMessages = false; - var solutionReleaseVersion = _.find(releaseVersionsToTry, function (versionToTry) { - var releaseRecord = catalog.official.getReleaseVersion( - releaseTrack, versionToTry); - if (!releaseRecord) { - throw Error("missing release record?"); - } - - // Reset the project context and pretend we're using the potential release. - projectContext.reset({ releaseForConstraints: releaseRecord }); - var messages = buildmessage.capture(function () { - projectContext.resolveConstraints(); - }); - if (messages.hasMessages()) { - // To avoid overloading the user, we only print messages for the first - // release version we try (which should be the latest) - if (!didPrintMessages) { - Console.info( - "Update to release", releaseTrack + "@" + versionToTry, - "is impossible:"); - Console.info(messages.formatMessages()); - didPrintMessages = true; - } - // Nope, this release didn't work. - return false; - } - - // Yay, it worked! - return true; - }); - - var newerAvailable = false; - if (! solutionReleaseVersion) { - Console.info( - "This project is at the latest release which is compatible with your " + - "current package constraints."); - return 0; - } else if (solutionReleaseVersion !== releaseVersionsToTry[0]) { - newerAvailable = true; - } - - var solutionReleaseName = releaseTrack + '@' + solutionReleaseVersion; + var releaseName = `${releaseTrack}@${releaseVersion}`; // We could at this point springboard to solutionRelease (which is no newer // than the release we are currently running), but there's no super-clear @@ -1527,6 +1488,11 @@ var maybeUpdateRelease = function (options) { var upgraders = require('../upgraders.js'); var upgradersToRun = upgraders.upgradersToRun(projectContext); + // Update every package in .meteor/packages to be (semver)>= the version + // set for that package in the release we are updating to + var releaseRecord = catalog.official.getReleaseVersion(releaseTrack, releaseVersion); + projectContext.projectConstraintsFile.updateReleaseConstraints(releaseRecord); + // Download and build packages and write the new versions to .meteor/versions. // XXX It's a little weird that we do a full preparation for build // (downloading packages, building packages, etc) when we might be about @@ -1537,7 +1503,7 @@ var maybeUpdateRelease = function (options) { projectContext.prepareProjectForBuild(); }); - projectContext.writeReleaseFileAndDevBundleLink(solutionReleaseName); + projectContext.writeReleaseFileAndDevBundleLink(releaseName); projectContext.packageMapDelta.displayOnConsole({ title: ("Changes to your project's package version selections from " + @@ -1546,11 +1512,6 @@ var maybeUpdateRelease = function (options) { Console.info(files.pathBasename(options.appDir) + ": updated to " + projectContext.releaseFile.displayReleaseName + "."); - if (newerAvailable) { - Console.info( - "(Newer releases are available but are not compatible with your " + - "current package constraints.)"); - } // Now run the upgraders. // XXX should we also run upgraders on other random commands, in case there @@ -1653,27 +1614,9 @@ main.registerCommand({ } else { upgradePackageNames = options.args; } - // We want to use the project's release for constraints even if we are - // currently running a newer release (eg if we ran 'meteor update --patch' and - // updated to an older patch release). (If the project has release 'none' - // because this is just 'updating packages', this can be null. Also, if we're - // running from a checkout this should be null even if the file doesn't say - // 'none'.) - var releaseRecordForConstraints = null; - if (!files.inCheckout() - && projectContext.releaseFile.normalReleaseSpecified()) { - releaseRecordForConstraints = catalog.official.getReleaseVersion( - projectContext.releaseFile.releaseTrack, - projectContext.releaseFile.releaseVersion); - if (! releaseRecordForConstraints) { - throw Error("unknown release " + - projectContext.releaseFile.displayReleaseName); - } - } // Try to resolve constraints, allowing the given packages to be upgraded. projectContext.reset({ - releaseForConstraints: releaseRecordForConstraints, upgradePackageNames: upgradePackageNames, upgradeIndirectDepPatchVersions: upgradeIndirectDepPatchVersions }); @@ -1721,21 +1664,9 @@ main.registerCommand({ topLevelPkgSet[constraint.package] = true; }); - var releaseConstrainedPkgSet = {}; // pinned core packages (to skip) - // check releaseRecordForConstraints is not null, e.g. possible - // when running meteor from checkout - if (releaseRecordForConstraints) { - _.each(releaseRecordForConstraints.packages, function (v, packageName) { - releaseConstrainedPkgSet[packageName] = true; - }); - } - var nonlatestDirectDeps = []; var nonlatestIndirectDeps = []; projectContext.packageMap.eachPackage(function (name, info) { - if (_.has(releaseConstrainedPkgSet, name)) { - return; - } var selectedVersion = info.version; var catalog = projectContext.projectCatalog; var latestVersion = getNewerVersion(name, selectedVersion, catalog); diff --git a/tools/cli/commands.js b/tools/cli/commands.js index a086304c65..87473a5777 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -325,6 +325,14 @@ function doRunCommand(options) { appPort = appPortMatch[2] ? parseInt(appPortMatch[2]) : null; } + if (options.production) { + Console.warn( + "Warning: The --production flag should only be used to simulate production " + + "bundling for testing purposes. Use meteor build to create a bundle for " + + "production deployment. See: https://guide.meteor.com/deployment.html" + ); + } + if (options['raw-logs']) { runLog.setRawLogs(true); } @@ -703,6 +711,15 @@ main.registerCommand({ return; } + // Also, write package version constraints from the current release + // If we are on a checkout, we don't need to do this as running from + // checkout still pins all package versions and if the user updates + // to a real release, the packages file will subsequently get updated + if (!release.current.isCheckout()) { + projectContext.projectConstraintsFile + .updateReleaseConstraints(release.current._manifest); + } + // Any upgrader that is in this version of Meteor doesn't need to be run on // this project. var upgraders = require('../upgraders.js'); diff --git a/tools/cli/example-repositories.js b/tools/cli/example-repositories.js index b4354be208..42b9b4a16a 100644 --- a/tools/cli/example-repositories.js +++ b/tools/cli/example-repositories.js @@ -14,4 +14,7 @@ export const EXAMPLE_REPOSITORIES = { 'repo': 'https://github.com/meteor/todos', 'branch': 'react', }, + 'angular2-boilerplate': { + repo: 'https://github.com/bsliran/angular2-meteor-base' + } }; diff --git a/tools/inspector.js b/tools/inspector.js index f9f625ab80..b4265c8b72 100644 --- a/tools/inspector.js +++ b/tools/inspector.js @@ -145,7 +145,7 @@ DEp.connectToChildProcess = function connectToChildProcess(child) { // port (not debugPort!), and create a connection to that port so that // the child process can communicate with node-inspector. child.stderr.on("data", function onData(buffer) { - var match = /debugger listening on port (\d+)/ + var match = /debugger listening on port (\d+)/i .exec(buffer.toString("utf8")); if (match) { child.stderr.removeListener("data", onData); diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index e17912a591..8e22ba6375 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -59,7 +59,7 @@ import { isTestFilePath } from './test-files.js'; // Cache the (slightly post-processed) results of linker.fullLink. const CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100; const CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG; -const LINKER_CACHE_SALT = 8; // Increment this number to force relinking. +const LINKER_CACHE_SALT = 9; // Increment this number to force relinking. const LINKER_CACHE = new LRU({ max: CACHE_SIZE, // Cache is measured in bytes. We don't care about servePath. diff --git a/tools/isobuild/compiler.js b/tools/isobuild/compiler.js index 58bb8ebf34..9d9e9b632c 100644 --- a/tools/isobuild/compiler.js +++ b/tools/isobuild/compiler.js @@ -29,7 +29,7 @@ var compiler = exports; // dependencies. (At least for now, packages only used in target creation (eg // minifiers) don't require you to update BUILT_BY, though you will need to quit // and rerun "meteor run".) -compiler.BUILT_BY = 'meteor/21'; +compiler.BUILT_BY = 'meteor/22'; // This is a list of all possible architectures that a build can target. (Client // is expanded into 'web.browser' and 'web.cordova') diff --git a/tools/isobuild/isopack.js b/tools/isobuild/isopack.js index 2c15ff6f2f..ce98fba763 100644 --- a/tools/isobuild/isopack.js +++ b/tools/isobuild/isopack.js @@ -1621,6 +1621,19 @@ _.extend(Isopack.prototype, { servePath: prelinkFile.servePath || undefined }; if (prelinkFile.sourceMap) { + // It appears in node v0.10.x, `new Buffer({someobject: 1})` + // would be silently swallowed. (leaving an empty buffer) + // In node v4+ this same code throws an error. + // XX - Not 100% sure what prelinkFile.sourceMap _can_ be, + // so here's some exhaustive checking of things buffer + // _will_ accept. + var acceptedByBuffer = _.isString(prelinkFile.sourceMap) + || _.isNumber(prelinkFile.sourceMap) + || _.isArray(prelinkFile.sourceMap) + || (prelinkFile.sourceMap instanceof Buffer); + if (!acceptedByBuffer) { + prelinkFile.sourceMap = JSON.stringify(prelinkFile.sourceMap); + } // Write the source map. if (typeof prelinkFile.sourceMap !== "string") { diff --git a/tools/project-context.js b/tools/project-context.js index 341f3d8343..9dfde085d6 100644 --- a/tools/project-context.js +++ b/tools/project-context.js @@ -60,8 +60,7 @@ var STAGE = { _.extend(ProjectContext.prototype, { reset: function (moreOptions, resetOptions) { var self = this; - // Allow overriding some options until the next call to reset; used by - // 'meteor update' code to try various values of releaseForConstraints. + // Allow overriding some options until the next call to reset; var options = _.extend({}, self.originalOptions, moreOptions); // This is options that are actually directed at reset itself. resetOptions = resetOptions || {}; @@ -142,21 +141,6 @@ _.extend(ProjectContext.prototype, { // to using the web.browser slice instead or make a common 'web' slice). self._forceIncludeCordovaUnibuild = options.forceIncludeCordovaUnibuild; - // If explicitly specified as null, use no release for constraints. - // If specified non-null, should be a release version catalog record. - // If not specified, defaults to release.current. - // - // Note that NONE of these cases are "use the release from - // self.releaseFile"; after all, if you are explicitly running `meteor - // --release foo` it will override what is found in .meteor/releases. - if (_.has(options, 'releaseForConstraints')) { - self._releaseForConstraints = options.releaseForConstraints || null; - } else if (release.current.isCheckout()) { - self._releaseForConstraints = null; - } else { - self._releaseForConstraints = release.current.getCatalogReleaseData(); - } - if (resetOptions.preservePackageMap && self.packageMap) { self._cachedVersionsBeforeReset = self.packageMap.toVersionMap(); // packageMapFile should always exist if packageMap does @@ -386,19 +370,8 @@ _.extend(ProjectContext.prototype, { // Let's also make sure we have a minimal gitignore. var gitignorePath = files.pathJoin(self.projectDir, '.meteor', '.gitignore'); - try { - var lines = files.readFile(gitignorePath, "utf8").split("\n"); - } catch (e) { - if (e.code !== "ENOENT") throw e; - lines = [""]; - } - - var needLocal = lines.indexOf("local") < 0; - var needDevBundle = lines.indexOf("dev_bundle") < 0; - if (needDevBundle || needLocal) { - if (needDevBundle) lines.unshift("dev_bundle"); - if (needLocal) lines.unshift("local"); - files.writeFileAtomically(gitignorePath, lines.join("\n")); + if (! files.exists(gitignorePath)) { + files.writeFileAtomically(gitignorePath, 'local\n'); } }, @@ -690,7 +663,6 @@ _.extend(ProjectContext.prototype, { self._addAppConstraints(depsAndConstraints); self._addLocalPackageConstraints(depsAndConstraints); - self._addReleaseConstraints(depsAndConstraints); return depsAndConstraints; }, @@ -717,19 +689,6 @@ _.extend(ProjectContext.prototype, { }); }, - _addReleaseConstraints: function (depsAndConstraints) { - var self = this; - if (! self._releaseForConstraints) - return; - _.each(self._releaseForConstraints.packages, function (version, packageName) { - var constraint = utils.parsePackageConstraint( - packageName + "@=" + version); - // Add a constraint ("this is the only version available") but no - // dependency (we don't automatically use all local packages!) - depsAndConstraints.constraints.push(constraint); - }); - }, - _getAnticipatedPrereleases: function (rootConstraints, cachedVersions) { var self = this; @@ -1023,6 +982,18 @@ _.extend(exports.ProjectConstraintsFile.prototype, { })); }, + // For every package we already have, update the constraint to be semver>= + // the constraint from the release + updateReleaseConstraints: function (releaseRecord) { + this.addConstraints( + _.compact(_.map(releaseRecord.packages, (version, packageName) => { + if (this.getConstraint(packageName)) { + return utils.parsePackageConstraint(packageName + '@' + version); + } + })) + ); + }, + // The packages in packagesToRemove are expected to actually be in the file; // if you want to provide different output for packages in the file vs not, // you should have already done that. diff --git a/tools/runners/run-app.js b/tools/runners/run-app.js index e0a5fb0082..1b7432d665 100644 --- a/tools/runners/run-app.js +++ b/tools/runners/run-app.js @@ -843,8 +843,14 @@ _.extend(AppRunner.prototype, { // Notify the server that new client assets have been added to the // build. self._refreshing = true; - appProcess.proc.send({ refresh: 'client' }); - self._refreshing = false; + // ChildProcess.prototype.send used to be synchronous, but is now + // asynchronous: https://github.com/nodejs/node/pull/2620 + appProcess.proc.send({ + refresh: 'client' + }, err => { + self._refreshing = false; + if (err) throw err; + }); // Establish a watcher on the new files. setupClientWatcher(); diff --git a/tools/runners/run-mongo.js b/tools/runners/run-mongo.js index 7bc2810ddb..d666c17c7a 100644 --- a/tools/runners/run-mongo.js +++ b/tools/runners/run-mongo.js @@ -7,6 +7,7 @@ var child_process = require('child_process'); var _ = require('underscore'); var isopackets = require('../tool-env/isopackets.js'); +var Console = require('../console/console.js').Console; // Given a Mongo URL, open an interative Mongo shell on this terminal // on that database. @@ -36,24 +37,33 @@ var runMongoShell = function (url) { }; // Start mongod with a dummy replSet and wait for it to listen. -var spawnMongod = function (mongodPath, port, dbPath, replSetName) { - var child_process = require('child_process'); +function spawnMongod(mongodPath, port, dbPath, replSetName) { + const child_process = require('child_process'); mongodPath = files.convertToOSPath(mongodPath); dbPath = files.convertToOSPath(dbPath); - return child_process.spawn(mongodPath, [ - // nb: cli-test.sh and findMongoPids make strong assumptions about the - // order of the arguments! Check them before changing any arguments. - '--bind_ip', '127.0.0.1', - '--smallfiles', - '--port', port, - '--dbpath', dbPath, - // Use an 8MB oplog rather than 256MB. Uses less space on disk and - // initializes faster. (Not recommended for production!) - '--oplogSize', '8', - '--replSet', replSetName - ], { + const args = [ + // nb: cli-test.sh and findMongoPids make strong assumptions about the + // order of the arguments! Check them before changing any arguments. + '--bind_ip', '127.0.0.1', + '--port', port, + '--dbpath', dbPath, + // Use an 8MB oplog rather than 256MB. Uses less space on disk and + // initializes faster. (Not recommended for production!) + '--oplogSize', '8', + '--replSet', replSetName + ]; + + // Use mmapv1 on windows, as our binary doesn't support WT + if (process.platform === "win32") { + args.push('--storageEngine', 'mmapv1', '--smallfiles'); + } else { + // The WT journal seems to be at least 300MB, which is just too much + args.push('--nojournal'); + } + + return child_process.spawn(mongodPath, args, { // Apparently in some contexts, Mongo crashes if your locale isn't set up // right. I wasn't able to reproduce it, but many people on #4019 // were. Let's default a couple environment variables to English UTF-8 if @@ -65,7 +75,7 @@ var spawnMongod = function (mongodPath, port, dbPath, replSetName) { LC_ALL: 'en_US.UTF-8' }, process.env) }); -}; +} // Find all running Mongo processes that were started by this program // (even by other simultaneous runs of this program). If passed, @@ -521,7 +531,7 @@ var launchMongo = function (options) { var stdoutOnData = fiberHelpers.bindEnvironment(function (data) { // note: don't use "else ifs" in this, because 'data' can have multiple // lines - if (/config from self or any seed \(EMPTYCONFIG\)/.test(data)) { + if (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data)) { replSetReadyToBeInitiated = true; maybeReadyToTalk(); } @@ -531,7 +541,7 @@ var launchMongo = function (options) { maybeReadyToTalk(); } - if (/ \[rsMgr\] replSet (PRIMARY|SECONDARY)/.test(data)) { + if (/ \[rsSync\] transition to primary complete/.test(data)) { replSetReady = true; maybeReadyToTalk(); } @@ -540,6 +550,19 @@ var launchMongo = function (options) { detectedErrors.freeSpace = true; } + // Running against a old mmapv1 engine, probably from pre-mongo-3.2 Meteor + if (/created by the 'mmapv1' storage engine, so setting the active storage engine to 'mmapv1'/.test(data)) { + Console.warn(); + Console.warn('Your development database is using mmapv1, ' + + 'the old, pre-MongoDB 3.0 database engine. ' + + 'You should consider upgrading to Wired Tiger, the new engine. ' + + 'The easiest way to do so in development is to run ' + + Console.command('meteor reset') + '. ' + + "If you'd like to migrate your database, please consult " + + Console.url('https://docs.mongodb.org/v3.0/release-notes/3.0-upgrade/')) + Console.warn(); + } + if (/Invalid or no user locale set/.test(data)) { detectedErrors.badLocale = true; } @@ -588,38 +611,26 @@ var launchMongo = function (options) { }); } - var initiateResult = yieldingMethod( - db.admin(), 'command', {replSetInitiate: configuration}); + try { + var initiateResult = yieldingMethod( + db.admin(), 'command', {replSetInitiate: configuration}); + } catch (e) { + if (e.message !== 'already initialized') { + throw Error("rs.initiate error: " + e.message); + } + } + if (stopped) { return; } - // why this isn't in the error is unclear. - if (initiateResult && initiateResult.documents - && initiateResult.documents[0] - && initiateResult.documents[0].errmsg) { - var err = initiateResult.documents[0].errmsg; - if (err !== "already initialized") { - throw Error("rs.initiate error: " + - initiateResult.documents[0].errmsg); - } - } + // XXX timeout eventually? while (!stopped) { - var status = yieldingMethod(db.admin(), 'command', - {replSetGetStatus: 1}); - if (!(status && status.documents && status.documents[0])) { - throw status; - } - status = status.documents[0]; - if (!status.ok) { - if (status.startupStatus === 6) { // "SOON" - utils.sleepMs(20); - continue; - } - throw status.errmsg; - } - // See http://docs.mongodb.org/manual/reference/replica-states/ - // for information about the various states. + var status = yieldingMethod( + db.admin(), 'command', {replSetGetStatus: 1}); + + // See https://docs.mongodb.com/manual/reference/replica-states/ + // for information on various states // Are any of the members starting up or recovering? if (_.any(status.members, function (member) { @@ -633,7 +644,6 @@ var launchMongo = function (options) { // Is the intended primary currently a secondary? (It passes through // that phase briefly.) - if (status.members[0].stateStr === 'SECONDARY') { utils.sleepMs(20); continue; @@ -800,7 +810,6 @@ _.extend(MRp, { self.suppressExitMessage = false; }, }); - // It has successfully started up, so if it exits after this point, that // actually is an interesting fact and we shouldn't suppress it. self.suppressExitMessage = false; diff --git a/tools/static-assets/server/mini-files.js b/tools/static-assets/server/mini-files.js index 8e75a6d59c..3d29cc5549 100644 --- a/tools/static-assets/server/mini-files.js +++ b/tools/static-assets/server/mini-files.js @@ -1,6 +1,7 @@ var _ = require("underscore"); var os = require("os"); var path = require("path"); +var assert = require("assert"); // All of these functions are attached to files.js for the tool; // they live here because we need them in boot.js as well to avoid duplicating @@ -73,6 +74,8 @@ var convertToStandardLineEndings = function (fileContents) { // forward slashes) var wrapPathFunction = function (name, partialPaths) { var f = path[name]; + assert.strictEqual(typeof f, "function"); + return function (/* args */) { if (process.platform === 'win32') { var args = _.toArray(arguments); @@ -101,12 +104,11 @@ files.pathResolve = wrapPathFunction("resolve"); files.pathDirname = wrapPathFunction("dirname"); files.pathBasename = wrapPathFunction("basename"); files.pathExtname = wrapPathFunction("extname"); +// The path.isAbsolute function is implemented in Node v4. +files.pathIsAbsolute = wrapPathFunction("isAbsolute"); files.pathSep = '/'; files.pathDelimiter = ':'; files.pathOsDelimiter = path.delimiter; -files.pathIsAbsolute = function (path) { - return toPosixPath(path).charAt(0) === '/'; -}; files.convertToStandardPath = convertToStandardPath; files.convertToOSPath = convertToOSPath; diff --git a/tools/static-assets/skel/.meteor/.gitignore b/tools/static-assets/skel/.meteor/.gitignore index 2b8ab361bb..4083037423 100644 --- a/tools/static-assets/skel/.meteor/.gitignore +++ b/tools/static-assets/skel/.meteor/.gitignore @@ -1,2 +1 @@ local -dev_bundle diff --git a/tools/tests/apps/failover-test/server/failover-test.js b/tools/tests/apps/failover-test/server/failover-test.js index b3e7df64a1..a194df44a8 100644 --- a/tools/tests/apps/failover-test/server/failover-test.js +++ b/tools/tests/apps/failover-test/server/failover-test.js @@ -23,12 +23,12 @@ var originalMasterName = null; steps.initialized = function () { // Great, we got the first thing. Let's get another thing. C.insert({step: 'next'}); - var master = C.rawDatabase().serverConfig._state.master; + var master = C.rawDatabase().serverConfig.isMasterDoc; if (!master) { console.log("No master in initialized?"); process.exit(1); } - originalMasterName = master.name; + originalMasterName = master.primary; console.log("Master starts as", originalMasterName); }; @@ -49,16 +49,16 @@ steps.next = function () { steps.steppedDown = function () { console.log("Write succeeded after stepdown."); - var master = C.rawDatabase().serverConfig._state.master; + var master = C.rawDatabase().serverConfig.isMasterDoc; if (!master) { console.log("No master in steppedDown?"); process.exit(1); } - if (master.name === originalMasterName) { + if (master.primary === originalMasterName) { console.log("Master didn't change?"); process.exit(1); } - console.log("Master ended as", master.name); + console.log("Master ended as", master.primary); console.log("SUCCESS"); process.exit(0); }; diff --git a/tools/tests/apps/modules/.meteor/.finished-upgraders b/tools/tests/apps/modules/.meteor/.finished-upgraders index dacc2c0d7a..7bd7197893 100644 --- a/tools/tests/apps/modules/.meteor/.finished-upgraders +++ b/tools/tests/apps/modules/.meteor/.finished-upgraders @@ -11,3 +11,4 @@ notices-for-facebook-graph-api-2 1.2.0-cordova-changes 1.2.0-breaking-changes 1.3.0-split-minifiers-package +1.3.5-remove-old-dev-bundle-link diff --git a/tools/tests/apps/modules/.meteor/release b/tools/tests/apps/modules/.meteor/release index e5b4dc1807..fcf9d2d773 100644 --- a/tools/tests/apps/modules/.meteor/release +++ b/tools/tests/apps/modules/.meteor/release @@ -1 +1 @@ -METEOR@1.3.4.4 +METEOR@1.3.5.1 diff --git a/tools/tests/apps/modules/.meteor/versions b/tools/tests/apps/modules/.meteor/versions index 642f7e7cec..c7993884d1 100644 --- a/tools/tests/apps/modules/.meteor/versions +++ b/tools/tests/apps/modules/.meteor/versions @@ -1,7 +1,7 @@ allow-deny@1.0.5 autoupdate@1.2.11 avital:mocha@2.1.0_10 -babel-compiler@6.8.4 +babel-compiler@6.8.5 babel-runtime@0.1.9_1 base64@1.0.9 binary-heap@1.0.9 @@ -14,14 +14,14 @@ caching-html-compiler@1.0.6 callback-hook@1.0.9 check@1.2.3 client-only-ecmascript@0.0.1 -coffeescript@1.1.3 +coffeescript@1.1.4 ddp@1.2.5 ddp-client@1.2.9 ddp-common@1.2.6 -ddp-server@1.2.9 +ddp-server@1.2.10 deps@1.0.12 diff-sequence@1.0.6 -ecmascript@0.4.7 +ecmascript@0.4.8 ecmascript-runtime@0.2.12 ejson@1.0.12 es5-shim@4.5.13 @@ -68,12 +68,12 @@ spacebars@1.0.12 spacebars-compiler@1.0.12 standard-minifier-css@1.0.8 standard-minifier-js@1.0.8 -templating@1.1.13 +templating@1.1.14 templating-tools@1.0.4 tmeasday:test-reporter-helpers@0.2.1 -tracker@1.0.14 +tracker@1.0.15 ui@1.0.11 underscore@1.0.9 url@1.0.10 -webapp@1.2.10 +webapp@1.2.11 webapp-hashing@1.0.9 diff --git a/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/.gitignore b/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/packages b/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/packages new file mode 100644 index 0000000000..25e81bdfaa --- /dev/null +++ b/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/packages @@ -0,0 +1,6 @@ +# Meteor packages used by this project, one per line. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-base # Packages every Meteor app needs to have diff --git a/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/release b/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/release new file mode 100644 index 0000000000..621e94f0ec --- /dev/null +++ b/tools/tests/apps/very-simple-app-with-no-package-constraints/.meteor/release @@ -0,0 +1 @@ +none diff --git a/tools/tests/apps/very-simple-app-with-no-package-constraints/simple.html b/tools/tests/apps/very-simple-app-with-no-package-constraints/simple.html new file mode 100644 index 0000000000..5eefc206cc --- /dev/null +++ b/tools/tests/apps/very-simple-app-with-no-package-constraints/simple.html @@ -0,0 +1,7 @@ + + Hello + + + +

Welcome to Meteor!

+ diff --git a/tools/tests/autoupdate.js b/tools/tests/autoupdate.js index db350a1047..3d826f5a41 100644 --- a/tools/tests/autoupdate.js +++ b/tools/tests/autoupdate.js @@ -34,7 +34,7 @@ var recommend = function (sandbox, version) { selftest.define("autoupdate", ['checkout', 'custom-warehouse'], function () { var s = new Sandbox({ warehouse: { - v1: { recommended: true}, + v1: { recommended: true }, v2: { recommended: true }, v3: { }, v4: { } diff --git a/tools/tests/create.js b/tools/tests/create.js index d3f7cb83c1..270112ef30 100644 --- a/tools/tests/create.js +++ b/tools/tests/create.js @@ -1,8 +1,10 @@ var selftest = require('../tool-testing/selftest.js'); var Sandbox = selftest.Sandbox; +const SIMPLE_WAREHOUSE = { v1: { recommended: true } }; selftest.define("create", function () { - var s = new Sandbox; + // We need a warehouse so the tool doesn't think we are running from checkout + var s = new Sandbox({ warehouse: SIMPLE_WAREHOUSE }); // Can we create an app? Yes! var run = s.run("create", "foobar"); @@ -11,8 +13,14 @@ selftest.define("create", function () { run.match("To run your new app"); run.expectExit(0); - // Now, can we run it? + // Test that the release constraints have been written to .meteor/packages s.cd("foobar"); + const packages = s.read(".meteor/packages"); + if (!packages.match('meteor-base@')) { + selftest.fail("Failed to add a version specifier to `meteor-base` package"); + } + + // Now, can we run it? run = s.run(); run.waitSecs(15); run.match("foobar"); diff --git a/tools/tests/mongo.js b/tools/tests/mongo.js index 1e3f2b0029..eafc5fecd3 100644 --- a/tools/tests/mongo.js +++ b/tools/tests/mongo.js @@ -36,7 +36,7 @@ var testMeteorMongo = function (appDir) { mongoRun.match('connecting to: 127.0.0.1'); // Note: when mongo shell's input is not a tty, there is no prompt. mongoRun.write('db.version()\n'); - mongoRun.match(/2\.6\.\d+/); + mongoRun.match(/3\.2\.\d+/); mongoRun.stop(); run.stop(); diff --git a/tools/tests/source-maps.js b/tools/tests/source-maps.js index 2e6432559f..dcc52a0320 100644 --- a/tools/tests/source-maps.js +++ b/tools/tests/source-maps.js @@ -82,7 +82,7 @@ selftest.define("source maps from built meteor tool", ['checkout', 'custom-wareh var run = s.run("throw-error"); run.matchErr(matchPathRegexp('\\(/tools/cli/commands\\.js:' + lineNumber)); - run.expectExit(8); + run.expectExit(1); }); selftest.define("source maps from a build plugin implementation", ['checkout', 'custom-warehouse'], function () { diff --git a/tools/tests/update-tests.js b/tools/tests/update-tests.js new file mode 100644 index 0000000000..97956b3df1 --- /dev/null +++ b/tools/tests/update-tests.js @@ -0,0 +1,53 @@ +import selftest, { Sandbox } from '../tool-testing/selftest.js'; +import catalog from '../packaging/catalog/catalog.js'; + +const DEFAULT_RELEASE_TRACK = catalog.DEFAULT_TRACK; +const SIMPLE_WAREHOUSE = { + v1: { }, + v2: { recommended: true } +}; + +selftest.define("'meteor update' adds constraints to `.meteor/packages`", () => { + const s = new Sandbox({ + warehouse: SIMPLE_WAREHOUSE, + fakeMongo: true + }); + + s.createApp("myapp", "very-simple-app-with-no-package-constraints", { + release: DEFAULT_RELEASE_TRACK + '@v1' + }); + s.cd("myapp"); + + run = s.run("update"); + run.match("updated to Meteor v2"); + run.expectExit(0); + + const packages = s.read(".meteor/packages"); + if (!packages.match('meteor-base@')) { + selftest.fail("Failed to add a version specifier to `meteor-base` package"); + } +}); + +selftest.define("'meteor update' alters constraints in `.meteor/packages`", () => { + const s = new Sandbox({ + warehouse: SIMPLE_WAREHOUSE, + fakeMongo: true + }); + + s.createApp("myapp", "very-simple-app-with-no-package-constraints", { + release: DEFAULT_RELEASE_TRACK + '@v1' + }); + s.cd("myapp"); + + // change the package file to be an old version + s.write('.meteor/packages', 'meteor-base@0.0.1'); + + run = s.run("update"); + run.match("updated to Meteor v2"); + run.expectExit(0); + + const packages = s.read(".meteor/packages"); + if (packages.match('meteor-base@0.0.1')) { + selftest.fail("Failed to update the version specifier for the `meteor-base` package"); + } +}); diff --git a/tools/upgraders.js b/tools/upgraders.js index 2d2f9e4a6e..8691afc261 100644 --- a/tools/upgraders.js +++ b/tools/upgraders.js @@ -227,7 +227,7 @@ the guide about breaking changes here:`, packagesFile.writeIfModified(); }, - "1.3.5-remove-old-dev-bundle-link": function (projectContext) { + "1.4.0-remove-old-dev-bundle-link": function (projectContext) { const oldDevBundleLink = files.pathJoin(projectContext.projectDir, ".meteor", "dev_bundle"); files.rm_recursive(oldDevBundleLink);