From 8e550dfe9aad90f53f37dcdfd5122ac2271ea251 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 18:03:02 -0700 Subject: [PATCH 01/11] add more spacing around banner --- tools/updater.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/updater.js b/tools/updater.js index cb15ce1736..ccfeef3480 100644 --- a/tools/updater.js +++ b/tools/updater.js @@ -46,7 +46,9 @@ exports.startUpdateChecks = function (context) { if (manifest.releases.stable.banner && warehouse.lastPrintedBannerRelease() !== manifestLatestRelease) { // XXX onStdio + console.log(); console.log(manifest.releases.stable.banner); + console.log(); warehouse.writeLastPrintedBannerRelease(manifestLatestRelease); } else { // Already printed this banner, or maybe there is no banner. From 8ed6e807717f040263f4d265f688bda9a16e51be Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 18:30:17 -0700 Subject: [PATCH 02/11] notice printing, as per script --- scripts/admin/bless-release.js | 17 +++++++++ scripts/admin/notices.json | 20 ++++++++--- tools/meteor.js | 5 ++- tools/warehouse.js | 66 ++++++++++++++++++++-------------- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/scripts/admin/bless-release.js b/scripts/admin/bless-release.js index aa6f5fca69..13e69fbfed 100644 --- a/scripts/admin/bless-release.js +++ b/scripts/admin/bless-release.js @@ -234,6 +234,23 @@ var main = function () { return readJSONFile(noticesFilename); }); + // Every "official" release needs to be in notices.json, even those without + // notices, so that the notice-printing code knows how far back to look. + if (!_.contains(_.pluck(notices, 'release'), blessedReleaseName)) { + die("notices.json must contain release " + + blessedReleaseName + "! (It does not need to have notices.)"); + } + + _.each(notices, function (record) { + if (!record.release) + die("An element of notices.json lacks a release."); + _.each(record.notices, function (line) { + if (line.length + record.release.length + 2 > 80) { + die("notices.json: notice line too long: " + line); + } + }); + }); + var bannerFilename = path.resolve(__dirname, 'banner.txt'); var banner = doOrDie("Can't read banner file " + bannerFilename, function () { return fs.readFileSync(bannerFilename, 'utf8'); diff --git a/scripts/admin/notices.json b/scripts/admin/notices.json index 057f257c79..a07502917e 100644 --- a/scripts/admin/notices.json +++ b/scripts/admin/notices.json @@ -1,10 +1,22 @@ [ { - "release": "0.6.0", - "tagline": "The engine!", - "changes": [ - "Use 'Npm.require' instead of '__meteor_bootstrap__.require'", + "release": "0.6.0" + }, + { + "release": "0.6.1", + "notices": [ + "hi", + "This has a very very veryveryvery very very very long long long line", "more..." ] + }, + { + "release": "0.6.2" + }, + { + "release": "0.6.3", + "notices": [ + "ok here is a notice" + ] } ] diff --git a/tools/meteor.js b/tools/meteor.js index 94629d0bbe..9333b83f17 100644 --- a/tools/meteor.js +++ b/tools/meteor.js @@ -451,7 +451,10 @@ Fiber(function () { console.log("%s: updated to Meteor %s.", context.appDir, context.releaseVersion); - warehouse.printNotices(appRelease, context.releaseVersion); + // Print any notices relevant to this upgrade. (We don't do this on an + // initial upgrade to Engine Meteor. + if (appRelease) + warehouse.printNotices(appRelease, context.releaseVersion); } }); diff --git a/tools/warehouse.js b/tools/warehouse.js index 81078939b3..95973a51c6 100644 --- a/tools/warehouse.js +++ b/tools/warehouse.js @@ -363,35 +363,47 @@ _.extend(warehouse, { var noticesPath = path.join( warehouse.getWarehouseDir(), 'releases', toRelease + '.notices.json'); - if (fs.existsSync(path.join(noticesPath))) { + try { var notices = JSON.parse(fs.readFileSync(noticesPath)); - var foundFromRelease = false; - var newChanges = []; // acculumate change until we hit 'fromRelease' - _.find(notices, function(change) { - if (change.release === fromRelease) { - foundFromRelease = true; - return true; // exit _.find - } else { - newChanges.push(change); - return false; - } - }); - - if (foundFromRelease) { - console.log("Important changes from " + fromRelease + ":"); - _.each(newChanges, function(change) { - console.log(change.release + ": " + change.tagline); - _.each(change.changes, function (changeline) { - console.log('* ' + changeline); - }); - console.log(); - }); - } else { - // didn't find 'fromRelease' in the notices. must have been - // an unofficial release. don't print anything. - // XXX probably print the latest only or something - } + } catch (e) { + // It's valid for this file to not exist (if it's an unblessed version) + // and eh, if the JSON is bad then the user doesn't really care. + return; } + + var noticesToPrint = []; + var foundFromRelease = false; + for (var i = 0; i < notices.length; ++i) { + var record = notices[i]; + // We want to print the notices for releases newer than fromRelease, and + // we always want to print toRelease even if we're updating from something + // that's not in the notices file at all. + if (record.notices && + (foundFromRelease || record.release === toRelease)) { + noticesToPrint.push(record); + } + // Nothing newer than toRelease. + if (record.release === toRelease) + break; + if (record.release === fromRelease) + foundFromRelease = true; + } + + if (_.isEmpty(noticesToPrint)) + return; + + console.log(); + console.log("-- Notice --"); + console.log(); + _.each(noticesToPrint, function (record) { + var header = record.release + ': '; + _.each(record.lines, function (line, i) { + console.log(header + line); + if (i === 0) + header = header.replace(/./g, ' '); + }); + console.log(); + }); }, // this function is also used by bless-release.js From de753799badba784ed181a0b2d0eb5a2a8d14ce1 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 18:54:35 -0700 Subject: [PATCH 03/11] fix typo in notices support --- tools/warehouse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/warehouse.js b/tools/warehouse.js index 95973a51c6..71a33ed8a5 100644 --- a/tools/warehouse.js +++ b/tools/warehouse.js @@ -397,7 +397,7 @@ _.extend(warehouse, { console.log(); _.each(noticesToPrint, function (record) { var header = record.release + ': '; - _.each(record.lines, function (line, i) { + _.each(record.notices, function (line, i) { console.log(header + line); if (i === 0) header = header.replace(/./g, ' '); From 55fbe16acf958b0767020785a409ff491fc22a2a Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 21:45:53 -0700 Subject: [PATCH 04/11] slightly better short description for update --- tools/meteor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/meteor.js b/tools/meteor.js index 9333b83f17..16c7423a37 100644 --- a/tools/meteor.js +++ b/tools/meteor.js @@ -347,7 +347,7 @@ Fiber(function () { Commands.push({ name: "update", - help: "Upgrade to the latest version of Meteor", + help: "Upgrade this project to the latest version of Meteor", func: function (argv) { // reparse args var opt = require('optimist').usage( From 912e36ad3fa4bb422468ac2ed887e9161cc90301 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:21:04 -0700 Subject: [PATCH 05/11] move --get-ready comment --- tools/meteor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/meteor.js b/tools/meteor.js index 16c7423a37..d342a21821 100644 --- a/tools/meteor.js +++ b/tools/meteor.js @@ -974,6 +974,9 @@ Fiber(function () { process.exit(0); }; + // Implements "meteor --get-ready", which you run to ensure that your + // checkout's Meteor is "complete" (dev bundle downloaded and all NPM modules + // installed). var getReady = function () { if (files.usesWarehouse()) { logging.die("meteor --get-ready only works in a checkout"); @@ -1006,8 +1009,6 @@ Fiber(function () { if (!files.in_checkout() && !process.env.METEOR_TEST_NO_SPRINGBOARD) toolsSpringboard(); - // Run this to ensure that your checkout's Meteor is "complete" (dev bundle - // downloaded and all NPM modules installed). if (argv['get-ready']) { getReady(); return; From fe1d61db4077675bf8d6d9a21731c1215aee75ed Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:27:51 -0700 Subject: [PATCH 06/11] more effective detection of stdout/err use for restart message --- tools/run.js | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/tools/run.js b/tools/run.js index 85e85c5ff4..87e9dbd098 100644 --- a/tools/run.js +++ b/tools/run.js @@ -217,7 +217,6 @@ var log_to_clients = function (msg) { // mongoURL // onExit // [onListen] -// [onStdio] // [nodeOptions] // [settingsFile] @@ -261,7 +260,6 @@ var start_server = function (options) { if (data.length != originalLength) options.onListen && options.onListen(); if (data) { - options.onStdio && options.onStdio(); log_to_clients({stdout: data}); } }); @@ -269,7 +267,6 @@ var start_server = function (options) { proc.stderr.setEncoding('utf8'); proc.stderr.on('data', function (data) { if (data) { - options.onStdio && options.onStdio(); log_to_clients({stderr: data}); } }); @@ -560,8 +557,6 @@ exports.run = function (context, options) { var mongo_url = process.env.MONGO_URL || ("mongodb://127.0.0.1:" + mongo_port + "/meteor"); var firstRun = true; - var lastThingThatPrintedWasRestartMessage; - var silentRuns = 0; var deps_info = null; var warned_about_no_deps_info = false; @@ -569,6 +564,34 @@ exports.run = function (context, options) { var server_handle; var watcher; + var lastThingThatPrintedWasRestartMessage = false; + var silentRuns = 0; + + // Hijack process.stdout and process.stderr so that whenever anything is + // written to one of them, if the last thing we printed as the "Meteor server + // restarted" message with no newline, we (a) print that newline and (b) + // remember that *something* was printed (and so we shouldn't try to erase and + // rewrite the line on the next restart). + var realStdoutWrite = process.stdout.write; + var realStderrWrite = process.stderr.write; + // Call this function before printing anything to stdout or stderr. + var onStdio = function () { + if (lastThingThatPrintedWasRestartMessage) { + realStdoutWrite.call(process.stdout, "\n"); + lastThingThatPrintedWasRestartMessage = false; + silentRuns = 0; + } + }; + process.stdout.write = function () { + onStdio(); + return realStdoutWrite.apply(process.stdout, arguments); + }; + process.stderr.write = function () { + onStdio(); + return realStderrWrite.apply(process.stderr, arguments); + }; + + if (options.once) { Status.shouldRestart = false; } @@ -682,12 +705,12 @@ exports.run = function (context, options) { // The last run was not the "Running on: " run, and it didn't print // anything. So the last thing that printed was the restart message. // Overwrite it. - process.stdout.write('\r'); + realStdoutWrite.call(process.stdout, '\r'); } - process.stdout.write("=> Meteor server restarted"); + realStdoutWrite.call(process.stdout, "=> Meteor server restarted"); if (lastThingThatPrintedWasRestartMessage) { ++silentRuns; - process.stdout.write(" (x" + (silentRuns+1) + ")"); + realStdoutWrite.call(process.stdout, " (x" + (silentRuns+1) + ")"); } lastThingThatPrintedWasRestartMessage = true; } @@ -712,13 +735,6 @@ exports.run = function (context, options) { _.each(request_queue, function (f) { f(); }); request_queue = []; }, - onStdio: function () { - if (lastThingThatPrintedWasRestartMessage) { - process.stdout.write("\n"); - lastThingThatPrintedWasRestartMessage = false; - silentRuns = 0; - } - }, nodeOptions: getNodeOptionsFromEnvironment(), settingsFile: options.settingsFile }); From 081a517baab1f2d0fd7c693bfb5d3a12669013e5 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:37:27 -0700 Subject: [PATCH 07/11] npm update message: don't include version (which can be long and ugly) --- tools/meteor_npm.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/meteor_npm.js b/tools/meteor_npm.js index acfae6afb3..9ab3e84269 100644 --- a/tools/meteor_npm.js +++ b/tools/meteor_npm.js @@ -353,10 +353,8 @@ _.extend(exports, { }, _logUpdateDependencies: function(packageName, npmDependencies) { - var npmDependenciesStr = _.map(npmDependencies, function(version, name) { - return name + '@' + version; - }).join(', '); - console.log(packageName + ': updating npm dependencies -- ' + npmDependenciesStr + '...'); + console.log('%s: updating npm dependencies -- %s...', + packageName, _.keys(npmDependencies).join(', ')); }, _randomToken: function() { From e989706d51fba7e8d7b06d0d670699b65081b4b1 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:41:57 -0700 Subject: [PATCH 08/11] avoid creating temporary package NPM dirs when nothing has changed --- tools/meteor_npm.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/tools/meteor_npm.js b/tools/meteor_npm.js index 9ab3e84269..f5a0b81b5c 100644 --- a/tools/meteor_npm.js +++ b/tools/meteor_npm.js @@ -60,16 +60,6 @@ _.extend(exports, { // randomize the name, in case we're bundling this package // multiple times in parallel. var newPackageNpmDir = packageNpmDir + '-new-' + self._randomToken(); - self._tmpDirs.push(newPackageNpmDir); // keep track so that we can remove them on process exit - fs.mkdirSync(newPackageNpmDir); - - // create .gitignore -- node_modules shouldn't be in git since we - // recreate it as needed by using `npm install`. since we use `npm - // shrinkwrap` we're guaranteed to have the same version installed - // each time. - fs.writeFileSync( - path.join(newPackageNpmDir, '.gitignore'), - ['node_modules', ''/*git diff complains without trailing newline*/].join('\n')); try { if (fs.existsSync(packageNpmDir)) { @@ -89,6 +79,20 @@ _.extend(exports, { } }, + _makeNewPackageNpmDir: function (newPackageNpmDir) { + var self = this; + self._tmpDirs.push(newPackageNpmDir); // keep track so that we can remove them on process exit + fs.mkdirSync(newPackageNpmDir); + + // create .gitignore -- node_modules shouldn't be in git since we + // recreate it as needed by using `npm install`. since we use `npm + // shrinkwrap` we're guaranteed to have the same version installed + // each time. + fs.writeFileSync( + path.join(newPackageNpmDir, '.gitignore'), + ['node_modules', ''/*git diff complains without trailing newline*/].join('\n')); + }, + _updateExistingNpmDirectory: function( packageName, newPackageNpmDir, packageNpmDir, npmDependencies, quiet) { var self = this; @@ -103,7 +107,6 @@ _.extend(exports, { var installedDependencies = self._installedDependencies(packageNpmDir); // If we already have the right things installed, life is good. - // XXX avoid creating and deleting newPackageNpmDir in this case? if (_.isEqual(installedDependencies, npmDependencies)) return; @@ -123,6 +126,8 @@ _.extend(exports, { } }); + self._makeNewPackageNpmDir(newPackageNpmDir); + if (!_.isEmpty(preservedShrinkwrap.dependencies)) { // There are some unchanged packages here. Install from shrinkwrap. fs.writeFileSync(path.join(newPackageNpmDir, 'npm-shrinkwrap.json'), @@ -164,6 +169,7 @@ _.extend(exports, { if (!quiet) self._logUpdateDependencies(packageName, npmDependencies); + self._makeNewPackageNpmDir(newPackageNpmDir); // install dependencies _.each(npmDependencies, function(version, name) { self._installNpmModule(name, version, newPackageNpmDir); From d9af3c210d7333b513aea2e9b6e088d7e7526d80 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:43:38 -0700 Subject: [PATCH 09/11] make run-tools-tests pass for a brief while --- scripts/cli-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli-test.sh b/scripts/cli-test.sh index 832d06e932..5c8ed06bc9 100755 --- a/scripts/cli-test.sh +++ b/scripts/cli-test.sh @@ -30,7 +30,7 @@ if [ "$METEOR_WAREHOUSE_DIR" ]; then # the current tools, in which case you can build and publish a new release # and set it here. export METEOR_TEST_NO_SPRINGBOARD=t - TEST_RELEASE="0.6.0-alpha1" + TEST_RELEASE="0.6.0" METEOR="$METEOR --release=$TEST_RELEASE" # some random non-official release fi From 88dedc5503c3c24f665e9e13fd3e558685968b1f Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:49:53 -0700 Subject: [PATCH 10/11] add newlines to "meteor deploy" output this way any NPM lines between "bundling..." and "uploading..." are less jarring --- tools/deploy.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/deploy.js b/tools/deploy.js index a8f783589d..9ab8cb6a67 100644 --- a/tools/deploy.js +++ b/tools/deploy.js @@ -90,7 +90,7 @@ var deployToServer = function (app_dir, bundleOptions, deployOptions) { var build_dir = path.join(app_dir, '.meteor', 'local', 'build_tar'); var bundle_path = path.join(build_dir, 'bundle'); - process.stdout.write('Deploying to ' + site + '. Bundling ... '); + process.stdout.write('Deploying to ' + site + '. Bundling...\n'); var bundler = require('./bundler.js'); var errors = bundler.bundle(app_dir, bundle_path, bundleOptions); if (errors) { @@ -102,7 +102,7 @@ var deployToServer = function (app_dir, bundleOptions, deployOptions) { process.exit(1); } - process.stdout.write('uploading ... '); + process.stdout.write('Uploading...\n'); var rpcOptions = {}; if (password) rpcOptions.password = password; @@ -120,8 +120,6 @@ var deployToServer = function (app_dir, bundleOptions, deployOptions) { process.exit(1); } - process.stdout.write('done.\n'); - var hostname = null; var response = null; try { From 421bd951c77fad18447af3b5d40297773d0ef76c Mon Sep 17 00:00:00 2001 From: David Glasser Date: Fri, 29 Mar 2013 22:57:12 -0700 Subject: [PATCH 11/11] in update message, only print basename --- tools/meteor.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/meteor.js b/tools/meteor.js index d342a21821..d16bce7cdf 100644 --- a/tools/meteor.js +++ b/tools/meteor.js @@ -447,9 +447,8 @@ Fiber(function () { // This is the right spot to do any other changes we need to the app in // order to update it for the new release (new metadata file formats, // etc, or maybe even updating renamed APIs). - // XXX should we really print the full path here (appDir)? (use pretty) console.log("%s: updated to Meteor %s.", - context.appDir, context.releaseVersion); + path.basename(context.appDir), context.releaseVersion); // Print any notices relevant to this upgrade. (We don't do this on an // initial upgrade to Engine Meteor.