diff --git a/History.md b/History.md index ed93c7f288..557d193240 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,32 @@ ## v.NEXT +## v1.4.1.3 + +* Node has been updated to version 4.6.1: + https://nodejs.org/en/blog/release/v4.6.1/ + +* The `mongodb` npm package has been upgraded to version 2.2.11. + +* The `fibers` npm package has been upgraded to version 1.0.15. + +* Running Meteor with a different `--port` will now automatically + reconfigure the Mongo replica set when using the WiredTiger storage + engine, instead of failing to start Mongo. + [#7840](https://github.com/meteor/meteor/pull/7840). + +* When the Meteor development server shuts down, it now attempts to kill + the `mongod` process it spawned, in addition to killing any running + `mongod` processes when the server first starts up. + https://github.com/meteor/meteor/pull/7668/commits/295d3d5678228f06ee0ab6c0d60139849a0ea192 + +* The `meteor ...` syntax will now work for any command + installed in `dev_bundle/bin`, except for Meteor's own commands. + +* Incomplete package downloads will now fail (and be retried several + times) instead of silently succeeding, which was the cause of the + dreaded `Error: ENOENT: no such file or directory, open... os.json` + error. [#7806](https://github.com/meteor/meteor/issues/7806) + ## v1.4.1.2 * Node has been upgraded to version 4.6.0, a recommended security release: diff --git a/meteor b/meteor index f7e92d6cd0..d95dba19ce 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.3.0 +BUNDLE_VERSION=4.4.1 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index e162820f3e..07b53618a7 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,39 +1,39 @@ Package.describe({ summary: "A user account system", - version: "1.2.11" + version: "1.2.13" }); Package.onUse(function (api) { - api.use('underscore@1.0.9', ['client', 'server']); - api.use('ecmascript@0.5.7', ['client', 'server']); - api.use('ddp-rate-limiter@1.0.5'); - api.use('localstorage@1.0.11', 'client'); - api.use('tracker@1.1.0', 'client'); - api.use('check@1.2.3', 'server'); - api.use('random@1.0.10', ['client', 'server']); - api.use('ejson@1.0.12', 'server'); - api.use('callback-hook@1.0.9', ['client', 'server']); + api.use('underscore', ['client', 'server']); + api.use('ecmascript', ['client', 'server']); + api.use('ddp-rate-limiter'); + api.use('localstorage', 'client'); + api.use('tracker', 'client'); + api.use('check', 'server'); + api.use('random', ['client', 'server']); + api.use('ejson', 'server'); + api.use('callback-hook', ['client', 'server']); // use unordered to work around a circular dependency // (service-configuration needs Accounts.connection) - api.use('service-configuration@1.0.10', ['client', 'server'], { unordered: true }); + api.use('service-configuration', ['client', 'server'], { unordered: true }); // needed for getting the currently logged-in user - api.use('ddp@1.2.5', ['client', 'server']); + api.use('ddp', ['client', 'server']); // need this because of the Meteor.users collection but in the future // we'd probably want to abstract this away - api.use('mongo@1.1.10', ['client', 'server']); + api.use('mongo', ['client', 'server']); // If the 'blaze' package is loaded, we'll define some helpers like // {{currentUser}}. If not, no biggie. - api.use('blaze@2.1.8', 'client', {weak: true}); + api.use('blaze', 'client', {weak: true}); // Allow us to detect 'autopublish', and publish some Meteor.users fields if // it's loaded. - api.use('autopublish@1.0.7', 'server', {weak: true}); + api.use('autopublish', 'server', {weak: true}); - api.use('oauth-encryption@1.2.0', 'server', {weak: true}); + api.use('oauth-encryption', 'server', {weak: true}); // Though this "Accounts" symbol is the only official Package export for // the accounts-base package, modules that import accounts-base will diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 764cc54fe4..58ff1e3f88 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.4.1_2' + version: '1.4.1_3' }); Package.includeTool(); diff --git a/packages/mongo/.npm/package/npm-shrinkwrap.json b/packages/mongo/.npm/package/npm-shrinkwrap.json index c5840f7d36..61615e3eb5 100644 --- a/packages/mongo/.npm/package/npm-shrinkwrap.json +++ b/packages/mongo/.npm/package/npm-shrinkwrap.json @@ -3,7 +3,7 @@ "mongodb-uri": { "version": "0.9.7", "resolved": "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz", - "from": "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz" + "from": "mongodb-uri@0.9.7" } } } diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 68192fefc5..0b3200508a 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -704,7 +704,7 @@ Mongo.Collection.prototype._createCappedCollection = function (byteSize, maxDocu }; /** - * @summary Returns the [`Collection`](http://mongodb.github.io/node-mongodb-native/1.4/api-generated/collection.html) object corresponding to this collection from the [npm `mongodb` driver module](https://www.npmjs.com/package/mongodb) which is wrapped by `Mongo.Collection`. + * @summary Returns the [`Collection`](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html) object corresponding to this collection from the [npm `mongodb` driver module](https://www.npmjs.com/package/mongodb) which is wrapped by `Mongo.Collection`. * @locus Server */ Mongo.Collection.prototype.rawCollection = function () { @@ -716,7 +716,7 @@ Mongo.Collection.prototype.rawCollection = function () { }; /** - * @summary Returns the [`Db`](http://mongodb.github.io/node-mongodb-native/1.4/api-generated/db.html) object corresponding to this collection's database connection from the [npm `mongodb` driver module](https://www.npmjs.com/package/mongodb) which is wrapped by `Mongo.Collection`. + * @summary Returns the [`Db`](http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html) object corresponding to this collection's database connection from the [npm `mongodb` driver module](https://www.npmjs.com/package/mongodb) which is wrapped by `Mongo.Collection`. * @locus Server */ Mongo.Collection.prototype.rawDatabase = function () { diff --git a/packages/mongo/connection_options.js b/packages/mongo/connection_options.js index c061513e0f..a5e746c4ca 100644 --- a/packages/mongo/connection_options.js +++ b/packages/mongo/connection_options.js @@ -1,6 +1,6 @@ /** * @summary Allows for user specified connection options - * @example http://mongodb.github.io/node-mongodb-native/2.1/reference/connecting/connection-settings/ + * @example http://mongodb.github.io/node-mongodb-native/2.2/reference/connecting/connection-settings/ * @locus Server * @param {Object} options User specified Mongo connection options */ diff --git a/packages/mongo/mongo_driver.js b/packages/mongo/mongo_driver.js index 567c349e4c..77eabdc3b6 100644 --- a/packages/mongo/mongo_driver.js +++ b/packages/mongo/mongo_driver.js @@ -130,15 +130,18 @@ MongoConnection = function (url, options) { self._observeMultiplexers = {}; self._onFailoverHook = new Hook; - 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 - // keeping this for backwards compatibility for now. - if (!(/[\?&]auto_?[rR]econnect=/.test(url))) { - mongoOptions.server.auto_reconnect = true; - } + var mongoOptions = _.extend({ + db: { safe: true }, + // http://mongodb.github.io/node-mongodb-native/2.2/api/Server.html + server: { + // Reconnect on error. + autoReconnect: true, + // Try to reconnect forever, instead of stopping after 30 tries (the + // default), with each attempt separated by 1000ms. + reconnectTries: Infinity + }, + replSet: {} + }, Mongo._connectionOptions); // Disable the native parser by default, unless specifically enabled // in the mongo URL. diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 5af9494d1f..6fac92bf19 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.12_1' + version: '1.1.13' }); Npm.depends({ @@ -21,7 +21,7 @@ Npm.strip({ }); Package.onUse(function (api) { - api.use('npm-mongo@1.5.48-1-rc.0', 'server'); + api.use('npm-mongo', 'server'); api.use('allow-deny'); api.use([ diff --git a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json index 50563e4ea7..4493b91832 100644 --- a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json +++ b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "bson": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.4.tgz", - "from": "bson@>=0.5.4 <0.6.0" + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.6.tgz", + "from": "bson@>=0.5.6 <0.6.0" }, "buffer-shims": { "version": "1.0.0", @@ -21,8 +21,8 @@ "from": "es6-promise@3.2.1" }, "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "from": "inherits@>=2.0.1 <2.1.0" }, "isarray": { @@ -31,14 +31,14 @@ "from": "isarray@>=1.0.0 <1.1.0" }, "mongodb": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.8.tgz", - "from": "mongodb@2.2.8" + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.11.tgz", + "from": "mongodb@2.2.11" }, "mongodb-core": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.0.10.tgz", - "from": "mongodb-core@2.0.10" + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.0.13.tgz", + "from": "mongodb-core@2.0.13" }, "process-nextick-args": { "version": "1.0.7", diff --git a/packages/npm-mongo/package.js b/packages/npm-mongo/package.js index 33c34710c2..bc70c84ffd 100644 --- a/packages/npm-mongo/package.js +++ b/packages/npm-mongo/package.js @@ -3,12 +3,12 @@ Package.describe({ summary: "Wrapper around the mongo npm package", - version: '1.5.48_1', + version: '2.2.11_1', documentation: null }); Npm.depends({ - mongodb: "2.2.8" + mongodb: "2.2.11" }); Package.onUse(function (api) { diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 934f0fb5e1..bc1105d8e3 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.4.1.2-rc.0", + "version": "1.4.1.3-rc.1", "recommended": false, "official": false, "description": "Meteor" diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index 34188e3837..f44dc66103 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,8 +1,8 @@ { "track": "METEOR", - "version": "1.4.1.2", + "version": "1.4.1.3", "recommended": false, "official": true, "description": "The Official Meteor Distribution", - "patchFrom": ["1.4.1.1"] + "patchFrom": ["1.4.1.2"] } diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index b0807c45fb..4eee6f85d1 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,7 +6,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.6 -NODE_VERSION=4.6.0 +NODE_VERSION=4.6.1 NPM_VERSION=3.10.8 if [ "$UNAME" == "Linux" ] ; then diff --git a/scripts/dev-bundle-server-package.js b/scripts/dev-bundle-server-package.js index 6c03d52c98..508c62607e 100644 --- a/scripts/dev-bundle-server-package.js +++ b/scripts/dev-bundle-server-package.js @@ -10,7 +10,7 @@ var packageJson = { version: "0.0.0", dependencies: { "meteor-promise": "0.7.2", - fibers: "1.0.13", + fibers: "1.0.15", promise: "7.1.1", // Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done // in the package too) because we should consider using lodash instead diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 2156c75fa0..1ee18b4e78 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -16,7 +16,7 @@ var packageJson = { "node-pre-gyp": "0.6.29", "meteor-babel": "0.12.0", "meteor-promise": "0.7.2", - fibers: "1.0.13", + fibers: "1.0.15", promise: "7.1.1", // So that Babel 6 can emit require("babel-runtime/helpers/...") calls. "babel-runtime": "6.9.2", diff --git a/scripts/generate-dev-bundle.ps1 b/scripts/generate-dev-bundle.ps1 index 7b9823ef84..20da753f62 100644 --- a/scripts/generate-dev-bundle.ps1 +++ b/scripts/generate-dev-bundle.ps1 @@ -2,7 +2,7 @@ # use 32bit by default $PLATFORM = "windows_x86" $MONGO_VERSION = "3.2.6" -$NODE_VERSION = "4.6.0" +$NODE_VERSION = "4.6.1" $NPM_VERSION = "3.10.8" $PYTHON_VERSION = "2.7.12" # For node-gyp diff --git a/scripts/generate-dev-bundle.sh b/scripts/generate-dev-bundle.sh index d37a3e1f04..5ac6911a3d 100755 --- a/scripts/generate-dev-bundle.sh +++ b/scripts/generate-dev-bundle.sh @@ -75,7 +75,7 @@ mv package.json npm-shrinkwrap.json "${DIR}/etc/" # bloats our dev bundle. Remove all the ones other than our # architecture. (Expression based on build.js in fibers source.) shrink_fibers () { - FIBERS_ARCH=$(node -p -e 'process.platform + "-" + process.arch + "-v8-" + /[0-9]+\.[0-9]+/.exec(process.versions.v8)[0]') + FIBERS_ARCH=$(node -p -e 'process.platform + "-" + process.arch + "-" + process.versions.modules') mv $FIBERS_ARCH .. rm -rf * mv ../$FIBERS_ARCH . diff --git a/tools/cli/dev-bundle-bin-commands.js b/tools/cli/dev-bundle-bin-commands.js index 5988abe27d..c9325b9799 100644 --- a/tools/cli/dev-bundle-bin-commands.js +++ b/tools/cli/dev-bundle-bin-commands.js @@ -1,11 +1,8 @@ // Note that this file is required before we install our Babel hooks in // ../tool-env/install-babel.js, so we can't use ES2015+ syntax here. +var fs = require("fs"); var path = require("path"); -var win32Extensions = { - node: ".exe", - npm: ".cmd" -}; // The dev_bundle/bin command has to come immediately after the meteor // command, as in `meteor npm` or `meteor node`, because we don't want to @@ -14,22 +11,22 @@ var devBundleBinCommand = process.argv[2]; var args = process.argv.slice(3); function getChildProcess() { - if (! win32Extensions.hasOwnProperty(devBundleBinCommand)) { + if (typeof devBundleBinCommand !== "string") { return Promise.resolve(null); } var helpers = require("./dev-bundle-bin-helpers.js"); - if (process.platform === "win32") { - devBundleBinCommand += win32Extensions[devBundleBinCommand]; - } - return Promise.all([ helpers.getDevBundle(), helpers.getEnv() ]).then(function (devBundleAndEnv) { var devBundleDir = devBundleAndEnv[0]; - var cmd = path.join(devBundleDir, "bin", devBundleBinCommand); + var cmd = helpers.getCommand(devBundleBinCommand, devBundleDir); + if (! cmd) { + return null; + } + var env = devBundleAndEnv[1]; var child = require("child_process").spawn(cmd, args, { stdio: "inherit", diff --git a/tools/cli/dev-bundle-bin-helpers.js b/tools/cli/dev-bundle-bin-helpers.js index 873fa30e60..5babb9cd6b 100644 --- a/tools/cli/dev-bundle-bin-helpers.js +++ b/tools/cli/dev-bundle-bin-helpers.js @@ -1,12 +1,65 @@ var fs = require("fs"); var path = require("path"); var files = require("../fs/mini-files.js"); +var isWindows = process.platform === "win32"; +var extensions = isWindows ? [".cmd", ".exe"] : [""]; +var hasOwn = Object.prototype.hasOwnProperty; function getDevBundle() { return require("./dev-bundle.js"); } exports.getDevBundle = getDevBundle; +exports.getCommand = function (name, devBundleDir) { + var result = null; + + // Strip leading and/or trailing whitespace. + name = name.replace(/^\s+|\s+$/g, ""); + + if (! isValidCommand(name, devBundleDir)) { + return result; + } + + extensions.some(function (ext) { + var cmd = path.join(devBundleDir, "bin", name + ext); + try { + if (fs.statSync(cmd).isFile()) { + result = cmd; + return true; + } + } catch (e) { + return false; + } + }); + + return result; +}; + +function isValidCommand(name, devBundleDir) { + if (name === "node" || + name === "npm") { + return true; + } + + if (! name || name.charAt(0) === ".") { + // Disallow empty commands and commands that start with a period. + return false; + } + + var meteorCommandsJsonPath = + path.join(devBundleDir, "bin", ".meteor-commands.json"); + + try { + var meteorCommands = require(meteorCommandsJsonPath); + } catch (e) { + return false; + } + + // If `meteor ` is already a Meteor command, don't let anything in + // dev_bundle/bin override it. + return ! hasOwn.call(meteorCommands, name); +} + exports.getEnv = function (options) { var devBundle = options && options.devBundle; var devBundlePromise = typeof devBundle === "string" diff --git a/tools/cli/dev-bundle.js b/tools/cli/dev-bundle.js index 6e032527fe..31439eb03e 100644 --- a/tools/cli/dev-bundle.js +++ b/tools/cli/dev-bundle.js @@ -52,7 +52,9 @@ function getDevBundleDir() { return defaultDevBundlePromise; } - return getDevBundleForRelease(release).then(function (devBundleDir) { + return Promise.resolve( + getDevBundleForRelease(release) + ).then(function (devBundleDir) { if (devBundleDir) { links.makeLink(devBundleDir, devBundleLink); return devBundleDir; diff --git a/tools/cli/main.js b/tools/cli/main.js index e5ab1f1d06..ebfd4a69ee 100644 --- a/tools/cli/main.js +++ b/tools/cli/main.js @@ -291,6 +291,28 @@ require('./commands-packages-query.js'); require('./commands-cordova.js'); require('./commands-aliases.js'); +/////////////////////////////////////////////////////////////////////////////// +// Record all the top-level commands as JSON +/////////////////////////////////////////////////////////////////////////////// + +export const meteorCommandsJsonPath = files.pathJoin( + files.getDevBundle(), "bin", ".meteor-commands.json" +); + +export function dumpMeteorCommands() { + const all = Object.create(null); + Object.keys(commands).forEach(name => all[name] = true); + const json = JSON.stringify(all, null, 2); + files.writeFile(meteorCommandsJsonPath, json + "\n"); + return all; +} + +if (files.inCheckout()) { + // If we're running Meteor from a checkout, dump the commands every + // time, so that the file remains up to date. + dumpMeteorCommands(); +} + /////////////////////////////////////////////////////////////////////////////// // Long-form help /////////////////////////////////////////////////////////////////////////////// diff --git a/tools/fs/files.js b/tools/fs/files.js index ae83d5e3ab..ff3198512c 100644 --- a/tools/fs/files.js +++ b/tools/fs/files.js @@ -717,13 +717,10 @@ files.extractTarGz = function (buffer, destPath, options) { } const startTime = +new Date; - let promise = tryExtractWithNativeTar(buffer, tempDir, options); - if (process.platform === "win32") { - promise = promise.catch( - error => tryExtractWithNative7z(buffer, tempDir, options) - ); - } + let promise = process.platform === "win32" + ? tryExtractWithNative7z(buffer, tempDir, options) + : tryExtractWithNativeTar(buffer, tempDir, options) promise = promise.catch( error => tryExtractWithNpmTar(buffer, tempDir, options) diff --git a/tools/runners/run-mongo.js b/tools/runners/run-mongo.js index 9f9b692a20..551d36d63b 100644 --- a/tools/runners/run-mongo.js +++ b/tools/runners/run-mongo.js @@ -482,15 +482,15 @@ var launchMongo = function (options) { proc = spawnMongod(mongod_path, port, dbPath, replSetName); - subHandles.push({ - stop: function () { - if (proc) { - proc.removeListener('exit', procExitHandler); - proc.kill('SIGINT'); - proc = null; - } + function stop() { + if (proc) { + proc.removeListener('exit', procExitHandler); + proc.kill('SIGINT'); + proc = null; } - }); + } + require("../tool-env/cleanup.js").onExit(stop); + subHandles.push({ stop }); var procExitHandler = fiberHelpers.bindEnvironment(function (code, signal) { // Defang subHandle.stop(). @@ -532,7 +532,8 @@ 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 (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data)) { + if (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data) || + /\[ReplicationExecutor\] Locally stored replica set configuration does not have a valid entry for the current node/.test(data)) { replSetReadyToBeInitiated = true; maybeReadyToTalk(); } @@ -596,10 +597,25 @@ var launchMongo = function (options) { if (stopped) { return; } + var configuration = { _id: replSetName, + version: 1, members: [{_id: 0, host: '127.0.0.1:' + options.port, priority: 100}] }; + + try { + const config = yieldingMethod(db.admin(), "command", { + replSetGetConfig: 1, + }).config; + + // If a replication set configuration already exists, it's + // important that the new version number is greater than the old. + if (config && _.has(config, "version")) { + configuration.version = config.version + 1; + } + } catch (e) {} + if (options.multiple) { // Add two more members: one of which should start as secondary but // could in theory become primary, and one of which can never be @@ -613,10 +629,16 @@ var launchMongo = function (options) { } try { - var initiateResult = yieldingMethod( - db.admin(), 'command', {replSetInitiate: configuration}); + yieldingMethod(db.admin(), 'command', { + replSetInitiate: configuration, + }); } catch (e) { - if (e.message !== 'already initialized') { + if (e.message === 'already initialized') { + yieldingMethod(db.admin(), 'command', { + replSetReconfig: configuration, + force: true, + }); + } else { throw Error("rs.initiate error: " + e.message); } } diff --git a/tools/tests/apps/mongo-sanity/.meteor/.finished-upgraders b/tools/tests/apps/mongo-sanity/.meteor/.finished-upgraders new file mode 100644 index 0000000000..aa607041da --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/.finished-upgraders @@ -0,0 +1,15 @@ +# This file contains information which helps Meteor properly upgrade your +# app when you run 'meteor update'. You should check it into version control +# with your project. + +notices-for-0.9.0 +notices-for-0.9.1 +0.9.4-platform-file +notices-for-facebook-graph-api-2 +1.2.0-standard-minifiers-package +1.2.0-meteor-platform-split +1.2.0-cordova-changes +1.2.0-breaking-changes +1.3.0-split-minifiers-package +1.4.0-remove-old-dev-bundle-link +1.4.1-add-shell-server-package diff --git a/tools/tests/apps/mongo-sanity/.meteor/.gitignore b/tools/tests/apps/mongo-sanity/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/tests/apps/mongo-sanity/.meteor/.id b/tools/tests/apps/mongo-sanity/.meteor/.id new file mode 100644 index 0000000000..789b92d073 --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/.id @@ -0,0 +1,7 @@ +# This file contains a token that is unique to your project. +# Check it into your repository along with the rest of this directory. +# It can be used for purposes such as: +# - ensuring you don't accidentally deploy one app on top of another +# - providing package authors with aggregated statistics + +fgbyyt1b3uxw5u734ug diff --git a/tools/tests/apps/mongo-sanity/.meteor/packages b/tools/tests/apps/mongo-sanity/.meteor/packages new file mode 100644 index 0000000000..6205c4c08c --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/packages @@ -0,0 +1,12 @@ +# Meteor packages used by this project, one per line. +# Check this file (and the other files in this directory) into your repository. +# +# '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 +mongo # The database Meteor supports right now + +ecmascript # Enable ECMAScript2015+ syntax in app code +shell-server # Server-side component of the `meteor shell` command + diff --git a/tools/tests/apps/mongo-sanity/.meteor/platforms b/tools/tests/apps/mongo-sanity/.meteor/platforms new file mode 100644 index 0000000000..efeba1b50c --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/tools/tests/apps/mongo-sanity/.meteor/release b/tools/tests/apps/mongo-sanity/.meteor/release new file mode 100644 index 0000000000..621e94f0ec --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/release @@ -0,0 +1 @@ +none diff --git a/tools/tests/apps/mongo-sanity/.meteor/versions b/tools/tests/apps/mongo-sanity/.meteor/versions new file mode 100644 index 0000000000..e675491585 --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/versions @@ -0,0 +1,54 @@ +allow-deny@1.0.5 +autoupdate@1.3.11 +babel-compiler@6.9.2-beta.5 +babel-runtime@0.1.12-beta.5 +base64@1.0.9 +binary-heap@1.0.9 +blaze@2.1.8 +blaze-tools@1.0.9 +boilerplate-generator@1.0.10 +callback-hook@1.0.9 +check@1.2.3 +ddp@1.2.5 +ddp-client@1.3.2-beta.5 +ddp-common@1.2.6 +ddp-server@1.3.11-beta.5 +deps@1.0.12 +diff-sequence@1.0.6 +ecmascript@0.5.9-beta.5 +ecmascript-runtime@0.3.15-beta.5 +ejson@1.0.12 +geojson-utils@1.0.9 +hot-code-push@1.0.4 +html-tools@1.0.10 +htmljs@1.0.10 +http@1.2.10-beta.5 +id-map@1.0.8 +jquery@1.11.9 +livedata@1.0.18 +logging@1.1.16-beta.5 +meteor@1.2.18-beta.5 +meteor-base@1.0.4 +minimongo@1.0.17 +modules@0.7.7-beta.5 +modules-runtime@0.7.7-beta.5 +mongo@1.1.13-beta.5 +mongo-id@1.0.5 +npm-mongo@1.5.51-beta.5 +observe-sequence@1.0.12 +ordered-dict@1.0.8 +promise@0.8.8-beta.5 +random@1.0.10 +reactive-var@1.0.10 +reload@1.1.10 +retry@1.0.8 +routepolicy@1.0.11 +shell-server@0.2.1 +spacebars@1.0.12 +spacebars-compiler@1.0.12 +tracker@1.1.0 +ui@1.0.11 +underscore@1.0.9 +url@1.0.10 +webapp@1.3.12-beta.5 +webapp-hashing@1.0.9 diff --git a/tools/tests/apps/mongo-sanity/server/main.js b/tools/tests/apps/mongo-sanity/server/main.js new file mode 100644 index 0000000000..45aa6e530a --- /dev/null +++ b/tools/tests/apps/mongo-sanity/server/main.js @@ -0,0 +1,18 @@ +import { Mongo } from 'meteor/mongo'; + +const collection = new Mongo.Collection("sanity"); + +Meteor.startup(() => { + let doc = collection.findOne(); + + if (! doc) { + collection.insert({ count: 0 }); + doc = collection.findOne(); + } + + collection.update(doc._id, { + $inc: { count: 1 } + }); + + console.log("count: " + collection.findOne().count); +}); diff --git a/tools/tests/mongo.js b/tools/tests/mongo.js index eafc5fecd3..eb9794a446 100644 --- a/tools/tests/mongo.js +++ b/tools/tests/mongo.js @@ -56,3 +56,32 @@ selftest.define("meteor mongo", function () { selftest.define("meteor mongo in unicode dir", function () { testMeteorMongo('asdf\u0442asdf'); }); + +selftest.define("mongo with multiple --port numbers (#7563)", function () { + var s = new Sandbox(); + s.createApp("mongo-multiple-ports", "mongo-sanity"); + s.cd("mongo-multiple-ports"); + + function check(args, matches) { + const run = s.run(...args); + run.waitSecs(30); + matches.forEach(m => { + run.waitSecs(10); + run.match(m); + }); + run.stop(); + } + + // Make absolutely sure we're creating the database for the first time. + check(["reset"], ["Project reset."]); + + let count = 0; + function next() { + return ["Started MongoDB", "count: " + (++count)]; + } + + check(["run"], next()); + check(["--port", "4321"], next()); + check(["--port", "4123"], next()); + check([], next()); +}); diff --git a/tools/utils/http-helpers.js b/tools/utils/http-helpers.js index 673da536b7..2dda4548e6 100644 --- a/tools/utils/http-helpers.js +++ b/tools/utils/http-helpers.js @@ -37,6 +37,14 @@ class ConcatStream extends Writable { return this.chunks[0]; } + + end(force = false) { + // Override the Writable#end method to ignore any .end() calls for + // this stream, since we likely want to resume the download later. + if (force === true) { + super.end(); + } + } } // Helper that tracks bytes written to a writable @@ -299,7 +307,17 @@ _.extend(exports, { // require it until we definitely need it. Console.debug("Doing HTTP request: ", options.method || 'GET', options.url); var request = require('request'); - var req = request(options, callback); + var req = request(options, function (error, response, body) { + if (! error && response && body) { + const contentLength = Number(response.headers["content-length"]); + if (contentLength > 0 && body.length < contentLength) { + error = new Error( + "Expected " + contentLength + " bytes in request body " + + "but received only " + body.length); + } + } + return callback.call(this, error, response, body); + }); if (_.isFunction(onRequest)) { onRequest(req); @@ -470,7 +488,6 @@ _.extend(exports, { } } - const result = attempt().await(); const response = result.response if (response.statusCode >= 400 && response.statusCode < 600) { @@ -478,6 +495,9 @@ _.extend(exports, { throw Error(`Could not get ${href}; server returned [${response.statusCode}]`); } + // Really end the stream if we got this far. + outputStream.end(true); + return outputStream.getBuffer(); } });