mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge pull request #3232 from meteor/word-wrap-final
Automatically line-wrap output
This commit is contained in:
2
meteor
2
meteor
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
BUNDLE_VERSION=0.3.72 # 0.3.63 on the Windows branch
|
||||
BUNDLE_VERSION=0.3.74
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
# bundles that are arch specific.
|
||||
|
||||
@@ -33,6 +33,7 @@ var packageJson = {
|
||||
netroute: "0.2.5",
|
||||
phantomjs: "1.9.12",
|
||||
"http-proxy": "1.6.0",
|
||||
"wordwrap": "0.0.2",
|
||||
// XXX We ought to be able to get this from the copy in js-analyze rather
|
||||
// than in the dev bundle.)
|
||||
esprima: "1.2.2",
|
||||
|
||||
@@ -117,7 +117,6 @@ npm install
|
||||
npm dedupe
|
||||
cp -R node_modules/* "${DIR}/lib/node_modules/"
|
||||
|
||||
|
||||
cd "${DIR}/lib"
|
||||
|
||||
# TODO Move this into dev-bundle-tool-package.js when it can be safely
|
||||
@@ -142,6 +141,7 @@ delete browserstack-webdriver/docs
|
||||
delete browserstack-webdriver/lib/test
|
||||
|
||||
delete sqlite3/deps
|
||||
delete wordwrap/test
|
||||
|
||||
# dedupe isn't good enough to eliminate 3 copies of esprima, sigh.
|
||||
find . -path '*/esprima/test' | xargs rm -rf
|
||||
|
||||
@@ -58,9 +58,10 @@ exports.loggedInConnection = function (url, domain, sessionType) {
|
||||
|
||||
if (! auth.isLoggedIn()) {
|
||||
// XXX we should have a better account signup page.
|
||||
Console.stderr.write(
|
||||
"Please log in with your Meteor developer account. If you don't have one,\n" +
|
||||
"you can quickly create one at www.meteor.com.\n");
|
||||
Console.error(
|
||||
"Please log in with your Meteor developer account.",
|
||||
"If you don't have one,",
|
||||
"you can quickly create one at www.meteor.com.");
|
||||
auth.doUsernamePasswordLogin({ retry: true });
|
||||
}
|
||||
|
||||
@@ -78,10 +79,10 @@ exports.loggedInConnection = function (url, domain, sessionType) {
|
||||
if (err.message === "access-denied") {
|
||||
// Maybe we thought we were logged in, but our token had been
|
||||
// revoked.
|
||||
Console.stderr.write(
|
||||
"It looks like you have been logged out! Please log in with your Meteor\n" +
|
||||
"developer account. If you don't have one, you can quickly create one\n" +
|
||||
"at www.meteor.com.\n");
|
||||
Console.error(
|
||||
"It looks like you have been logged out!",
|
||||
"Please log in with your Meteor developer account. If you don't have",
|
||||
"one, you can quickly create one at www.meteor.com.");
|
||||
auth.doUsernamePasswordLogin({ retry: true });
|
||||
auth.loginWithTokenOrOAuth(
|
||||
conn,
|
||||
|
||||
120
tools/auth.js
120
tools/auth.js
@@ -336,11 +336,10 @@ var tryRevokeOldTokens = function (options) {
|
||||
var logoutFailWarning = function (domain) {
|
||||
if (! warned) {
|
||||
// This isn't ideal but is probably better that saying nothing at all
|
||||
process.stderr.write("warning: " +
|
||||
(options.firstTry ?
|
||||
"couldn't" : "still trying to") +
|
||||
" confirm logout with " + domain +
|
||||
"\n");
|
||||
Console.error("warning: " +
|
||||
(options.firstTry ?
|
||||
"couldn't" : "still trying to") +
|
||||
" confirm logout with " + domain);
|
||||
warned = true;
|
||||
}
|
||||
};
|
||||
@@ -603,7 +602,7 @@ var doInteractivePasswordLogin = function (options) {
|
||||
|
||||
var loginFailed = function () {
|
||||
if (! options.suppressErrorMessage) {
|
||||
process.stderr.write("Login failed.\n");
|
||||
Console.error("Login failed.");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -634,7 +633,7 @@ var doInteractivePasswordLogin = function (options) {
|
||||
} else {
|
||||
loginFailed();
|
||||
if (options.retry) {
|
||||
process.stderr.write("\n");
|
||||
Console.error();
|
||||
continue;
|
||||
} else {
|
||||
maybeCloseConnection();
|
||||
@@ -715,17 +714,18 @@ exports.loginCommand = withAccountsConnection(function (options,
|
||||
var galaxyLoginResult = logInToGalaxy(galaxy);
|
||||
if (galaxyLoginResult.error) {
|
||||
// XXX add human readable error messages
|
||||
process.stderr.write('\nLogin to ' + galaxy + ' failed. ');
|
||||
|
||||
var failedLoginMsg = "\nLogin to ' + galaxy + ' failed. ";
|
||||
if (galaxyLoginResult.error === 'unauthorized') {
|
||||
process.stderr.write('You are not authorized for this galaxy.\n');
|
||||
Console.error(
|
||||
failedLoginMsg + 'You are not authorized for this galaxy.');
|
||||
} else if (galaxyLoginResult.error === 'no_oauth_server') {
|
||||
process.stderr.write('The galaxy could not ' +
|
||||
'contact Meteor Accounts.\n');
|
||||
Console.error(
|
||||
failedLoginMsg + 'The galaxy could not contact Meteor Accounts.');
|
||||
} else if (galaxyLoginResult.error === 'no_identity') {
|
||||
process.stderr.write('Your login information could not be found.\n');
|
||||
Console.error(
|
||||
failedLoginMsg + 'Your login information could not be found.');
|
||||
} else {
|
||||
process.stderr.write('Error: ' + galaxyLoginResult.error + '\n');
|
||||
Console.error(failedLoginMsg + 'Error: ' + galaxyLoginResult.error );
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -741,10 +741,11 @@ exports.loginCommand = withAccountsConnection(function (options,
|
||||
tryRevokeOldTokens({ firstTry: true, connection: connection });
|
||||
|
||||
data = readSessionData();
|
||||
process.stderr.write("\nLogged in" + (galaxy ? " to " + galaxy : "") +
|
||||
(currentUsername(data) ?
|
||||
" as " + currentUsername(data) : "") + ".\n" +
|
||||
"Thanks for being a Meteor developer!\n");
|
||||
Console.error();
|
||||
Console.error("Logged in" + (galaxy ? " to " + galaxy : "") +
|
||||
(currentUsername(data) ?
|
||||
" as " + currentUsername(data) : "") + "." +
|
||||
"Thanks for being a Meteor developer!");
|
||||
return 0;
|
||||
});
|
||||
|
||||
@@ -759,11 +760,11 @@ exports.logoutCommand = function (options) {
|
||||
tryRevokeOldTokens({ firstTry: true });
|
||||
|
||||
if (wasLoggedIn)
|
||||
process.stderr.write("Logged out.\n");
|
||||
Console.error("Logged out.");
|
||||
else
|
||||
// We called logOutAllSessions/writeSessionData anyway, out of an
|
||||
// abundance of caution.
|
||||
process.stderr.write("Not logged in.\n");
|
||||
Console.error("Not logged in.");
|
||||
};
|
||||
|
||||
// If this is fully set up account (with a username and password), or
|
||||
@@ -845,25 +846,25 @@ exports.whoAmICommand = function (options) {
|
||||
|
||||
var data = readSessionData();
|
||||
if (! loggedIn(data)) {
|
||||
process.stderr.write("Not logged in. 'meteor login' to log in.\n");
|
||||
Console.error(
|
||||
"Not logged in. " + Console.command("'meteor login'") + " to log in.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var username = currentUsername(data);
|
||||
if (username) {
|
||||
process.stdout.write(username + "\n");
|
||||
Console.rawInfo(username + "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
var url = getSession(data, config.getAccountsDomain()).registrationUrl;
|
||||
if (url) {
|
||||
process.stderr.write(
|
||||
"You haven't chosen your username yet. To pick it, go here:\n" +
|
||||
"\n" +
|
||||
url + "\n");
|
||||
Console.error("You haven't chosen your username yet. To pick it, go here:");
|
||||
Console.error();
|
||||
Console.error(Console.url(url));
|
||||
} else {
|
||||
// Won't happen in normal operation
|
||||
process.stderr.write("You haven't chosen your username yet.\n");
|
||||
Console.error("You haven't chosen your username yet.");
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -893,11 +894,13 @@ exports.registerOrLogIn = withAccountsConnection(function (connection) {
|
||||
break;
|
||||
} catch (err) {
|
||||
if (err.error === 400 && ! utils.validEmail(email)) {
|
||||
if (email.trim().length)
|
||||
process.stderr.write("Please double-check that address.\n\n");
|
||||
if (email.trim().length) {
|
||||
Console.error("Please double-check that address.");
|
||||
Console.error();
|
||||
}
|
||||
} else {
|
||||
process.stderr.write("\nCouldn't connect to server. " +
|
||||
"Check your internet connection.\n");
|
||||
Console.error("\nCouldn't connect to server. " +
|
||||
"Check your internet connection.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -917,10 +920,11 @@ exports.registerOrLogIn = withAccountsConnection(function (connection) {
|
||||
writeSessionData(data);
|
||||
return true;
|
||||
} else if (result.alreadyExisted && result.sentRegistrationEmail) {
|
||||
process.stderr.write(
|
||||
"\n" +
|
||||
"You need to pick a password for your account so that you can log in.\n" +
|
||||
"An email has been sent to you with the link.\n\n");
|
||||
Console.error();
|
||||
Console.error(
|
||||
"You need to pick a password for your account so that you can log in.",
|
||||
"An email has been sent to you with the link.");
|
||||
Console.error();
|
||||
|
||||
var animationFrame = 0;
|
||||
var lastLinePrinted = "";
|
||||
@@ -928,12 +932,12 @@ exports.registerOrLogIn = withAccountsConnection(function (connection) {
|
||||
var spinner = ['-', '\\', '|', '/'];
|
||||
lastLinePrinted = "Waiting for you to register on the web... " +
|
||||
spinner[animationFrame];
|
||||
process.stderr.write(lastLinePrinted + "\r");
|
||||
Console.rawError(lastLinePrinted + "\r");
|
||||
animationFrame = (animationFrame + 1) % spinner.length;
|
||||
}, 200);
|
||||
var stopSpinner = function () {
|
||||
process.stderr.write(new Array(lastLinePrinted.length + 1).join(' ') +
|
||||
"\r");
|
||||
Console.rawError(new Array(lastLinePrinted.length + 1).join(' ') +
|
||||
"\r");
|
||||
clearInterval(timer);
|
||||
};
|
||||
|
||||
@@ -946,14 +950,14 @@ exports.registerOrLogIn = withAccountsConnection(function (connection) {
|
||||
stopSpinner();
|
||||
if (e.errorType !== "Meteor.Error")
|
||||
throw e;
|
||||
process.stderr.write(
|
||||
"When you've picked your password, run 'meteor login' to log in.\n")
|
||||
Console.error(
|
||||
"When you've picked your password, run " +
|
||||
Console.command("'meteor login'") + " to log in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
stopSpinner();
|
||||
process.stderr.write("Username: " +
|
||||
waitForRegistrationResult.username + "\n");
|
||||
Console.error("Username: " + waitForRegistrationResult.username);
|
||||
loginResult = doInteractivePasswordLogin({
|
||||
username: waitForRegistrationResult.username,
|
||||
retry: true,
|
||||
@@ -961,7 +965,7 @@ exports.registerOrLogIn = withAccountsConnection(function (connection) {
|
||||
});
|
||||
return loginResult;
|
||||
} else if (result.alreadyExisted && result.username) {
|
||||
process.stderr.write("\nLogging in as " + result.username + ".\n");
|
||||
Console.error("\nLogging in as " + Console.command(result.username) + ".");
|
||||
|
||||
loginResult = doInteractivePasswordLogin({
|
||||
username: result.username,
|
||||
@@ -971,8 +975,9 @@ exports.registerOrLogIn = withAccountsConnection(function (connection) {
|
||||
return loginResult;
|
||||
} else {
|
||||
// Hmm, got an email we don't understand.
|
||||
process.stderr.write(
|
||||
"\nThere was a problem. Please log in with 'meteor login'.\n");
|
||||
Console.error(
|
||||
"\nThere was a problem. Please log in with " +
|
||||
Console.command("'meteor login'") + ".");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@@ -989,26 +994,29 @@ exports.maybePrintRegistrationLink = function (options) {
|
||||
|
||||
if (session.userId && ! session.username && session.registrationUrl) {
|
||||
if (options.leadingNewline)
|
||||
process.stderr.write("\n");
|
||||
Console.error();
|
||||
if (options.onlyAllowIfRegistered) {
|
||||
// A stronger message: we're going to not allow whatever they were trying
|
||||
// to do!
|
||||
process.stderr.write(
|
||||
"You need to claim a username and set a password on your Meteor developer\n" +
|
||||
"account to run this command. It takes about a minute at:\n" +
|
||||
" " + session.registrationUrl + "\n");
|
||||
Console.error(
|
||||
"You need to claim a username and set a password on your Meteor",
|
||||
"developer account to run this command. It takes about a minute at:",
|
||||
session.registrationUrl);
|
||||
Console.error();
|
||||
} else if (! options.firstTime) {
|
||||
// If they've already been prompted to set a password then this
|
||||
// is more of a friendly reminder, so we word it slightly
|
||||
// differently than the first time they're being shown a
|
||||
// registration url.
|
||||
process.stderr.write(
|
||||
"You should set a password on your Meteor developer account. It takes\n" +
|
||||
"about a minute at: " + session.registrationUrl + "\n\n");
|
||||
Console.error(
|
||||
"You should set a password on your Meteor developer account.",
|
||||
"It takes about a minute at:", session.registrationUrl);
|
||||
Console.error();
|
||||
} else {
|
||||
process.stderr.write(
|
||||
"You can set a password on your account or change your email address at:\n" +
|
||||
session.registrationUrl + "\n\n");
|
||||
Console.error(
|
||||
"You can set a password on your account or change your email",
|
||||
"address at:" + session.registrationUrl);
|
||||
Console.error();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,17 +90,17 @@ cordova.buildTargets = function (projectContext, targets, options) {
|
||||
|
||||
if (! inProject) {
|
||||
if (! supported) {
|
||||
Console.warn(Console.fail(MESSAGE_IOS_ONLY_ON_MAC));
|
||||
Console.failWarn(MESSAGE_IOS_ONLY_ON_MAC);
|
||||
} else {
|
||||
Console.warn("Please add the " + displayPlatform +
|
||||
" platform to your project first.");
|
||||
if (! hasSdk) {
|
||||
Console.info("First install the SDK by running: " +
|
||||
Console.bold("meteor install-sdk " + platform));
|
||||
Console.command("meteor install-sdk " + platform));
|
||||
Console.info("Then run: " +
|
||||
Console.bold("meteor add-platform " + platform));
|
||||
Console.command("meteor add-platform " + platform));
|
||||
} else {
|
||||
Console.info("Run: " + Console.bold("meteor add-platform " + platform));
|
||||
Console.info("Run: " + Console.command("meteor add-platform " + platform));
|
||||
}
|
||||
}
|
||||
throw new main.ExitWithCode(2);
|
||||
@@ -115,9 +115,9 @@ cordova.buildTargets = function (projectContext, targets, options) {
|
||||
if (supported)
|
||||
Console.warn("The " + displayPlatform + " platform is not installed;" +
|
||||
" please run: " +
|
||||
Console.bold("meteor install-sdk " + platform));
|
||||
Console.command("meteor install-sdk " + platform));
|
||||
else
|
||||
Console.warn(Console.fail(MESSAGE_IOS_ONLY_ON_MAC));
|
||||
Console.failWarn(MESSAGE_IOS_ONLY_ON_MAC);
|
||||
|
||||
throw new main.ExitWithCode(2);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ var setVerboseness = cordova.setVerboseness = function (v) {
|
||||
};
|
||||
var verboseLog = cordova.verboseLog = function (/* args */) {
|
||||
if (verboseness)
|
||||
Console.stderr.write('%% ' + util.format.apply(null, arguments) + '\n');
|
||||
Console.rawError('%% ' + util.format.apply(null, arguments) + "\n");
|
||||
};
|
||||
|
||||
|
||||
@@ -374,8 +374,8 @@ var ensureCordovaProject = function (projectContext, appName) {
|
||||
if (err instanceof main.ExitWithCode) {
|
||||
process.exit(err.code);
|
||||
}
|
||||
Console.stderr.write("Error creating Cordova project: " +
|
||||
err.message + "\n" + err.stack + "\n");
|
||||
Console.error("Error creating Cordova prject: " + err.message);
|
||||
Console.rawError(err.stack + "\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -904,14 +904,16 @@ var CordovaRunner = function (projectContext, platformName, options) {
|
||||
// projectContext being asynchronously reset.)
|
||||
if (self.platformName !== "ios" &&
|
||||
self.projectContext.packageMap.getInfo('oauth2')) {
|
||||
Console.warn(
|
||||
"\n" +
|
||||
"WARNING: It looks like you are using OAuth2 login in your app.\n" +
|
||||
" Meteor's OAuth2 implementation does not currently work with\n" +
|
||||
" mobile apps in local development mode, except in the iOS\n" +
|
||||
" simulator. You can run the iOS simulator with 'meteor run ios'.\n" +
|
||||
" For additional workarounds, see\n" +
|
||||
" https://github.com/meteor/meteor/wiki/OAuth-for-mobile-Meteor-clients.\n");
|
||||
Console.warn();
|
||||
Console.labelWarn(
|
||||
"It looks like you are using OAuth2 login in your app. " +
|
||||
"Meteor's OAuth2 implementation does not currently work with " +
|
||||
"mobile apps in local development mode, except in the iOS " +
|
||||
"simulator. You can run the iOS simulator with 'meteor run ios'. " +
|
||||
"For additional workarounds, see " +
|
||||
Console.url(
|
||||
"https://github.com/meteor/meteor/wiki/" +
|
||||
"OAuth-for-mobile-Meteor-clients."));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1030,30 +1032,29 @@ var execCordovaOnPlatform = function (projectContext, platformName, options) {
|
||||
try {
|
||||
execFileSyncOrThrow('sh', args);
|
||||
} catch (err) {
|
||||
Console.stderr.write([
|
||||
"",
|
||||
chalk.green("Could not open your project in Xcode."),
|
||||
chalk.green("Try running again with the --verbose option."),
|
||||
chalk.green("Instructions for running your app on an iOS device:"),
|
||||
chalk.cyan("https://github.com/meteor/meteor/wiki/How-to-run-your-app-on-an-iOS-device"),
|
||||
""
|
||||
].join("\n"));
|
||||
|
||||
Console.error();
|
||||
Console.error(chalk.green("Could not open your project in Xcode."));
|
||||
Console.error(chalk.green("Try running again with the --verbose option."));
|
||||
Console.error(
|
||||
chalk.green("Instructions for running your app on an iOS device: ") +
|
||||
Console.url(
|
||||
"https://github.com/meteor/meteor/wiki/" +
|
||||
"How-to-run-your-app-on-an-iOS-device")
|
||||
);
|
||||
Console.error();
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
Console.stdout.write([
|
||||
"",
|
||||
chalk.green([
|
||||
"Your project has been opened in Xcode so that you can run your app on ",
|
||||
"an iOS device. For further instructions, visit this wiki page:",
|
||||
].join("\n")),
|
||||
chalk.cyan(
|
||||
"https://github.com/meteor/meteor/wiki/How-to-run-your-app-on-an-iOS-device"
|
||||
),
|
||||
""
|
||||
].join("\n"));
|
||||
|
||||
Console.info();
|
||||
Console.info(
|
||||
chalk.green(
|
||||
"Your project has been opened in Xcode so that you can run your " +
|
||||
"app on an iOS device. For further instructions, visit this " +
|
||||
"wiki page: ") +
|
||||
Console.url(
|
||||
"https://github.com/meteor/meteor/wiki/" +
|
||||
"How-to-run-your-app-on-an-iOS-device"
|
||||
));
|
||||
Console.info();
|
||||
} else {
|
||||
verboseLog('Running emulator:', localCordova, args);
|
||||
var emulatorOptions = { verbose: options.verbose, cwd: cordovaPath };
|
||||
@@ -1068,35 +1069,31 @@ var execCordovaOnPlatform = function (projectContext, platformName, options) {
|
||||
localCordova, args, emulatorOptions,
|
||||
function(err, code) {
|
||||
if (err && platform === "android" && isDevice) {
|
||||
Console.stderr.write([
|
||||
"",
|
||||
chalk.green("Could not start the app on your device. Is it plugged in?"),
|
||||
chalk.green("Try running again with the --verbose option."),
|
||||
chalk.green("Instructions for running your app on an Android device:"),
|
||||
chalk.cyan("https://github.com/meteor/meteor/wiki/How-to-run-your-app-on-an-Android-device"),
|
||||
""
|
||||
].join("\n"));
|
||||
Console.error();
|
||||
Console.error(
|
||||
chalk.green("Could not start the app on your device. Is it plugged in?"));
|
||||
Console.error("Try running again with the --verbose option.");
|
||||
Console.error(
|
||||
chalk.green("Instructions for running your app on an Android device: ") +
|
||||
Console.url(
|
||||
"https://github.com/meteor/meteor/wiki/" +
|
||||
"How-to-run-your-app-on-an-Android-device"));
|
||||
Console.error();
|
||||
} else if (err && platform === "android") {
|
||||
Console.stderr.write([
|
||||
"",
|
||||
chalk.green("Could not start the app in the Android emulator."),
|
||||
chalk.green("Try running again with the --verbose option."),
|
||||
""
|
||||
].join("\n"));
|
||||
Console.error();
|
||||
Console.error(chalk.green("Could not start the app in the Android emulator."));
|
||||
Console.error(chalk.green("Try running again with the --verbose option."));
|
||||
Console.error();
|
||||
} else if (err && platform === "ios") {
|
||||
Console.stderr.write([
|
||||
"",
|
||||
chalk.green("Could not start the app in the iOS simulator."),
|
||||
chalk.green("Try running again with the --verbose option."),
|
||||
""
|
||||
].join("\n"));
|
||||
Console.error();
|
||||
Console.error(chalk.green("Could not start the app in the iOS simulator."));
|
||||
Console.error(chalk.green("Try running again with the --verbose option."));
|
||||
Console.error();
|
||||
} else if (err) {
|
||||
Console.stderr.write([
|
||||
"",
|
||||
chalk.green("Could not start your app."),
|
||||
chalk.green("Try running again with the --verbose option."),
|
||||
""
|
||||
].join("\n"));
|
||||
Console.error();
|
||||
Console.error(chalk.green("Could not start your app."));
|
||||
Console.error(chalk.green("Try running again with the --verbose option."));
|
||||
Console.error();
|
||||
}
|
||||
|
||||
// Don't throw an error or print the stack trace, but still exit the
|
||||
@@ -1292,9 +1289,12 @@ var checkAgreePlatformTerms = function (platform, name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.stdout.write("The following terms apply to " + name + ":\n\n");
|
||||
Console.stdout.write(terms + "\n\n");
|
||||
Console.stdout.write("You must agree to the terms to proceed.\n");
|
||||
Console.info("The following terms apply to " + name + ":");
|
||||
Console.info();
|
||||
Console.info(terms);
|
||||
Console.info();
|
||||
Console.info("You must agree to the terms to proceed.");
|
||||
Console.info();
|
||||
|
||||
var agreed = false;
|
||||
|
||||
@@ -1312,7 +1312,8 @@ var checkAgreePlatformTerms = function (platform, name) {
|
||||
};
|
||||
|
||||
var checkPlatformRequirements = function (platform, options) {
|
||||
options = _.extend({log: false, fix: false, fixConsole: false, fixSilent: false}, options);
|
||||
options = _.extend(
|
||||
{ log: false, fix: false, fixConsole: false, fixSilent: false }, options);
|
||||
if (platform == 'android') {
|
||||
return Android.checkRequirements(options);
|
||||
} else if (platform == 'ios') {
|
||||
@@ -1327,7 +1328,9 @@ var requirePlatformReady = function (platform) {
|
||||
try {
|
||||
var installed = checkPlatformRequirements(platform);
|
||||
if (!installed.acceptable) {
|
||||
Console.warn("The " + platformToHuman(platform) + " platform is not installed; please run: " + Console.bold("meteor install-sdk " + platform));
|
||||
Console.warn(
|
||||
"The " + platformToHuman(platform) + " platform is not installed;",
|
||||
"please run: " + Console.command("meteor install-sdk " + platform));
|
||||
throw new main.ExitWithCode(2);
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -1336,7 +1339,8 @@ var requirePlatformReady = function (platform) {
|
||||
} else if (err instanceof main.ExitWithCode) {
|
||||
throw err;
|
||||
} else {
|
||||
Console.warn("Unexpected error while checking platform requirements: ", err);
|
||||
Console.warn(
|
||||
"Unexpected error while checking platform requirements: ", err);
|
||||
}
|
||||
throw new main.ExitWithCode(2);
|
||||
}
|
||||
@@ -1787,7 +1791,9 @@ _.extend(IOS.prototype, {
|
||||
}
|
||||
|
||||
buildmessage.enterJob({title: 'Installing Xcode'}, function () {
|
||||
//Console.info("Launching Xcode installer; please choose 'Get Xcode' to install Xcode");
|
||||
//Console.info(
|
||||
// "Launching Xcode installer;",
|
||||
// "please choose 'Get Xcode' to install Xcode");
|
||||
//files.run('/usr/bin/xcodebuild', '--install');
|
||||
|
||||
// XXX: Any way to open direct in AppStore (rather than in browser)?
|
||||
@@ -1832,7 +1838,9 @@ _.extend(IOS.prototype, {
|
||||
var fix = !!options.fix;
|
||||
|
||||
if (!Host.isMac()) {
|
||||
log && Console.info("You are not running on OSX; we won't be able to install Xcode for local iOS development");
|
||||
log && Console.info(
|
||||
"You are not running on OSX;",
|
||||
"we won't be able to install Xcode for local iOS development");
|
||||
return { acceptable: false, missing: [ "ios" ] };
|
||||
}
|
||||
|
||||
@@ -1840,14 +1848,14 @@ _.extend(IOS.prototype, {
|
||||
|
||||
var okay = true;
|
||||
if (self.hasXcode()) {
|
||||
log && Console.info(Console.success("Xcode is installed"));
|
||||
log && Console.success("Xcode is installed");
|
||||
} else {
|
||||
if (fix) {
|
||||
log && Console.info("Installing Xcode");
|
||||
|
||||
self.installXcode();
|
||||
} else {
|
||||
log && Console.info(Console.fail("Xcode is not installed"));
|
||||
log && Console.failInfo("Xcode is not installed");
|
||||
|
||||
result.missing.push("xcode");
|
||||
result.acceptable = false;
|
||||
@@ -1864,7 +1872,7 @@ _.extend(IOS.prototype, {
|
||||
|
||||
if (self.hasXcode()) {
|
||||
if (self.hasAgreedXcodeLicense()) {
|
||||
log && Console.info(Console.success("Xcode license agreed"));
|
||||
log && Console.success("Xcode license agreed");
|
||||
} else {
|
||||
if (fix) {
|
||||
log && Console.info("Please accept the Xcode license");
|
||||
@@ -1873,7 +1881,7 @@ _.extend(IOS.prototype, {
|
||||
|
||||
// XXX: Wait?
|
||||
} else {
|
||||
log && Console.info(Console.fail("You must accept the Xcode license"));
|
||||
log && Console.failInfo("You must accept the Xcode license");
|
||||
|
||||
result.missing.push("xcode-license");
|
||||
result.acceptable = false;
|
||||
@@ -1882,14 +1890,17 @@ _.extend(IOS.prototype, {
|
||||
}
|
||||
|
||||
_.each(['5.0', '5.0.1', '5.1', '6.0', '6.1'], function (version) {
|
||||
if (self.isSdkInstalled(version)) {
|
||||
log && Console.warn("An old version of the iPhone SDK is installed (" + version + "); you should");
|
||||
log && Console.warn("probably delete it. With SDK versions prior to 7.0 installed, your apps");
|
||||
log && Console.warn("can't be published to the App Store. Moreover, some Cordova plugins are");
|
||||
log && Console.warn("incompatible with this SDK.");
|
||||
log && Console.info("You can remove it by deleting this directory: ");
|
||||
log && Console.info(" " + self.getDirectoryForSdk(version));
|
||||
|
||||
if (self.isSdkInstalled(version) && log) {
|
||||
Console.warn(
|
||||
"An old version of the iPhone SDK is installed",
|
||||
Console.noWrap("(" + version + ")") + ";",
|
||||
"you should probably delete it. With SDK versions prior to 7.0",
|
||||
"installed, your apps can't be published to the App Store.",
|
||||
"Moreover, some Cordova plugins are incompatible with this SDK.",
|
||||
"You can remove it by deleting this directory: ");
|
||||
Console.warn(
|
||||
Console.path(self.getDirectoryForSdk(version)),
|
||||
Console.options({ indent: 4 }));
|
||||
// Not really a failure; just warn...
|
||||
}
|
||||
});
|
||||
@@ -1935,7 +1946,9 @@ _.extend(Android.prototype, {
|
||||
return stat != null;
|
||||
}
|
||||
|
||||
Console.info("Can't determine acceleration for unknown host: ", archinfo.host());
|
||||
Console.info(
|
||||
"Can't determine acceleration for unknown host: ",
|
||||
Console.noWrap(archinfo.host()));
|
||||
return undefined;
|
||||
},
|
||||
|
||||
@@ -1956,7 +1969,9 @@ _.extend(Android.prototype, {
|
||||
files.mkdir_p(dir);
|
||||
fs.writeFileSync(filepath, mpkg);
|
||||
|
||||
Console.info("Launching HAXM installer; we recommend allocating 1024MB of RAM (or more)");
|
||||
Console.info(
|
||||
"Launching HAXM installer;",
|
||||
"we recommend allocating 1024MB of RAM (or more)");
|
||||
files.run('open', filepath);
|
||||
|
||||
return;
|
||||
@@ -1969,7 +1984,8 @@ _.extend(Android.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("Can't install acceleration for unknown host: " + archinfo.host());
|
||||
throw new Error(
|
||||
"Can't install acceleration for unknown host: " + archinfo.host());
|
||||
},
|
||||
|
||||
useGlobalAdk: function () {
|
||||
@@ -1998,7 +2014,8 @@ _.extend(Android.prototype, {
|
||||
}
|
||||
|
||||
if (!optional && !androidSdkPath) {
|
||||
throw new Error("Cannot find Android SDK; be sure the 'android' tool is on your path");
|
||||
throw new Error(
|
||||
"Cannot find Android SDK; be sure the 'android' tool is on your path");
|
||||
}
|
||||
|
||||
Console.debug("Using (global) Android SDK at", androidSdkPath);
|
||||
@@ -2054,9 +2071,10 @@ _.extend(Android.prototype, {
|
||||
}
|
||||
|
||||
if (execution.exitCode !== 0) {
|
||||
Console.warn("Unexpected exit code from android process: " + execution.exitCode);
|
||||
Console.warn("stdout: " + execution.stdout);
|
||||
Console.warn("stderr: " + execution.stderr);
|
||||
Console.warn(
|
||||
"Unexpected exit code from android process: " + execution.exitCode);
|
||||
Console.rawWarn("stdout: " + execution.stdout + "\n");
|
||||
Console.rawWarn("stderr: " + execution.stderr + "\n");
|
||||
|
||||
throw new Error("Error running android tool: exit code " + execution.exitCode);
|
||||
}
|
||||
@@ -2175,9 +2193,9 @@ _.extend(Android.prototype, {
|
||||
if (execution.exitCode !== 0) {
|
||||
Console.debug("Unable to run aapt." +
|
||||
" (This is normal if 32 bit libraries are not found)");
|
||||
Console.debug(" exit code: " + execution.exitCode);
|
||||
Console.debug(" stdout: " + execution.stdout);
|
||||
Console.debug(" stderr: " + execution.stderr);
|
||||
Console.rawDebug(" exit code: " + execution.exitCode + "\n");
|
||||
Console.rawDebug(" stdout: " + execution.stdout + "\n");
|
||||
Console.rawDebug(" stderr: " + execution.stderr + "\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -2376,25 +2394,38 @@ _.extend(Android.prototype, {
|
||||
|
||||
if (Host.hasAptGet()) {
|
||||
Console.info("You can install the JDK using:");
|
||||
Console.info(" sudo apt-get install --yes openjdk-7-jdk");
|
||||
Console.info(
|
||||
Console.comand("sudo apt-get install --yes openjdk-7-jdk"),
|
||||
Console.options({ indent: 2 }));
|
||||
|
||||
// XXX: Technically, these are for Android, not installing Java
|
||||
if (processor == "x86_64") {
|
||||
Console.info("You will also need some 32-bit libraries:");
|
||||
Console.info(" sudo apt-get install --yes lib32z1 lib32stdc++6");
|
||||
Console.info(
|
||||
Console.command("sudo apt-get install --yes lib32z1 lib32stdc++6"),
|
||||
Console.options({ indent: 2 }));
|
||||
}
|
||||
} else if (Host.hasYum()) {
|
||||
Console.info("You can install the JDK using:");
|
||||
Console.info(" sudo yum install -y java-1.7.0-openjdk-devel");
|
||||
Console.info(
|
||||
Console.command("sudo yum install -y java-1.7.0-openjdk-devel"),
|
||||
Console.options({ indent: 2 }));
|
||||
|
||||
// XXX: Technically, these are for Android, not installing Java
|
||||
if (processor == "x86_64") {
|
||||
Console.info("You will also need some 32-bit libraries:");
|
||||
Console.info(" sudo yum install -y glibc.i686 zlib.i686 libstdc++.i686 ncurses-libs.i686");
|
||||
Console.info(
|
||||
Console.command(
|
||||
"sudo yum install -y glibc.i686 zlib.i686 " +
|
||||
"libstdc++.i686 ncurses-libs.i686"),
|
||||
Console.options({ indent: 2 }));
|
||||
}
|
||||
} else {
|
||||
Console.warn("You should install the JDK; we don't have instructions for your distribution (sorry!)");
|
||||
Console.info("Please do submit the instructions so we can include them.")
|
||||
Console.warn(
|
||||
"You should install the JDK; we don't have instructions",
|
||||
"for your distribution (sorry!)");
|
||||
Console.info(
|
||||
"Please do submit the instructions so we can include them.");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -2463,9 +2494,10 @@ _.extend(Android.prototype, {
|
||||
}
|
||||
|
||||
if (execution.exitCode != 0) {
|
||||
Console.warn("Unexpected exit code from script: " + execution.exitCode);
|
||||
Console.warn("stdout: " + execution.stdout);
|
||||
Console.warn("stderr: " + execution.stderr);
|
||||
Console.warn(
|
||||
"Unexpected exit code from script: " + execution.exitCode);
|
||||
Console.rawWarn("stdout: " + execution.stdout + "\n");
|
||||
Console.rawWarn("stderr: " + execution.stderr + "\n");
|
||||
throw new Error('Could not download Android bundle');
|
||||
}
|
||||
});
|
||||
@@ -2484,8 +2516,12 @@ _.extend(Android.prototype, {
|
||||
|
||||
// Boost timeout if not running HAXM/KVM
|
||||
if (self.hasAcceleration() === false) {
|
||||
Console.warn("Android emulator acceleration was not installed; the emulator will be very slow.");
|
||||
Console.info("You can run '" + Console.command("meteor install-sdk android") + "' for help.")
|
||||
Console.warn(
|
||||
"Android emulator acceleration was not installed;",
|
||||
"the emulator will be very slow.");
|
||||
Console.info(
|
||||
"You can run '" +
|
||||
Console.command("meteor install-sdk android") + "' for help.");
|
||||
timeLimit *= 4;
|
||||
}
|
||||
|
||||
@@ -2503,11 +2539,15 @@ _.extend(Android.prototype, {
|
||||
Console.error("The emulator did not start in the expected time.");
|
||||
if (self.hasAcceleration() === false) {
|
||||
if (Host.isLinux()) {
|
||||
Console.info("We highly recommend enabling KVM to speed up the emulator.");
|
||||
Console.info(
|
||||
"We highly recommend enabling KVM to speed up the emulator.");
|
||||
} else {
|
||||
Console.info("We highly recommend installing HAXM to speed up the emulator.");
|
||||
Console.info(
|
||||
"We highly recommend installing HAXM to speed up the emulator.");
|
||||
}
|
||||
Console.info("You can run '" + Console.command("meteor install-sdk android") + "' for help.")
|
||||
Console.info(
|
||||
"You can run '" +
|
||||
Console.command("meteor install-sdk android") + "' for help.");
|
||||
}
|
||||
|
||||
throw new main.ExitWithCode(1);
|
||||
@@ -2552,7 +2592,7 @@ _.extend(Android.prototype, {
|
||||
device[kv[0]] = kv[1];
|
||||
}
|
||||
devices.push(device);
|
||||
Console.debug("Found device", JSON.stringify(device));
|
||||
Console.rawDebug("Found device", JSON.stringify(device) + "\n");
|
||||
});
|
||||
return devices;
|
||||
},
|
||||
@@ -2581,7 +2621,7 @@ _.extend(Android.prototype, {
|
||||
var hasAndroid = false;
|
||||
if (!self.useGlobalAdk()) {
|
||||
if (self.hasAndroidBundle()) {
|
||||
log && Console.info(Console.success("Found Android bundle"));
|
||||
log && Console.success("Found Android bundle");
|
||||
hasAndroid = true;
|
||||
} else {
|
||||
if (fixConsole) {
|
||||
@@ -2590,7 +2630,7 @@ _.extend(Android.prototype, {
|
||||
self.installAndroidBundle();
|
||||
hasAndroid = true;
|
||||
} else {
|
||||
log && Console.info(Console.fail("Android bundle not found"));
|
||||
log && Console.failInfo("Android bundle not found");
|
||||
|
||||
result.missing.push("android-bundle");
|
||||
result.acceptable = false;
|
||||
@@ -2601,14 +2641,14 @@ _.extend(Android.prototype, {
|
||||
if (self.useGlobalAdk()) {
|
||||
var androidSdk = self.findAndroidSdk(true);
|
||||
if (androidSdk) {
|
||||
log && Console.info(Console.success("Found Android SDK"));
|
||||
log && Console.success("Found Android SDK");
|
||||
|
||||
// XXX: Verify
|
||||
hasAndroid = true;
|
||||
} else {
|
||||
log && Console.info(Console.fail("Android SDK not found"));
|
||||
|
||||
log && Console.info("If you set USE_GLOBAL_ADK, the 'android' tool must be on your path");
|
||||
log && Console.failInfo("Android SDK not found");
|
||||
log && Console.info(
|
||||
"If you set USE_GLOBAL_ADK, the 'android' tool must be on your path");
|
||||
|
||||
result.missing.push("android-global-sdk");
|
||||
result.acceptable = false;
|
||||
@@ -2616,9 +2656,9 @@ _.extend(Android.prototype, {
|
||||
|
||||
var hasAnt = !!Host.which("ant");
|
||||
if (hasAnt) {
|
||||
log && Console.info(Console.success("Found ant on PATH"));
|
||||
log && Console.success("Found ant on PATH");
|
||||
} else {
|
||||
log && Console.info(Console.fail("Ant not found on PATH"));
|
||||
log && Console.failInfo("Ant not found on PATH");
|
||||
|
||||
result.missing.push("apache-ant");
|
||||
result.acceptable = false;
|
||||
@@ -2627,7 +2667,7 @@ _.extend(Android.prototype, {
|
||||
|
||||
var hasJava = false;
|
||||
if (self.hasJdk()) {
|
||||
log && Console.info(Console.success("A JDK is installed"));
|
||||
log && Console.success("A JDK is installed");
|
||||
hasJava = true;
|
||||
} else {
|
||||
if (fix) {
|
||||
@@ -2636,7 +2676,7 @@ _.extend(Android.prototype, {
|
||||
self.installJdk();
|
||||
hasJava = true;
|
||||
} else {
|
||||
log && Console.info(Console.fail("A JDK is not installed"));
|
||||
log && Console.failInfo("A JDK is not installed");
|
||||
|
||||
result.missing.push("jdk");
|
||||
result.acceptable = false;
|
||||
@@ -2645,16 +2685,16 @@ _.extend(Android.prototype, {
|
||||
|
||||
if (hasAndroid && hasJava) {
|
||||
if (self.isPlatformToolsInstalled()) {
|
||||
log && Console.info(Console.success("Found Android Platform tools"));
|
||||
log && Console.success("Found Android Platform tools");
|
||||
} else {
|
||||
if (fixSilent) {
|
||||
log && Console.info("Installing Android Platform tools");
|
||||
self.installTarget('platform-tools', function () {
|
||||
return self.isPlatformToolsInstalled();
|
||||
});
|
||||
log && Console.info(Console.success("Installed Android Platform tools"));
|
||||
log && Console.success("Installed Android Platform tools");
|
||||
} else {
|
||||
log && Console.info(Console.fail("Android Platform tools not found"));
|
||||
log && Console.failInfo("Android Platform tools not found");
|
||||
|
||||
result.missing.push("android-platform-tools");
|
||||
result.acceptable = false;
|
||||
@@ -2663,7 +2703,7 @@ _.extend(Android.prototype, {
|
||||
|
||||
var hasBuildToolsVersion;
|
||||
if (self.isBuildToolsInstalled('21.0.0')) {
|
||||
log && Console.info(Console.success("Found Android Build Tools"));
|
||||
log && Console.success("Found Android Build Tools");
|
||||
hasBuildToolsVersion = '21.0.0';
|
||||
} else {
|
||||
if (fixSilent) {
|
||||
@@ -2671,10 +2711,10 @@ _.extend(Android.prototype, {
|
||||
self.installTarget('build-tools-21.0.0', function () {
|
||||
return self.isBuildToolsInstalled('21.0.0');
|
||||
});
|
||||
log && Console.info(Console.success("Installed Android Build Tools"));
|
||||
log && Console.success("Installed Android Build Tools");
|
||||
hasBuildToolsVersion = '21.0.0';
|
||||
} else {
|
||||
log && Console.info(Console.fail("Android Build Tools not found"));
|
||||
log && Console.failInfo("Android Build Tools not found");
|
||||
|
||||
result.missing.push("android-build-tools");
|
||||
result.acceptable = false;
|
||||
@@ -2685,7 +2725,7 @@ _.extend(Android.prototype, {
|
||||
// Check that we can actually run aapt - on 64 bit, we need 32 bit libs
|
||||
// We need aapt to be installed to do this!
|
||||
if (!self.canRunAapt(hasBuildToolsVersion)) {
|
||||
log && Console.info(Console.fail("32-bit libraries not found"));
|
||||
log && Console.failInfo("32-bit libraries not found");
|
||||
|
||||
result.missing.push("libs32");
|
||||
result.acceptable = false;
|
||||
@@ -2693,31 +2733,33 @@ _.extend(Android.prototype, {
|
||||
}
|
||||
|
||||
if (self.isPlatformInstalled('android-19')) {
|
||||
log && Console.info(Console.success("Found Android 19 API"));
|
||||
log && Console.success("Found Android 19 API");
|
||||
} else {
|
||||
if (fixSilent) {
|
||||
log && Console.info("Installing Android 19 API");
|
||||
self.installTarget('android-19', function () {
|
||||
return self.isPlatformInstalled('android-19');
|
||||
});
|
||||
log && Console.info(Console.success("Installed Android 19 API"));
|
||||
log && Console.success("Installed Android 19 API");
|
||||
} else {
|
||||
log && Console.info(Console.fail("Android API 19 not found"));
|
||||
log && Console.failInfo("Android API 19 not found");
|
||||
|
||||
result.missing.push("android-api");
|
||||
result.acceptable = false;
|
||||
}
|
||||
}
|
||||
|
||||
// (We could alternatively check for {SDK}/system-images/android-19/default/x86/build.prop)
|
||||
// (We could alternatively check for
|
||||
// {SDK}/system-images/android-19/default/x86/build.prop)
|
||||
if (self.hasTarget('19', 'default/x86')) {
|
||||
log && Console.info(Console.success("Found suitable Android x86 image"));
|
||||
log && Console.success("Found suitable Android x86 image");
|
||||
} else {
|
||||
if (fixSilent) {
|
||||
// The x86 image will fail to install if dependencies aren't there;
|
||||
// we've checked the others by version,but we should double-check
|
||||
// platform-tools as we don't check versions there
|
||||
log && Console.info("Making sure Android Platform tools are up to date");
|
||||
log && Console.info(
|
||||
"Making sure Android Platform tools are up to date");
|
||||
self.installTarget('platform-tools', function () {
|
||||
return self.isPlatformToolsInstalled();
|
||||
});
|
||||
@@ -2726,9 +2768,9 @@ _.extend(Android.prototype, {
|
||||
self.installTarget('sys-img-x86-android-19', function () {
|
||||
return self.hasTarget('19', 'default/x86');
|
||||
});
|
||||
log && Console.info(Console.success("Installed Android x86 image"));
|
||||
log && Console.success("Installed Android x86 image");
|
||||
} else {
|
||||
log && Console.info(Console.fail("Suitable Android x86 image not found"));
|
||||
log && Console.failInfo("Suitable Android x86 image not found");
|
||||
|
||||
result.missing.push("android-sys-img");
|
||||
result.acceptable = false;
|
||||
@@ -2737,21 +2779,26 @@ _.extend(Android.prototype, {
|
||||
|
||||
var avdName = self.getAvdName();
|
||||
if (self.hasAvd(avdName)) {
|
||||
log && Console.info(Console.success("'" + avdName + "' android virtual device (AVD) found"));
|
||||
log && Console.success(
|
||||
"'" + avdName + "' android virtual device (AVD) found");
|
||||
} else {
|
||||
var isDefaultAvd = avdName === DEFAULT_AVD_NAME;
|
||||
if (fixSilent && isDefaultAvd) {
|
||||
log && Console.info("Creating android virtual device (AVD): " + avdName);
|
||||
|
||||
log && Console.info(
|
||||
"Creating android virtual device (AVD): " + avdName);
|
||||
var avdOptions = {};
|
||||
self.createAvd(avdName, avdOptions);
|
||||
|
||||
log && Console.info(Console.success("'" + avdName + "' android virtual device (AVD) created"));
|
||||
log && Console.success(
|
||||
"'" + avdName + "' android virtual device (AVD) created");
|
||||
} else {
|
||||
log && Console.info(Console.fail("'" + avdName + "' android virtual device (AVD) not found"));
|
||||
log && Console.failInfo(
|
||||
"'" + avdName + "' android virtual device (AVD) not found");
|
||||
|
||||
if (!isDefaultAvd) {
|
||||
log && Console.info("(Because you specified a custom AVD, we don't create it automatically)");
|
||||
log && Console.info(
|
||||
"(Because you specified a custom AVD, we don't create it",
|
||||
"automatically)");
|
||||
}
|
||||
|
||||
result.missing.push("android-avd");
|
||||
@@ -2766,18 +2813,21 @@ _.extend(Android.prototype, {
|
||||
if (fix) {
|
||||
self.installAcceleration();
|
||||
} else {
|
||||
log && Console.info(Console.fail("Android emulator acceleration is not installed"));
|
||||
log && Console.info(" (The Android emulator will be very slow without acceleration)");
|
||||
log && Console.failInfo(
|
||||
"Android emulator acceleration is not installed");
|
||||
log && Console.info(
|
||||
"(The Android emulator will be very slow without acceleration)",
|
||||
Console.options({ indent: 2 }));
|
||||
|
||||
result.missing.push("haxm");
|
||||
|
||||
// Not all systems can install the accelerator, so don't block
|
||||
// XXX: Maybe we should block the emulator (only); it is unusable without it
|
||||
//result.acceptable = false
|
||||
// XXX: Maybe we should block the emulator (only); it is unusable
|
||||
//without it result.acceptable = false
|
||||
}
|
||||
} else if (hasAcceleration === true) {
|
||||
// (can be undefined)
|
||||
log && Console.info(Console.success("Android emulator acceleration is installed"));
|
||||
log && Console.success("Android emulator acceleration is installed");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2886,19 +2936,19 @@ main.registerCommand({
|
||||
// explain why we can't remove server or browser platforms
|
||||
if (_.contains(projectContextModule.PlatformList.DEFAULT_PLATFORMS,
|
||||
platform)) {
|
||||
Console.stdout.write(platform + ": cannot remove platform " +
|
||||
"in this version of Meteor\n");
|
||||
Console.warn(
|
||||
platform + ": cannot remove platform in this version of Meteor");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.contains(platforms, platform)) {
|
||||
Console.stdout.write(platform + ": removed platform\n");
|
||||
Console.info(platform + ": removed platform");
|
||||
platforms = _.without(platforms, platform);
|
||||
changed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Console.stdout.write(platform + ": platform is not in this project\n");
|
||||
Console.error(platform + ": platform is not in this project");
|
||||
});
|
||||
|
||||
if (! changed) {
|
||||
@@ -2927,7 +2977,7 @@ main.registerCommand({
|
||||
|
||||
var platforms = projectContext.platformList.getPlatforms();
|
||||
|
||||
Console.stdout.write(platforms.join("\n"));
|
||||
Console.rawInfo(platforms.join("\n") + "\n");
|
||||
});
|
||||
|
||||
main.registerCommand({
|
||||
@@ -2978,7 +3028,9 @@ main.registerCommand({
|
||||
|
||||
if (!Android.hasAvd(avd)) {
|
||||
Console.error("'" + avd + "' android virtual device (AVD) does not exist");
|
||||
Console.info("The default AVD is called meteor, and will be created automatically for you");
|
||||
Console.info(
|
||||
"The default AVD is called meteor, and will be created",
|
||||
"automatically for you");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3023,7 +3075,7 @@ main.registerCommand({
|
||||
var installed = checkPlatformRequirements(platform, { log:true, fix: false, fixConsole: true, fixSilent: true } );
|
||||
if (!_.isEmpty(installed.missing)) {
|
||||
if (Host.isLinux() && platform === "ios") {
|
||||
Console.warn(Console.fail(MESSAGE_IOS_ONLY_ON_MAC));
|
||||
Console.failWarn(MESSAGE_IOS_ONLY_ON_MAC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3043,7 +3095,8 @@ main.registerCommand({
|
||||
url += "#" + anchor;
|
||||
}
|
||||
openUrl(url);
|
||||
Console.info("Please follow the instructions here:\n" + Console.bold(url) + "\n");
|
||||
Console.info(
|
||||
"Please follow the instructions here:\n" + Console.url(url) + "\n");
|
||||
} else {
|
||||
Console.info("We don't have installation instructions for your platform");
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ var Console = require('./console.js').Console;
|
||||
var projectContextModule = require('./project-context.js');
|
||||
var packageVersionParser = require('./package-version-parser.js');
|
||||
|
||||
// On some informational actions, we only refresh the package catalog if it is > 15 minutes old
|
||||
// On some informational actions, we only refresh the package catalog if it is >
|
||||
// 15 minutes old
|
||||
var DEFAULT_MAX_AGE_MS = 15 * 60 * 1000;
|
||||
|
||||
// Returns an object with keys:
|
||||
@@ -153,7 +154,6 @@ main.registerCommand({
|
||||
// not actually in the app!
|
||||
// XXX Maybe we should do a first pass that only builds packages actually in
|
||||
// the app and does display the PackageMapDelta?
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
@@ -260,9 +260,9 @@ main.registerCommand({
|
||||
// weird. Let's not allow this.
|
||||
Console.error(
|
||||
"The package you are in appears to be inside a Meteor app but is not " +
|
||||
"in its packages directory. You may only publish packages that are " +
|
||||
"entirely outside of a project or that are loaded by the project " +
|
||||
"that they are inside.");
|
||||
"in its packages directory. You may only publish packages that are " +
|
||||
"entirely outside of a project or that are loaded by the project " +
|
||||
"that they are inside.");
|
||||
return 1;
|
||||
}
|
||||
var packageName = localVersionRecord.packageName;
|
||||
@@ -290,10 +290,10 @@ main.registerCommand({
|
||||
|
||||
if (!options['top-level'] && !packageName.match(/:/)) {
|
||||
Console.error(
|
||||
"Only administrators can create top-level packages without an account prefix.\n" +
|
||||
"(To confirm that you wish to create a top-level package with no account\n" +
|
||||
"prefix, please run this command again with the --top-level option.)");
|
||||
|
||||
"Only administrators can create top-level packages without an",
|
||||
"account prefix. (To confirm that you wish to create a top-level",
|
||||
"package with no account prefix, please run this command again",
|
||||
"with the --top-level option.)");
|
||||
// You actually shouldn't be able to get here without being logged in, but
|
||||
// it seems poor form to assume anything like that for the point of a
|
||||
// brief error message.
|
||||
@@ -360,28 +360,41 @@ main.registerCommand({
|
||||
// This is an undocumented command that you are not supposed to run! We
|
||||
// assume that you know what you are doing, if you ran it, and are OK with
|
||||
// overrwriting normal compatibilities.
|
||||
Console.warn("\nWARNING: Your package contains binary code.");
|
||||
Console.warn();
|
||||
Console.labelWarn("Your package contains binary code.");
|
||||
} else if (binary) {
|
||||
// Normal publish flow. Tell the user nicely.
|
||||
Console.warn();
|
||||
Console.warn(
|
||||
"\nThis package contains binary code and must be built on multiple architectures.\n");
|
||||
|
||||
"This package contains binary code and must be built on",
|
||||
"multiple architectures.");
|
||||
Console.warn();
|
||||
Console.info(
|
||||
"You can access Meteor provided build machines, pre-configured to support\n" +
|
||||
"older versions of MacOS and Linux, by running:\n");
|
||||
|
||||
_.each(["os.osx.x86_64", "os.linux.x86_64", "os.linux.x86_32"], function (a) {
|
||||
Console.info(" meteor admin get-machine", a);
|
||||
"You can access Meteor provided build machines, pre-configured to",
|
||||
"support older versions of MacOS and Linux, by running:");
|
||||
_.each(["os.osx.x86_64", "os.linux.x86_64", "os.linux.x86_32"],
|
||||
function (a) {
|
||||
Console.info(
|
||||
Console.command("meteor admin get-machine " + a),
|
||||
Console.options({ indent: 2 }));
|
||||
});
|
||||
|
||||
Console.info("\nOn each machine, run:\n");
|
||||
|
||||
Console.info(" meteor",
|
||||
"publish-for-arch",
|
||||
packageSource.name + "@" + packageSource.version);
|
||||
|
||||
Console.info("\nFor more information on binary ABIs and consistent builds, see:");
|
||||
Console.info(" https://github.com/meteor/meteor/wiki/Build-Machines\n");
|
||||
Console.info();
|
||||
Console.info("On each machine, run:");
|
||||
Console.info();
|
||||
Console.info(
|
||||
Console.command(
|
||||
"meteor publish-for-arch " +
|
||||
packageSource.name + "@" + packageSource.version),
|
||||
Console.options({ indent: 2 }));
|
||||
Console.info();
|
||||
Console.info(
|
||||
"For more information on binary ABIs and consistent builds, see:");
|
||||
Console.info(
|
||||
Console.url("https://github.com/meteor/meteor/wiki/Build-Machines"),
|
||||
Console.options({ indent: 2 })
|
||||
);
|
||||
Console.info();
|
||||
}
|
||||
|
||||
// Refresh, so that we actually learn about the thing we just published.
|
||||
@@ -411,26 +424,36 @@ main.registerCommand({
|
||||
var packageInfo = catalog.official.getPackage(name);
|
||||
if (! packageInfo) {
|
||||
Console.error(
|
||||
"You can't call `meteor publish-for-arch` on package '" + name + "' without\n" +
|
||||
"publishing it first.\n\n" +
|
||||
"To publish the package, run `meteor publish --create` from the package directory.\n");
|
||||
|
||||
"You can't call " + Console.command("`meteor publish-for-arch`") +
|
||||
"on package '" + name + "' without " +" publishing it first."
|
||||
);
|
||||
Console.error();
|
||||
Console.error(
|
||||
"To publish the package, run " +
|
||||
Console.command("`meteor publish --create` ") +
|
||||
"from the package directory.");
|
||||
Console.error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
var pkgVersion = catalog.official.getVersion(name, versionString);
|
||||
if (! pkgVersion) {
|
||||
Console.error(
|
||||
"You can't call `meteor publish-for-arch` on version " + versionString + " of\n" +
|
||||
"package '" + name + "' without publishing it first.\n\n" +
|
||||
"To publish the version, run `meteor publish` from the package directory.\n\n");
|
||||
|
||||
"You can't call", Console.command("`meteor publish-for-arch`"),
|
||||
"on version " + versionString + " of " + "package '" + name +
|
||||
"' without publishing it first.");
|
||||
Console.error();
|
||||
Console.error(
|
||||
"To publish the package, run " + Console.command("`meteor publish ` ") +
|
||||
"from the package directory.");
|
||||
Console.error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! pkgVersion.source || ! pkgVersion.source.url) {
|
||||
Console.error('There is no source uploaded for ' +
|
||||
name + '@' + versionString);
|
||||
Console.error(
|
||||
"There is no source uploaded for",
|
||||
name + '@' + versionString);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -439,30 +462,33 @@ main.registerCommand({
|
||||
// further springboarding based on reading a nested json file.
|
||||
if (! _.has(pkgVersion, 'releaseName')) {
|
||||
if (files.inCheckout()) {
|
||||
process.stderr.write(
|
||||
"This package was published from an old version of meteor," +
|
||||
"but you are running from checkout!\nConsider running " +
|
||||
"`meteor --release 1.0`, so we can springboard correctly.\n");
|
||||
process.stderr.exit(1);
|
||||
Console.error(
|
||||
"This package was published from an old version of meteor, " +
|
||||
"but you are running from checkout! Consider running " +
|
||||
Console.command("`meteor --release 1.0`"),
|
||||
"so we can springboard correctly.");
|
||||
process.exit(1);
|
||||
}
|
||||
throw new main.SpringboardToSpecificRelease("METEOR@1.0");
|
||||
}
|
||||
|
||||
if (pkgVersion.releaseName === null) {
|
||||
if (! files.inCheckout()) {
|
||||
process.stderr.write(
|
||||
"This package was published from a checkout of meteor! The tool cannot replicate\n" +
|
||||
"that environment and will not even try. Please check out meteor at the \n" +
|
||||
"corresponding git commit and try again.\n");
|
||||
Console.error(
|
||||
"This package was published from a checkout of meteor!",
|
||||
"The tool cannot replicate that environment and will not even try.",
|
||||
"Please check out meteor at the " +
|
||||
"corresponding git commit and try again.");
|
||||
process.exit(1);
|
||||
}
|
||||
} else if (files.inCheckout()) {
|
||||
process.stderr.write(
|
||||
"This package was published from a built version of meteor," +
|
||||
"but you are running from checkout!\nConsider running from a " +
|
||||
"proper Meteor release with `meteor --release " +
|
||||
pkgVersion.releaseName + "` so we can springboard correctly.\n");
|
||||
process.stderr.exit(1);
|
||||
Console.error(
|
||||
"This package was published from a built version of meteor, " +
|
||||
"but you are running from checkout! Consider running from a " +
|
||||
"proper Meteor release with " +
|
||||
Console.command("`meteor --release " + pkgVersion.releaseName + "`"),
|
||||
"so we can springboard correctly.");
|
||||
process.exit(1);
|
||||
} else if (pkgVersion.releaseName !== release.current.name) {
|
||||
// We are in a built release, and so is the package, but it's a different
|
||||
// one. Springboard!
|
||||
@@ -496,10 +522,11 @@ main.registerCommand({
|
||||
// Copy over a version lock file from the source tarball.
|
||||
var versionsFile = path.join(packageDir, '.versions');
|
||||
if (! fs.existsSync(versionsFile)) {
|
||||
process.stderr.write(
|
||||
"This package has no valid version lock file: are you trying to use publish-for-arch on\n" +
|
||||
"a core package? Publish-for-arch cannot guarantee safety. Please use\n" +
|
||||
"publish --existing-version instead.\n");
|
||||
Console.error(
|
||||
"This package has no valid version lock file: are you trying to use " +
|
||||
"publish-for-arch on a core package? Publish-for-arch cannot " +
|
||||
"guarantee safety. Please use",
|
||||
Console.command("'meteor publish --existing-version'"), "instead.");
|
||||
process.exit(1);
|
||||
}
|
||||
files.copyFile(path.join(packageDir, '.versions'),
|
||||
@@ -640,9 +667,9 @@ main.registerCommand({
|
||||
if (start === "0.8." || start === "0.7." ||
|
||||
start === "0.6." || start === "0.5.") {
|
||||
buildmessage.error(
|
||||
"It looks like you are trying to publish a pre-package-server meteor release.\n" +
|
||||
"Doing this through the package server is going to cause a lot of confusion.\n" +
|
||||
"Please use the old release process.");
|
||||
"It looks like you are trying to publish a pre-package-server " +
|
||||
"meteor release. Doing this through the package server is going " +
|
||||
"to cause a lot of confusion. Please use the old release process.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -656,7 +683,7 @@ main.registerCommand({
|
||||
if (!trackRecord) {
|
||||
Console.error(
|
||||
'There is no release track named ' + relConf.track +
|
||||
'. If you are creating a new track, use the --create-track flag.');
|
||||
'. If you are creating a new track, use the --create-track flag.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -696,9 +723,9 @@ main.registerCommand({
|
||||
// these by accident. So, we will disallow it for now.
|
||||
if (relConf.packages || relConf.tool) {
|
||||
Console.error(
|
||||
"Setting the --from-checkout option will use the tool and packages in your meteor " +
|
||||
"checkout.\n" +
|
||||
"Your release configuration file should not contain that information.");
|
||||
"Setting the --from-checkout option will use the tool and packages " +
|
||||
"in your meteor checkout. " +
|
||||
"Your release configuration file should not contain that information.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -924,13 +951,17 @@ main.registerCommand({
|
||||
Console.error(
|
||||
"Failed to push git tag. Please push git tag manually!");
|
||||
Console.error(
|
||||
"If you are publishing a non-prerelease version, then the readme will show up " +
|
||||
"in atmosphere. To make sure that happens, after pushing the git tag, please " +
|
||||
"run the following:");
|
||||
"If you are publishing a non-prerelease version, then the readme " +
|
||||
"should show up in Atmosphere. To make sure that happens, after " +
|
||||
"pushing the git tag, please run the following:");
|
||||
_.each(toPublish, function (name) {
|
||||
Console.info("meteor admin set-latest-readme " + name + " --tag " + gitTag);
|
||||
Console.info(
|
||||
Console.command(
|
||||
"meteor admin set-latest-readme " + name + " --tag " + gitTag));
|
||||
});
|
||||
Console.error("If you are publishing an experimental version, don't worry about it.");
|
||||
Console.error(
|
||||
"If you are publishing an experimental version, ",
|
||||
"don't worry about it.");
|
||||
fail = true;
|
||||
}
|
||||
if (! fail) {
|
||||
@@ -938,14 +969,15 @@ main.registerCommand({
|
||||
var isopk = projectContext.isopackCache.getIsopack(name);
|
||||
if (! isopk)
|
||||
throw Error("no isopack for " + name);
|
||||
|
||||
var url = "https://raw.githubusercontent.com/meteor/meteor/" + gitTag +
|
||||
var url =
|
||||
"https://raw.githubusercontent.com/meteor/meteor/" + gitTag +
|
||||
"/packages/" +
|
||||
name + "/README.md";
|
||||
var version = isopk.version;
|
||||
packageClient.callPackageServer(
|
||||
conn, '_changeReadmeURL', name, version, url);
|
||||
Console.info("Setting the readme of", name + "@" + version, "to", url);
|
||||
Console.info(
|
||||
"Setting the readme of", name + "@" + version, "to", Console.url(url));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -954,12 +986,13 @@ main.registerCommand({
|
||||
// packages. Unlike publish, this is advanced functionality, so the user
|
||||
// should be familiar with the concept.
|
||||
if (! _.isEmpty(unfinishedBuilds)) {
|
||||
Console.warning();
|
||||
Console.warning(
|
||||
"WARNING: Some packages contain binary dependencies.");
|
||||
Console.warning("Builds have not been published for the following packages:");
|
||||
Console.warn();
|
||||
Console.labelWarn(
|
||||
"Some packages contain binary dependencies.");
|
||||
Console.warn(
|
||||
"Builds have not been published for the following packages:");
|
||||
_.each(unfinishedBuilds, function (version, name) {
|
||||
Console.warning(name + "@" + version);
|
||||
Console.warn(name + "@" + version);
|
||||
});
|
||||
// Note: we don't actually enforce the proper build machine thing. You
|
||||
// can't use publish-for-arch for meteor-tool, for example, you need to
|
||||
@@ -969,7 +1002,7 @@ main.registerCommand({
|
||||
// --existing-version: presumably you don't care about compatibility
|
||||
// etc. If it is an official release, you ought to use a build machine
|
||||
// though.
|
||||
Console.warning(
|
||||
Console.warn(
|
||||
"Please publish the builds separately, from a proper build machine.");
|
||||
}
|
||||
}
|
||||
@@ -997,6 +1030,7 @@ main.registerCommand({
|
||||
var versionVisible = function (record) {
|
||||
return options['show-old'] || !record.unmigrated;
|
||||
};
|
||||
var INDENT = 6;
|
||||
|
||||
var full = options.args[0].split('@');
|
||||
var name = full[0];
|
||||
@@ -1097,20 +1131,25 @@ main.registerCommand({
|
||||
|
||||
if (v.buildArchitectures) {
|
||||
var buildArchitectures = v.buildArchitectures.split(' ');
|
||||
Console.info(" Architectures: ", formatAsList(buildArchitectures, { formatter: formatArchitecture }));
|
||||
Console.info(
|
||||
"Architectures: ",
|
||||
formatAsList(
|
||||
buildArchitectures, { formatter: formatArchitecture }),
|
||||
Console.options({ indent: INDENT }));
|
||||
}
|
||||
// XXX: else show "no architectures"?
|
||||
if (v.packages) {
|
||||
Console.info(" tool: " + v.tool);
|
||||
Console.info(" packages:");
|
||||
Console.info("tool: " + v.tool, Console.options({ indent: INDENT }));
|
||||
Console.info("packages:", Console.options({ indent: INDENT }));
|
||||
|
||||
_.each(v.packages, function(pv, pn) {
|
||||
Console.info(" " + pn + "@" + pv);
|
||||
Console.info(pn + "@" + pv, Console.options({ indent: INDENT }));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Console.info("\n");
|
||||
Console.info();
|
||||
Console.info();
|
||||
} else {
|
||||
// Non-detailed list of versions
|
||||
|
||||
@@ -1126,7 +1165,7 @@ main.registerCommand({
|
||||
rows.push(row);
|
||||
});
|
||||
|
||||
utils.printTwoColumns(rows);
|
||||
Console.printTwoColumns(rows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,7 +1175,8 @@ main.registerCommand({
|
||||
var myMaintainerString = "";
|
||||
var myMaintainers = _.pluck(record.maintainers, 'username');
|
||||
if (myMaintainers.length === 0) {
|
||||
Console.debug("No maintainer records found: ", JSON.stringify(record));
|
||||
Console.rawDebug(
|
||||
"No maintainer records found: ", JSON.stringify(record), "\n");
|
||||
} else if (myMaintainers.length === 1) {
|
||||
myMaintainerString = myMaintainers[0];
|
||||
} else {
|
||||
@@ -1180,7 +1220,8 @@ main.registerCommand({
|
||||
catalogRefresh: new catalog.Refresh.OnceAtStart({ maxAge: DEFAULT_MAX_AGE_MS, ignoreErrors: true })
|
||||
}, function (options) {
|
||||
if (options.args.length === 0) {
|
||||
Console.info("To show all packages, do", Console.command("meteor search ."));
|
||||
Console.info(
|
||||
"To show all packages, do", Console.command("meteor search ."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1310,7 +1351,8 @@ main.registerCommand({
|
||||
explainIfRefreshFailed();
|
||||
} else {
|
||||
Console.info(
|
||||
"To get more information on a specific item, use", Console.command("meteor show"));
|
||||
"To get more information on a specific item, use",
|
||||
Console.command("meteor show"));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1405,21 +1447,26 @@ main.registerCommand({
|
||||
utils.printPackageList(items);
|
||||
|
||||
if (newVersionsAvailable) {
|
||||
Console.info("\n" +
|
||||
"* New versions of these packages are available! Run 'meteor update' to try\n" +
|
||||
" to update those packages to their latest versions. If your packages cannot be\n" +
|
||||
" updated further, try typing meteor add <package>@<newVersion> to see more\n" +
|
||||
" information.");
|
||||
Console.info();
|
||||
Console.info(
|
||||
"New versions of these packages are available! Run",
|
||||
Console.command("'meteor update'"), "to try to update those",
|
||||
"packages to their latest versions. If your packages cannot be",
|
||||
"updated further, try typing",
|
||||
Console.command("`meteor add <package>@<newVersion>`"),
|
||||
"to see more information.",
|
||||
Console.options({ bulletPoint: "* " }));
|
||||
}
|
||||
if (anyBuiltLocally) {
|
||||
Console.info("\n" +
|
||||
"+ These packages are built locally from source.");
|
||||
Console.info();
|
||||
Console.info(
|
||||
"These packages are built locally from source.",
|
||||
Console.options({ bulletPoint: "+ " }));
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// update
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1437,8 +1484,8 @@ var maybeUpdateRelease = function (options) {
|
||||
// We are running from checkout, so we are not updating the release.
|
||||
if (release.current && release.current.isCheckout()) {
|
||||
Console.error(
|
||||
"You are running Meteor from a checkout, so we cannot update the Meteor release.\n" +
|
||||
"Checking to see if we can update your packages.");
|
||||
"You are running Meteor from a checkout, so we cannot update",
|
||||
"the Meteor release. Checking to see if we can update your packages.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1508,18 +1555,18 @@ var maybeUpdateRelease = function (options) {
|
||||
// command even ran. They could equivalently have run 'meteor
|
||||
// help --release xyz'.
|
||||
Console.info(
|
||||
"Installed. Run 'meteor update' inside of a particular project\n" +
|
||||
"directory to update that project to " +
|
||||
release.current.getDisplayName() + ".");
|
||||
"Installed. Run " + Console.command("'meteor update' ") +
|
||||
"inside of a particular project directory to update that project to " +
|
||||
release.current.getDisplayName() + ".");
|
||||
} else {
|
||||
// We get here if the user ran 'meteor update' and we didn't
|
||||
// find a new version.
|
||||
Console.info(
|
||||
"The latest version of Meteor, " + release.current.getReleaseVersion() +
|
||||
", is already installed on this\n" +
|
||||
"computer. Run 'meteor update' inside of a particular project\n" +
|
||||
"directory to update that project to " +
|
||||
release.current.getDisplayName());
|
||||
", is already installed on this computer. Run " +
|
||||
Console.command("'meteor update'") + " inside of a particular " +
|
||||
"project directory to update that project to " +
|
||||
release.current.getDisplayName());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1544,7 +1591,7 @@ var maybeUpdateRelease = function (options) {
|
||||
var maybeTheLatestRelease = release.explicit ? "" : ", the latest release";
|
||||
Console.info(
|
||||
"This project is already at " +
|
||||
release.current.getDisplayName() + maybeTheLatestRelease + ".");
|
||||
release.current.getDisplayName() + maybeTheLatestRelease + ".");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1590,8 +1637,7 @@ var maybeUpdateRelease = function (options) {
|
||||
// not try to patch you to an unfriendly release. So, either way, as far
|
||||
// as we are concerned you are at the 'latest patch version'
|
||||
if (!patchRecord || !patchRecord.recommended ) {
|
||||
Console.error(
|
||||
"You are at the latest patch version.");
|
||||
Console.error("You are at the latest patch version.");
|
||||
return 0;
|
||||
}
|
||||
// Great, we found a patch version. You can only have one latest patch for
|
||||
@@ -1616,9 +1662,9 @@ var maybeUpdateRelease = function (options) {
|
||||
// We could not find any releases newer than the one that we are on, on
|
||||
// that track, so we are done.
|
||||
Console.info(
|
||||
"This project is already at " + projectContext.releaseFile.displayReleaseName +
|
||||
", which is newer\n" +
|
||||
"than the latest release.");
|
||||
"This project is already at " +
|
||||
Console.noWrap(projectContext.releaseFile.displayReleaseName) +
|
||||
", which is newer than the latest release.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1639,7 +1685,8 @@ var maybeUpdateRelease = function (options) {
|
||||
// Nope, this release didn't work.
|
||||
Console.debug(
|
||||
"Update to release", releaseTrack + "@" + versionToTry,
|
||||
"is impossible:\n" + messages.formatMessages());
|
||||
"is impossible:");
|
||||
Console.debug(messages.formatMessages());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1651,8 +1698,8 @@ var maybeUpdateRelease = function (options) {
|
||||
var newerAvailable = false;
|
||||
if (! solutionReleaseVersion) {
|
||||
Console.info(
|
||||
"This project is at the latest release which is compatible with your\n" +
|
||||
"current package constraints.");
|
||||
"This project is at the latest release which is compatible with your " +
|
||||
"current package constraints.");
|
||||
return 0;
|
||||
} else if (solutionReleaseVersion !== releaseVersionsToTry[0]) {
|
||||
newerAvailable = true;
|
||||
@@ -1689,8 +1736,8 @@ var maybeUpdateRelease = function (options) {
|
||||
projectContext.releaseFile.displayReleaseName + ".");
|
||||
if (newerAvailable) {
|
||||
Console.info(
|
||||
"(Newer releases are available but are not compatible with your\n" +
|
||||
"current package constraints.)");
|
||||
"(Newer releases are available but are not compatible with your " +
|
||||
"current package constraints.)");
|
||||
}
|
||||
|
||||
// Now run the upgraders.
|
||||
@@ -2001,7 +2048,7 @@ main.registerCommand({
|
||||
});
|
||||
});
|
||||
if (messages.hasMessages()) {
|
||||
Console.error("=> Errors while parsing arguments:");
|
||||
Console.arrowError("Errors while parsing arguments:", 1);
|
||||
Console.printMessages(messages);
|
||||
explainIfRefreshFailed(); // this is why we're not using captureAndExit
|
||||
return 1;
|
||||
@@ -2014,7 +2061,7 @@ main.registerCommand({
|
||||
projectContext.prepareProjectForBuild();
|
||||
});
|
||||
if (messages.hasMessages()) {
|
||||
Console.error("=> Errors while adding packages:");
|
||||
Console.arrowError("Errors while adding packages:", 1);
|
||||
Console.printMessages(messages);
|
||||
explainIfRefreshFailed(); // this is why we're not using captureAndExit
|
||||
return 1;
|
||||
@@ -2026,12 +2073,12 @@ main.registerCommand({
|
||||
projectContext.packageMapDelta.displayOnConsole();
|
||||
|
||||
// Show descriptions of directly added packages.
|
||||
Console.stdout.write("\n");
|
||||
Console.info();
|
||||
_.each(constraintsToAdd, function (constraint) {
|
||||
var version = projectContext.packageMap.getInfo(constraint.name).version;
|
||||
var versionRecord = projectContext.projectCatalog.getVersion(
|
||||
constraint.name, version);
|
||||
Console.stdout.write(
|
||||
Console.info(
|
||||
constraint.name +
|
||||
(versionRecord.description ? (": " + versionRecord.description) : ""));
|
||||
});
|
||||
@@ -2178,7 +2225,8 @@ main.registerCommand({
|
||||
}
|
||||
if ((options.add || options.remove) && options.list) {
|
||||
Console.error(
|
||||
"Sorry, you can't change the users at the same time as you're listing them.");
|
||||
"Sorry, you can't change the users at the same time as you're",
|
||||
"listing them.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2213,7 +2261,7 @@ main.registerCommand({
|
||||
packageClient.callPackageServer(
|
||||
conn, 'removeMaintainer', name, options.remove);
|
||||
}
|
||||
Console.info(" Done!");
|
||||
Console.info("Success.");
|
||||
}
|
||||
} catch (err) {
|
||||
packageClient.handlePackageServerConnectionError(err);
|
||||
@@ -2230,16 +2278,18 @@ main.registerCommand({
|
||||
|
||||
if (!record) {
|
||||
Console.info(
|
||||
"Could not get list of maintainers: package " + name + " does not exist.");
|
||||
"Could not get list of maintainers:",
|
||||
"package " + name + " does not exist.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.info("\nThe maintainers for " + name + " are:");
|
||||
Console.info();
|
||||
Console.info("The maintainers for " + name + " are:");
|
||||
_.each(record.maintainers, function (user) {
|
||||
if (! user || !user.username)
|
||||
Console.info("<unknown>");
|
||||
Console.rawInfo("<unknown>" + "\n");
|
||||
else
|
||||
Console.info(user.username + "");
|
||||
Console.rawInfo(user.username + "\n");
|
||||
});
|
||||
return 0;
|
||||
});
|
||||
@@ -2284,11 +2334,11 @@ main.registerCommand({
|
||||
toolPackage, toolVersion);
|
||||
if (!toolPkgBuilds) {
|
||||
// XXX this could also mean package unknown.
|
||||
Console.error('Tool version unknown: ' + release.tool + '');
|
||||
Console.error('Tool version unknown: ' + release.tool);
|
||||
return 1;
|
||||
}
|
||||
if (!toolPkgBuilds.length) {
|
||||
Console.error('Tool version has no builds: ' + release.tool + '');
|
||||
Console.error('Tool version has no builds: ' + release.tool);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2308,8 +2358,8 @@ main.registerCommand({
|
||||
});
|
||||
|
||||
Console.error(
|
||||
'Building bootstrap tarballs for architectures ' +
|
||||
osArches.join(', ') + '');
|
||||
'Building bootstrap tarballs for architectures ' + osArches.join(', '));
|
||||
|
||||
// Before downloading anything, check that the catalog contains everything we
|
||||
// need for the OSes that the tool is built for.
|
||||
var messages = buildmessage.capture(function () {
|
||||
@@ -2328,7 +2378,7 @@ main.registerCommand({
|
||||
});
|
||||
|
||||
if (messages.hasMessages()) {
|
||||
Console.error("\n" + messages.formatMessages());
|
||||
Console.printMessages(messages);
|
||||
return 1;
|
||||
};
|
||||
|
||||
@@ -2432,8 +2482,7 @@ main.registerCommand({
|
||||
var bannersData = fs.readFileSync(bannersFile, 'utf8');
|
||||
bannersData = JSON.parse(bannersData);
|
||||
} catch (e) {
|
||||
Console.error("Could not parse banners file: ");
|
||||
Console.error(e.message + "");
|
||||
Console.error("Could not parse banners file: " + e.message);
|
||||
return 1;
|
||||
}
|
||||
if (!bannersData.track) {
|
||||
@@ -2482,14 +2531,15 @@ main.registerCommand({
|
||||
var name = release[0];
|
||||
var version = release[1];
|
||||
if (!version) {
|
||||
Console.error('\n Must specify release version (track@version)');
|
||||
Console.error('Must specify release version (track@version)');
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now let's get down to business! Fetching the thing.
|
||||
var record = catalog.official.getReleaseTrack(name);
|
||||
if (!record) {
|
||||
Console.error('\n There is no release track named ' + name);
|
||||
Console.error();
|
||||
Console.error('There is no release track named ' + name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2503,14 +2553,15 @@ main.registerCommand({
|
||||
try {
|
||||
if (options.unrecommend) {
|
||||
Console.info("Unrecommending " + name + "@" + version + "...");
|
||||
packageClient.callPackageServer(conn, 'unrecommendVersion', name, version);
|
||||
Console.info("Done!\n " + name + "@" + version +
|
||||
" is no longer a recommended release");
|
||||
packageClient.callPackageServer(
|
||||
conn, 'unrecommendVersion', name, version);
|
||||
Console.info("Success.");
|
||||
Console.info(name + "@" + version, "is no longer a recommended release");
|
||||
} else {
|
||||
Console.info("Recommending " + options.args[0] + "...");
|
||||
packageClient.callPackageServer(conn, 'recommendVersion', name, version);
|
||||
Console.info("Done!\n " + name + "@" + version +
|
||||
" is now a recommended release");
|
||||
Console.info("Success.");
|
||||
Console.info(name + "@" + version, "is now a recommended release");
|
||||
}
|
||||
} catch (err) {
|
||||
packageClient.handlePackageServerConnectionError(err);
|
||||
@@ -2538,7 +2589,8 @@ main.registerCommand({
|
||||
// Now let's get down to business! Fetching the thing.
|
||||
var record = catalog.official.getPackage(name);
|
||||
if (!record) {
|
||||
Console.error('\n There is no package named ' + name);
|
||||
Console.error();
|
||||
Console.error('There is no package named ' + name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2550,12 +2602,12 @@ main.registerCommand({
|
||||
}
|
||||
|
||||
try {
|
||||
Console.info(
|
||||
"Changing homepage on "
|
||||
Console.rawInfo(
|
||||
"Changing homepage on "
|
||||
+ name + " to " + url + "...");
|
||||
packageClient.callPackageServer(conn,
|
||||
'_changePackageHomepage', name, url);
|
||||
Console.info("Done!");
|
||||
Console.info(" done");
|
||||
} catch (err) {
|
||||
packageClient.handlePackageServerConnectionError(err);
|
||||
return 1;
|
||||
@@ -2601,16 +2653,16 @@ main.registerCommand({
|
||||
|
||||
try {
|
||||
var status = options.success ? "successfully" : "unsuccessfully";
|
||||
// XXX: This should probably use progress bars instead.
|
||||
_.each(versions, function (version) {
|
||||
process.stdout.write(
|
||||
"Setting "
|
||||
+ name + "@" + version + " as " +
|
||||
status + " migrated ...");
|
||||
Console.rawInfo(
|
||||
"Setting " + name + "@" + version + " as " +
|
||||
status + " migrated ... ");
|
||||
packageClient.callPackageServer(
|
||||
conn,
|
||||
'_changeVersionMigrationStatus',
|
||||
name, version, !options.success);
|
||||
process.stdout.write(" done!\n");
|
||||
Console.info("done.");
|
||||
});
|
||||
} catch (err) {
|
||||
packageClient.handlePackageServerConnectionError(err);
|
||||
@@ -2656,14 +2708,13 @@ main.registerCommand({
|
||||
}
|
||||
|
||||
try {
|
||||
Console.info(
|
||||
"Setting README of "
|
||||
+ name + "@" + version + " to " + url);
|
||||
packageClient.callPackageServer(
|
||||
conn,
|
||||
'_changeReadmeURL',
|
||||
name, version, url);
|
||||
Console.info(" done!\n");
|
||||
// XXX: This output should probably use progress bars instead!
|
||||
Console.rawInfo("Setting README of " + name + "@" + version + " to " + url + " ... ");
|
||||
packageClient.callPackageServer(
|
||||
conn,
|
||||
'_changeReadmeURL',
|
||||
name, version, url);
|
||||
Console.info("done.");
|
||||
} catch (err) {
|
||||
packageClient.handlePackageServerConnectionError(err);
|
||||
return 1;
|
||||
|
||||
@@ -70,7 +70,9 @@ var showInvalidArchMsg = function (arch) {
|
||||
Console.info("Invalid architecture: " + arch);
|
||||
Console.info("The following are valid Meteor architectures:");
|
||||
_.each(_.keys(VALID_ARCHITECTURES), function (va) {
|
||||
Console.info(" " + va);
|
||||
Console.info(
|
||||
Console.command(va),
|
||||
Console.options({ indent: 2 }));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -85,7 +87,7 @@ main.registerCommand({
|
||||
catalogRefresh: new catalog.Refresh.Never()
|
||||
}, function (options) {
|
||||
var archinfo = require('./archinfo.js');
|
||||
console.log(archinfo.host());
|
||||
Console.rawInfo(archinfo.host() + "\n");
|
||||
});
|
||||
|
||||
// Prints the current release in use. Note that if there is not
|
||||
@@ -101,15 +103,16 @@ main.registerCommand({
|
||||
if (release.current === null) {
|
||||
if (! options.appDir)
|
||||
throw new Error("missing release, but not in an app?");
|
||||
Console.stderr.write(
|
||||
"This project was created with a checkout of Meteor, rather than an\n" +
|
||||
"official release, and doesn't have a release number associated with\n" +
|
||||
"it. You can set its release with 'meteor update'.\n");
|
||||
Console.error(
|
||||
"This project was created with a checkout of Meteor, rather than an " +
|
||||
"official release, and doesn't have a release number associated with " +
|
||||
"it. You can set its release with " +
|
||||
Console.command("'meteor update'") + ".");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (release.current.isCheckout()) {
|
||||
Console.stderr.write("Unreleased (running from a checkout)\n");
|
||||
Console.error("Unreleased (running from a checkout).");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -123,15 +126,15 @@ main.registerCommand({
|
||||
catalogRefresh: new catalog.Refresh.Never()
|
||||
}, function (options) {
|
||||
if (files.inCheckout()) {
|
||||
Console.stderr.write("checkout\n");
|
||||
Console.error("checkout");
|
||||
return 1;
|
||||
} else if (release.current === null) {
|
||||
// .meteor/release says "none" but not in a checkout.
|
||||
Console.stderr.write("none\n");
|
||||
Console.error("none");
|
||||
return 1;
|
||||
} else {
|
||||
Console.stdout.write(release.current.name + "\n");
|
||||
Console.stdout.write(files.getToolsVersion() + "\n");
|
||||
Console.rawInfo(release.current.name + "\n");
|
||||
Console.rawInfo(files.getToolsVersion() + "\n");
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
@@ -193,16 +196,16 @@ function doRunCommand (options) {
|
||||
var parsedUrl = utils.parseUrl(options.port);
|
||||
} catch (err) {
|
||||
if (options.verbose) {
|
||||
Console.stderr.write('Error while parsing --port option: '
|
||||
+ err.stack + '\n');
|
||||
Console.rawError(
|
||||
"Error while parsing --port option: " + err.stack + "\n");
|
||||
} else {
|
||||
Console.stderr.write(err.message + '\n');
|
||||
Console.error(err.message);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! parsedUrl.port) {
|
||||
Console.stderr.write("--port must include a port.\n");
|
||||
Console.error("--port must include a port.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -210,10 +213,10 @@ function doRunCommand (options) {
|
||||
var parsedMobileServer = utils.mobileServerForRun(options);
|
||||
} catch (err) {
|
||||
if (options.verbose) {
|
||||
Console.stderr.write('Error while parsing --mobile-server option: '
|
||||
+ err.stack + '\n');
|
||||
Console.rawError(
|
||||
"Error while parsing --mobile-server option: " + err.stack + "\n");
|
||||
} else {
|
||||
Console.stderr.write(err.message + '\n');
|
||||
Console.error(err.message);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -289,14 +292,13 @@ function doRunCommand (options) {
|
||||
// If we are targeting the remote devices, warn about ports and same network
|
||||
if (utils.runOnDevice(options)) {
|
||||
cordova.verboseLog('A run on a device requested');
|
||||
var warning = [
|
||||
"WARNING: You are testing your app on a remote device.",
|
||||
" For the mobile app to be able to connect to the local server, make",
|
||||
" sure your device is on the same network, and that the network",
|
||||
" configuration allows clients to talk to each other",
|
||||
" (no client isolation)."];
|
||||
|
||||
Console.stderr.write(warning.join("\n"));
|
||||
var warning =
|
||||
"You are testing your app on a remote device." +
|
||||
"For the mobile app to be able to connect to the local server, make " +
|
||||
"sure your device is on the same network, and that the network " +
|
||||
"configuration allows clients to talk to each other " +
|
||||
"(no client isolation).";
|
||||
Console.labelWarn(warning);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,9 +306,10 @@ function doRunCommand (options) {
|
||||
if (options['app-port']) {
|
||||
var appPortMatch = options['app-port'].match(/^(?:(.+):)?([0-9]+)?$/);
|
||||
if (!appPortMatch) {
|
||||
Console.stderr.write(
|
||||
"run: --app-port must be a number or be of the form 'host:port' where\n" +
|
||||
"port is a number. Try 'meteor help run' for help.\n");
|
||||
Console.error(
|
||||
"run: --app-port must be a number or be of the form 'host:port' ",
|
||||
"where port is a number. Try",
|
||||
Console.command("'meteor help run'") + " for help.");
|
||||
return 1;
|
||||
}
|
||||
appHost = appPortMatch[1] || null;
|
||||
@@ -378,8 +381,9 @@ main.registerCommand({
|
||||
catalogRefresh: new catalog.Refresh.Never()
|
||||
}, function (options) {
|
||||
if (!options.appDir) {
|
||||
Console.stderr.write(
|
||||
"The 'meteor shell' command must be run in a Meteor app directory."
|
||||
Console.error(
|
||||
"The " + Console.command("'meteor shell'") + " command must be run",
|
||||
"in a Meteor app directory."
|
||||
);
|
||||
} else {
|
||||
require('./server/shell.js').connect(options.appDir);
|
||||
@@ -411,12 +415,13 @@ main.registerCommand({
|
||||
|
||||
// No package examples exist yet.
|
||||
if (options.list && options.example) {
|
||||
Console.stderr.write("No package examples exist at this time.\n\n");
|
||||
Console.error("No package examples exist at this time.");
|
||||
Console.error();
|
||||
throw new main.ShowUsage;
|
||||
}
|
||||
|
||||
if (!packageName) {
|
||||
Console.stderr.write("Please specify the name of the package. \n");
|
||||
Console.error("Please specify the name of the package.");
|
||||
throw new main.ShowUsage;
|
||||
}
|
||||
|
||||
@@ -429,7 +434,7 @@ main.registerCommand({
|
||||
var inYourApp = options.appDir ? " in your app" : "";
|
||||
|
||||
if (fs.existsSync(packageDir)) {
|
||||
Console.stderr.write(packageName + ": Already exists" + inYourApp + "\n");
|
||||
Console.error(packageName + ": Already exists" + inYourApp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -468,11 +473,11 @@ main.registerCommand({
|
||||
ignore: [/^local$/]
|
||||
});
|
||||
} catch (err) {
|
||||
Console.stderr.write("Could not create package: " + err.message + "\n");
|
||||
Console.error("Could not create package: " + err.message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.stdout.write(packageName + ": created" + inYourApp + "\n");
|
||||
Console.info(packageName + ": created" + inYourApp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -498,12 +503,16 @@ main.registerCommand({
|
||||
});
|
||||
|
||||
if (options.list) {
|
||||
Console.stdout.write("Available examples:\n");
|
||||
Console.info("Available examples:");
|
||||
_.each(examples, function (e) {
|
||||
Console.stdout.write(" " + e + "\n");
|
||||
Console.info(
|
||||
Console.command(e),
|
||||
Console.options({ indent: 2 }));
|
||||
});
|
||||
Console.stdout.write("\n" +
|
||||
"Create a project from an example with 'meteor create --example <name>'.\n");
|
||||
Console.info();
|
||||
Console.info(
|
||||
"Create a project from an example with " +
|
||||
Console.command("'meteor create --example <name>'") + ".");
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -517,13 +526,13 @@ main.registerCommand({
|
||||
var appPath = path.resolve(appPathAsEntered);
|
||||
|
||||
if (fs.existsSync(appPath)) {
|
||||
Console.stderr.write(appPath + ": Already exists\n");
|
||||
Console.error(appPath + ": Already exists");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (files.findAppDir(appPath)) {
|
||||
Console.stderr.write(
|
||||
"You can't create a Meteor project inside another Meteor project.\n");
|
||||
Console.error(
|
||||
"You can't create a Meteor project inside another Meteor project.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -533,8 +542,11 @@ main.registerCommand({
|
||||
|
||||
if (options.example) {
|
||||
if (examples.indexOf(options.example) === -1) {
|
||||
Console.stderr.write(options.example + ": no such example\n\n");
|
||||
Console.stderr.write("List available applications with 'meteor create --list'.\n");
|
||||
Console.error(options.example + ": no such example.");
|
||||
Console.error();
|
||||
Console.error(
|
||||
"List available applications with",
|
||||
Console.command("'meteor create --list'") + ".");
|
||||
return 1;
|
||||
} else {
|
||||
files.cp_r(path.join(exampleDir, options.example), appPath, {
|
||||
@@ -597,10 +609,12 @@ main.registerCommand({
|
||||
Console.info(message);
|
||||
}
|
||||
|
||||
Console.stdout.write(
|
||||
"To run your new app:\n" +
|
||||
" cd " + appPathAsEntered + "\n" +
|
||||
" meteor\n");
|
||||
Console.info("To run your new app:");
|
||||
Console.info(
|
||||
Console.command("cd " + appPathAsEntered), Console.options({ indent: 2 }));
|
||||
Console.info(
|
||||
Console.command("meteor"), Console.options({ indent: 2 }));
|
||||
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -638,11 +652,13 @@ main.registerCommand(_.extend({ name: 'bundle', hidden: true
|
||||
}, buildCommands),
|
||||
function (options) {
|
||||
|
||||
Console.stderr.write(
|
||||
"This command has been deprecated in favor of 'meteor build', which allows you to\n" +
|
||||
"build for multiple platforms and outputs a directory instead of a single\n" +
|
||||
"tarball. See 'meteor help build' for more information.\n\n");
|
||||
|
||||
Console.error(
|
||||
"This command has been deprecated in favor of " +
|
||||
Console.command("'meteor build'") + ", which allows you to " +
|
||||
"build for multiple platforms and outputs a directory instead of " +
|
||||
"a single tarball. See " + Console.command("'meteor help build'") +
|
||||
"for more information.");
|
||||
Console.error();
|
||||
return buildCommand(_.extend(options, { _serverOnly: true }));
|
||||
});
|
||||
|
||||
@@ -697,20 +713,20 @@ var buildCommand = function (options) {
|
||||
var parsedMobileServer = utils.parseUrl(
|
||||
mobileServer, { protocol: "http://" });
|
||||
} catch (err) {
|
||||
Console.stderr.write(err.message);
|
||||
Console.error(err.message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! parsedMobileServer.host) {
|
||||
Console.stderr.write("--server must include a hostname.\n");
|
||||
Console.error("--server must include a hostname.");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
// For Cordova builds, require '--server'.
|
||||
// XXX better error message?
|
||||
Console.stderr.write(
|
||||
"Supply the server hostname and port in the --server option\n" +
|
||||
"for mobile app builds.\n");
|
||||
Console.error(
|
||||
"Supply the server hostname and port in the --server option " +
|
||||
"for mobile app builds.");
|
||||
return 1;
|
||||
}
|
||||
var cordovaSettings = {};
|
||||
@@ -742,11 +758,14 @@ var buildCommand = function (options) {
|
||||
// We would like the output path to be outside the app directory, which
|
||||
// means the first step to getting there is going up a level.
|
||||
if (relative.substr(0, 3) !== ('..' + path.sep)) {
|
||||
Console.warn("");
|
||||
Console.warn("Warning: The output directory is under your source tree.");
|
||||
Console.warn(" Your generated files may get interpreted as source code!");
|
||||
Console.warn(" Consider building into a different directory instead (" + Console.command("meteor build ../output") + ")");
|
||||
Console.warn("");
|
||||
Console.warn();
|
||||
Console.labelWarn(
|
||||
"The output directory is under your source tree.",
|
||||
"Your generated files may get interpreted as source code!",
|
||||
"Consider building into a different directory instead (" +
|
||||
Console.command("meteor build ../output") + ")",
|
||||
Console.options({ indent: 2 }));
|
||||
Console.warn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,8 +794,8 @@ var buildCommand = function (options) {
|
||||
}
|
||||
});
|
||||
if (bundleResult.errors) {
|
||||
Console.stderr.write("Errors prevented bundling:\n");
|
||||
Console.stderr.write(bundleResult.errors.formatMessages());
|
||||
Console.error("Errors prevented bundling:");
|
||||
Console.error(bundleResult.errors.formatMessages());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -790,8 +809,8 @@ var buildCommand = function (options) {
|
||||
|
||||
files.createTarball(path.join(buildDir, 'bundle'), outputTar);
|
||||
} catch (err) {
|
||||
Console.stderr.write("Errors during tarball creation:\n");
|
||||
Console.stderr.write(err.message);
|
||||
Console.error("Errors during tarball creation:");
|
||||
Console.error(err.message);
|
||||
files.rm_recursive(buildDir);
|
||||
return 1;
|
||||
}
|
||||
@@ -868,17 +887,18 @@ main.registerCommand({
|
||||
// specified?
|
||||
|
||||
if (! mongoPort) {
|
||||
Console.stdout.write(
|
||||
"mongo: Meteor isn't running a local MongoDB server.\n" +
|
||||
"\n" +
|
||||
"This command only works while Meteor is running your application\n" +
|
||||
"locally. Start your application first. (This error will also occur if\n" +
|
||||
"you asked Meteor to use a different MongoDB server with $MONGO_URL when\n" +
|
||||
"you ran your application.)\n" +
|
||||
"\n" +
|
||||
"If you're trying to connect to the database of an app you deployed\n" +
|
||||
"with 'meteor deploy', specify your site's name with this command.\n"
|
||||
);
|
||||
Console.info("mongo: Meteor isn't running a local MongoDB server.");
|
||||
Console.info();
|
||||
Console.info(
|
||||
"This command only works while Meteor is running your application " +
|
||||
"locally. Start your application first. (This error will also occur " +
|
||||
"if you asked Meteor to use a different MongoDB server with " +
|
||||
"$MONGO_URL when you ran your application.)");
|
||||
Console.info();
|
||||
Console.info(
|
||||
"If you're trying to connect to the database of an app you deployed " +
|
||||
"with " + Console.command("'meteor deploy'") +
|
||||
", specify your site's name with this command.");
|
||||
return 1;
|
||||
}
|
||||
mongoUrl = "mongodb://127.0.0.1:" + mongoPort + "/meteor";
|
||||
@@ -925,13 +945,14 @@ main.registerCommand({
|
||||
catalogRefresh: new catalog.Refresh.Never()
|
||||
}, function (options) {
|
||||
if (options.args.length !== 0) {
|
||||
Console.stderr.write(
|
||||
"meteor reset only affects the locally stored database.\n" +
|
||||
"\n" +
|
||||
"To reset a deployed application use\n" +
|
||||
" meteor deploy --delete appname\n" +
|
||||
"followed by\n" +
|
||||
" meteor deploy appname\n");
|
||||
Console.error("meteor reset only affects the locally stored database.");
|
||||
Console.error();
|
||||
Console.error("To reset a deployed application use");
|
||||
Console.error(
|
||||
Console.command("meteor deploy --delete appname"), Console.options({ indent: 2 }));
|
||||
Console.error("followed by");
|
||||
Console.error(
|
||||
Console.command("meteor deploy appname"), Console.options({ indent: 2 }));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -942,18 +963,18 @@ main.registerCommand({
|
||||
require(path.join(__dirname, 'run-mongo.js')).findMongoPort;
|
||||
var isRunning = !! findMongoPort(options.appDir);
|
||||
if (isRunning) {
|
||||
Console.stderr.write(
|
||||
"reset: Meteor is running.\n" +
|
||||
"\n" +
|
||||
"This command does not work while Meteor is running your application.\n" +
|
||||
"Exit the running Meteor development server.\n");
|
||||
Console.error("reset: Meteor is running.");
|
||||
Console.error();
|
||||
Console.error(
|
||||
"This command does not work while Meteor is running your application.",
|
||||
"Exit the running Meteor development server.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var localDir = path.join(options.appDir, '.meteor', 'local');
|
||||
files.rm_recursive(localDir);
|
||||
|
||||
Console.stdout.write("Project reset.\n");
|
||||
Console.info("Project reset.");
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1004,13 +1025,14 @@ main.registerCommand({
|
||||
|
||||
if (options.password) {
|
||||
if (useGalaxy) {
|
||||
Console.stderr.write("Galaxy does not support --password.\n");
|
||||
Console.error("Galaxy does not support --password.");
|
||||
} else {
|
||||
Console.stderr.write(
|
||||
"Setting passwords on apps is no longer supported. Now there are\n" +
|
||||
"user accounts and your apps are associated with your account so that\n" +
|
||||
"only you (and people you designate) can access them. See the\n" +
|
||||
"'meteor claim' and 'meteor authorized' commands.\n");
|
||||
Console.error(
|
||||
"Setting passwords on apps is no longer supported. Now there are " +
|
||||
"user accounts and your apps are associated with your account so " +
|
||||
"that only you (and people you designate) can access them. See the " +
|
||||
Console.command("'meteor claim'") + " and " +
|
||||
Console.command("'meteor authorized'") + " commands.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1018,18 +1040,16 @@ main.registerCommand({
|
||||
var starball = options.star;
|
||||
if (starball && ! useGalaxy) {
|
||||
// XXX it would be nice to support this for non-Galaxy deploys too
|
||||
Console.stderr.write(
|
||||
"--star: only supported when deploying to Galaxy.\n");
|
||||
Console.error("--star: only supported when deploying to Galaxy.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var loggedIn = auth.isLoggedIn();
|
||||
if (! loggedIn) {
|
||||
Console.stderr.write(
|
||||
"To instantly deploy your app on a free testing server, just enter your\n" +
|
||||
"email address!\n" +
|
||||
"\n");
|
||||
|
||||
Console.error(
|
||||
"To instantly deploy your app on a free testing server,",
|
||||
"just enter your email address!");
|
||||
Console.error();
|
||||
if (! auth.registerOrLogIn())
|
||||
return 1;
|
||||
}
|
||||
@@ -1037,10 +1057,11 @@ main.registerCommand({
|
||||
// Override architecture iff applicable.
|
||||
var buildArch = DEPLOY_ARCH;
|
||||
if (options['override-architecture-with-local']) {
|
||||
Console.stdout.write(
|
||||
"\n => WARNING: OVERRIDING DEPLOY ARCHITECTURE WITH LOCAL ARCHITECTURE\n");
|
||||
Console.stdout.write(
|
||||
" => If your app contains binary code, it may break terribly and you will be sad.\n\n");
|
||||
Console.warn();
|
||||
Console.labelWarn(
|
||||
"OVERRIDING DEPLOY ARCHITECTURE WITH LOCAL ARCHITECTURE.",
|
||||
"If your app contains binary code, it may break in unexpected " +
|
||||
"and terrible ways.");
|
||||
buildArch = archinfo.host();
|
||||
}
|
||||
|
||||
@@ -1142,14 +1163,15 @@ main.registerCommand({
|
||||
}, function (options) {
|
||||
|
||||
if (options.add && options.remove) {
|
||||
Console.stderr.write(
|
||||
"Sorry, you can only add or remove one user at a time.\n");
|
||||
Console.error(
|
||||
"Sorry, you can only add or remove one user at a time.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((options.add || options.remove) && options.list) {
|
||||
Console.stderr.write(
|
||||
"Sorry, you can't change the users at the same time as you're listing them.\n");
|
||||
Console.error(
|
||||
"Sorry, you can't change the users at the same time as",
|
||||
"you're listing them.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1158,16 +1180,17 @@ main.registerCommand({
|
||||
var site = qualifySitename(options.args[0]);
|
||||
|
||||
if (hostedWithGalaxy(site)) {
|
||||
Console.stderr.write(
|
||||
"Sites hosted on Galaxy do not have an authorized user list.\n" +
|
||||
"Instead, go to your Galaxy dashboard to change the authorized users\n" +
|
||||
"of your Galaxy.\n");
|
||||
Console.error(
|
||||
"Sites hosted on Galaxy do not have an authorized user list. " +
|
||||
"Instead, go to your Galaxy dashboard to change the authorized users " +
|
||||
"of your Galaxy.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! auth.isLoggedIn()) {
|
||||
Console.stderr.write(
|
||||
"You must be logged in for that. Try 'meteor login'.\n");
|
||||
Console.error(
|
||||
"You must be logged in for that. Try " +
|
||||
Console.command("'meteor login'"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1194,16 +1217,19 @@ main.registerCommand({
|
||||
var site = qualifySitename(options.args[0]);
|
||||
|
||||
if (! auth.isLoggedIn()) {
|
||||
Console.stderr.write(
|
||||
"You must be logged in to claim sites. Use 'meteor login' to log in.\n" +
|
||||
"If you don't have a Meteor developer account yet, create one by clicking\n" +
|
||||
"'Sign in' and then 'Create account' at www.meteor.com.\n\n");
|
||||
Console.error(
|
||||
"You must be logged in to claim sites. Use " +
|
||||
Console.command("'meteor login'") + " to log in. If you don't have a " +
|
||||
"Meteor developer account yet, create one by clicking " +
|
||||
Console.command("'Sign in'") + " and then " +
|
||||
Console.command("'Create account'") + " at www.meteor.com.");
|
||||
Console.error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (hostedWithGalaxy(site)) {
|
||||
Console.stderr.write(
|
||||
"Sorry, you can't claim sites that are hosted on Galaxy.\n");
|
||||
Console.error(
|
||||
"Sorry, you can't claim sites that are hosted on Galaxy.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1270,19 +1296,19 @@ main.registerCommand({
|
||||
try {
|
||||
var parsedUrl = utils.parseUrl(options.port);
|
||||
} catch (err) {
|
||||
Console.stderr.write(err.message);
|
||||
Console.error(err.message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! parsedUrl.port) {
|
||||
Console.stderr.write("--port must include a port.\n");
|
||||
Console.error("--port must include a port.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
var parsedMobileServer = utils.mobileServerForRun(options);
|
||||
} catch (err) {
|
||||
Console.stderr.write(err.message);
|
||||
Console.error(err.message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1583,18 +1609,18 @@ main.registerCommand({
|
||||
var loggedInAccountsConnectionOrPrompt = function (action) {
|
||||
var token = auth.getSessionToken(config.getAccountsDomain());
|
||||
if (! token) {
|
||||
Console.stderr.write("You must be logged in to " + action + ".\n");
|
||||
Console.error("You must be logged in to " + action + ".");
|
||||
auth.doUsernamePasswordLogin({ retry: true });
|
||||
Console.stdout.write("\n");
|
||||
Console.info();
|
||||
}
|
||||
|
||||
token = auth.getSessionToken(config.getAccountsDomain());
|
||||
var conn = auth.loggedInAccountsConnection(token);
|
||||
if (conn === null) {
|
||||
// Server rejected our token.
|
||||
Console.stderr.write("You must be logged in to " + action + ".\n");
|
||||
Console.error("You must be logged in to " + action + ".");
|
||||
auth.doUsernamePasswordLogin({ retry: true });
|
||||
Console.stdout.write("\n");
|
||||
Console.info();
|
||||
token = auth.getSessionToken(config.getAccountsDomain());
|
||||
conn = auth.loggedInAccountsConnection(token);
|
||||
}
|
||||
@@ -1612,9 +1638,9 @@ main.registerCommand({
|
||||
|
||||
var token = auth.getSessionToken(config.getAccountsDomain());
|
||||
if (! token) {
|
||||
Console.stderr.write("You must be logged in to list your organizations.\n");
|
||||
Console.error("You must be logged in to list your organizations.");
|
||||
auth.doUsernamePasswordLogin({ retry: true });
|
||||
Console.stdout.write("\n");
|
||||
Console.info();
|
||||
}
|
||||
|
||||
var url = config.getAccountsApiUrl() + "/organizations";
|
||||
@@ -1627,13 +1653,13 @@ main.registerCommand({
|
||||
});
|
||||
var body = JSON.parse(result.body);
|
||||
} catch (err) {
|
||||
Console.stderr.write("Error listing organizations.\n");
|
||||
Console.error("Error listing organizations.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (result.response.statusCode === 401 &&
|
||||
body && body.error === "invalid_credential") {
|
||||
Console.stderr.write("You must be logged in to list your organizations.\n");
|
||||
Console.error("You must be logged in to list your organizations.");
|
||||
// XXX It would be nice to do a username/password prompt here like
|
||||
// we do for the other orgs commands.
|
||||
return 1;
|
||||
@@ -1641,14 +1667,14 @@ main.registerCommand({
|
||||
|
||||
if (result.response.statusCode !== 200 ||
|
||||
! body || ! body.organizations) {
|
||||
Console.stderr.write("Error listing organizations.\n");
|
||||
Console.error("Error listing organizations.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (body.organizations.length === 0) {
|
||||
Console.stdout.write("You are not a member of any organizations.\n");
|
||||
Console.info("You are not a member of any organizations.");
|
||||
} else {
|
||||
Console.stdout.write(_.pluck(body.organizations, "name").join("\n") + "\n");
|
||||
Console.rawInfo(_.pluck(body.organizations, "name").join("\n") + "\n");
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
@@ -1666,8 +1692,8 @@ main.registerCommand({
|
||||
}, function (options) {
|
||||
|
||||
if (options.add && options.remove) {
|
||||
Console.stderr.write(
|
||||
"Sorry, you can only add or remove one member at a time.\n");
|
||||
Console.error(
|
||||
"Sorry, you can only add or remove one member at a time.");
|
||||
throw new main.ShowUsage;
|
||||
}
|
||||
|
||||
@@ -1685,28 +1711,26 @@ main.registerCommand({
|
||||
options.add ? "addOrganizationMember": "removeOrganizationMember",
|
||||
options.args[0], username);
|
||||
} catch (err) {
|
||||
Console.stderr.write("Error " +
|
||||
(options.add ? "adding" : "removing") +
|
||||
" member: " + err.reason + "\n");
|
||||
Console.error("Error " +
|
||||
(options.add ? "adding" : "removing") +
|
||||
" member: " + err.reason);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.stdout.write(username + " " +
|
||||
Console.info(username + " " +
|
||||
(options.add ? "added to" : "removed from") +
|
||||
" organization " + options.args[0] + ".\n");
|
||||
" organization " + options.args[0] + ".");
|
||||
} else {
|
||||
// Showing the members of an org
|
||||
try {
|
||||
var result = conn.call("showOrganization", options.args[0]);
|
||||
} catch (err) {
|
||||
Console.stderr.write("Error showing organization: " +
|
||||
err.reason + "\n");
|
||||
Console.error("Error showing organization: " + err.reason);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var members = _.pluck(result, "username");
|
||||
|
||||
Console.stdout.write(members.join("\n") + "\n");
|
||||
Console.rawInfo(members.join("\n") + "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1755,7 +1779,7 @@ main.registerCommand({
|
||||
} catch (e) {
|
||||
if (!(e instanceof SyntaxError))
|
||||
throw e;
|
||||
Console.stderr.write("Bad regular expression: " + str + "\n");
|
||||
Console.error("Bad regular expression: " + str);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -1818,8 +1842,9 @@ main.registerCommand({
|
||||
}, function (options) {
|
||||
auth.pollForRegistrationCompletion();
|
||||
if (! auth.isLoggedIn()) {
|
||||
Console.stderr.write(
|
||||
"You must be logged in for that. Try 'meteor login'.\n");
|
||||
Console.error(
|
||||
"You must be logged in for that. Try " +
|
||||
Console.command("'meteor login'") + ".");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1898,7 +1923,7 @@ main.registerCommand({
|
||||
'key' : ret.sshKey,
|
||||
'hostKey' : ret.hostKey
|
||||
};
|
||||
Console.info(JSON.stringify(retJson, null, 2));
|
||||
Console.rawInfo(JSON.stringify(retJson, null, 2) + "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1926,7 +1951,7 @@ main.registerCommand({
|
||||
maybeVerbose];
|
||||
|
||||
var printOptions = connOptions.join(' ');
|
||||
maybeLog("Connecting: ssh " + printOptions);
|
||||
maybeLog("Connecting: " + Console.command("ssh " + printOptions));
|
||||
|
||||
var child_process = require('child_process');
|
||||
var future = new Future;
|
||||
@@ -1978,10 +2003,10 @@ main.registerCommand({
|
||||
return 'none';
|
||||
};
|
||||
|
||||
Console.stdout.write(p('email') + " " + p('port') + " " + p('changed') +
|
||||
" " + p('args') + "\n");
|
||||
Console.info(p('email') + " " + p('port') + " " + p('changed') +
|
||||
" " + p('args'));
|
||||
if (options.url)
|
||||
Console.stdout.write('url\n');
|
||||
Console.info('url');
|
||||
if (options['delete'])
|
||||
Console.stdout.write('delete\n');
|
||||
Console.info('delete');
|
||||
});
|
||||
|
||||
473
tools/console.js
473
tools/console.js
@@ -1,17 +1,17 @@
|
||||
///
|
||||
/// utility functions for formatting output to the screen
|
||||
/// A set of utility functions for formatting output sent to the screen.
|
||||
///
|
||||
/// Console offers several pieces of functionality:
|
||||
/// debug / info / warn messages:
|
||||
/// Outputs to the screen, optionally with colors (when pretty == true)
|
||||
/// 'legacy' functions: Console.stdout.write & Console.stderr.write
|
||||
/// Make porting code a lot easier (just a regex from process -> Console)
|
||||
/// Progress bar support
|
||||
/// Displays a progress bar on the screen, but hides it around log messages
|
||||
/// (The need to hide it is why we have this class)
|
||||
/// - debug / info / warn messages: Output to the screen, optionally with
|
||||
/// colors (when pretty == true). Wrap the output to the width of the user's
|
||||
/// terminal, making sure to not split the same word over multiple
|
||||
/// lines. (Also provides 'rawInfo', 'rawDebug' (etc) for when you DON'T want
|
||||
/// to pre-process the output.)
|
||||
/// - Progress bar support
|
||||
/// Display a progress bar on the screen, but hide it around log messages.
|
||||
///
|
||||
/// In future, we might do things like move all support for verbose mode in here,
|
||||
/// and also integrate the buildmessage functionality into here
|
||||
/// In future, we might do things like move all support for verbose mode in
|
||||
/// here, and also integrate the buildmessage functionality into here
|
||||
///
|
||||
|
||||
var _ = require('underscore');
|
||||
@@ -24,6 +24,7 @@ var buildmessage = require('./buildmessage.js');
|
||||
var chalk = require('chalk');
|
||||
var cleanup = require('./cleanup.js');
|
||||
var utils = require('./utils.js');
|
||||
var wordwrap = require('wordwrap');
|
||||
|
||||
var PROGRESS_DEBUG = !!process.env.METEOR_PROGRESS_DEBUG;
|
||||
var FORCE_PRETTY=undefined;
|
||||
@@ -31,11 +32,10 @@ if (process.env.METEOR_PRETTY_OUTPUT) {
|
||||
FORCE_PRETTY = process.env.METEOR_PRETTY_OUTPUT != '0';
|
||||
}
|
||||
|
||||
if (!process.env.METEOR_COLOR) {
|
||||
if (! process.env.METEOR_COLOR) {
|
||||
chalk.enabled = false;
|
||||
}
|
||||
|
||||
|
||||
var STATUSLINE_MAX_LENGTH = 60; // XXX unused?
|
||||
var STATUS_MAX_LENGTH = 40;
|
||||
|
||||
@@ -49,6 +49,18 @@ var STATUS_INTERVAL_MS = 500;
|
||||
// XXX: ? FALLBACK_STATUS = 'Pondering';
|
||||
var FALLBACK_STATUS = '';
|
||||
|
||||
// If there is a part of the larger text, and we really want to make sure that
|
||||
// it doesn't get split up, we will replace the space with a utf character that
|
||||
// we are not likely to use anywhere else. This one looks like the a BLACK SUN
|
||||
// WITH RAYS. We intentionally want to NOT use a space-like character: it should
|
||||
// be obvious that something has gone wrong if this ever gets printed.
|
||||
var SPACE_REPLACEMENT = '\u2600';
|
||||
// In Javascript, replace only replaces the first occurance and this is the
|
||||
// proposed alternative.
|
||||
var replaceAll = function (str, search, replace) {
|
||||
return str.split(search).join(replace);
|
||||
};
|
||||
|
||||
var spacesArray = new Array(200).join(' ');
|
||||
var spacesString = function (length) {
|
||||
if (length > spacesArray.length) {
|
||||
@@ -56,6 +68,8 @@ var spacesString = function (length) {
|
||||
}
|
||||
return spacesArray.substring(0, length);
|
||||
};
|
||||
var ARROW = "=> ";
|
||||
|
||||
|
||||
var toFixedLength = function (text, length) {
|
||||
text = text || "";
|
||||
@@ -72,7 +86,8 @@ var toFixedLength = function (text, length) {
|
||||
return text;
|
||||
};
|
||||
|
||||
// No-op progress display, that means we don't have to handle the 'no progress display' case
|
||||
// No-op progress display, that means we don't have to handle the 'no progress
|
||||
// display' case
|
||||
var ProgressDisplayNone = function () {
|
||||
};
|
||||
|
||||
@@ -217,7 +232,7 @@ _.extend(ProgressBarRenderer.prototype, {
|
||||
.replace(':current', self.curr)
|
||||
.replace(':total', self.total)
|
||||
.replace(':elapsed', isNaN(elapsed) ? '0.0' : (elapsed / 1000).toFixed(1))
|
||||
.replace(':eta', (isNaN(eta) || !isFinite(eta)) ? '0.0' : (eta / 1000).toFixed(1))
|
||||
.replace(':eta', (isNaN(eta) || ! isFinite(eta)) ? '0.0' : (eta / 1000).toFixed(1))
|
||||
.replace(':percent', percent.toFixed(0) + '%');
|
||||
|
||||
/* compute the available space (non-zero) for the bar */
|
||||
@@ -312,7 +327,7 @@ _.extend(ProgressDisplayFull.prototype, {
|
||||
var streamColumns = this._stream.columns;
|
||||
var statusColumns;
|
||||
var progressColumns;
|
||||
if (!streamColumns) {
|
||||
if (! streamColumns) {
|
||||
statusColumns = STATUS_MAX_LENGTH;
|
||||
progressColumns = 0;
|
||||
} else {
|
||||
@@ -377,7 +392,7 @@ _.extend(StatusPoller.prototype, {
|
||||
}
|
||||
|
||||
self._pollFiber = Fiber(function () {
|
||||
while (!self._stop) {
|
||||
while (! self._stop) {
|
||||
utils.sleepMs(100);
|
||||
|
||||
self.statusPoll();
|
||||
@@ -414,7 +429,7 @@ _.extend(StatusPoller.prototype, {
|
||||
} else {
|
||||
var fraction = state.done ? 1.0 : (state.current / state.end);
|
||||
|
||||
if (!isNaN(fraction) && fraction >= 0) {
|
||||
if (! isNaN(fraction) && fraction >= 0) {
|
||||
progressDisplay.updateProgress(fraction, startTime);
|
||||
} else {
|
||||
progressDisplay.updateProgress(0, startTime);
|
||||
@@ -471,12 +486,6 @@ var Console = function (options) {
|
||||
// Legacy helpers
|
||||
self.stdout = {};
|
||||
self.stderr = {};
|
||||
self.stdout.write = function (msg) {
|
||||
self._legacyWrite(LEVEL_INFO, msg);
|
||||
};
|
||||
self.stderr.write = function (msg) {
|
||||
self._legacyWrite(LEVEL_WARN, msg);
|
||||
};
|
||||
|
||||
self._stream = process.stdout;
|
||||
|
||||
@@ -497,7 +506,6 @@ var Console = function (options) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var LEVEL_CODE_ERROR = 4;
|
||||
var LEVEL_CODE_WARN = 3;
|
||||
var LEVEL_CODE_INFO = 2;
|
||||
@@ -508,6 +516,15 @@ var LEVEL_WARN = { code: LEVEL_CODE_WARN };
|
||||
var LEVEL_INFO = { code: LEVEL_CODE_INFO };
|
||||
var LEVEL_DEBUG = { code: LEVEL_CODE_DEBUG };
|
||||
|
||||
// We use a special class to represent the options that we send to the Console
|
||||
// because it allows us to call 'instance of' on the last argument of variadic
|
||||
// functions. This allows us to keep the signature of our custom output
|
||||
// functions (ex: info) roughly the same as the originals.
|
||||
var ConsoleOptions = function (o) {
|
||||
var self = this;
|
||||
self.options = o;
|
||||
}
|
||||
|
||||
_.extend(Console.prototype, {
|
||||
LEVEL_ERROR: LEVEL_ERROR,
|
||||
LEVEL_WARN: LEVEL_WARN,
|
||||
@@ -537,7 +554,7 @@ _.extend(Console.prototype, {
|
||||
self._pretty = self._progressDisplayEnabled = true;
|
||||
|
||||
// Update the screen if anything changed.
|
||||
if (!originalPretty || !originalProgressDisplayEnabled)
|
||||
if (! originalPretty || ! originalProgressDisplayEnabled)
|
||||
self._updateProgressDisplay();
|
||||
|
||||
try {
|
||||
@@ -547,7 +564,7 @@ _.extend(Console.prototype, {
|
||||
self._pretty = originalPretty;
|
||||
self._progressDisplayEnabled = originalProgressDisplayEnabled;
|
||||
// Update the screen if anything changed.
|
||||
if (!originalPretty || !originalProgressDisplayEnabled)
|
||||
if (! originalPretty || ! originalProgressDisplayEnabled)
|
||||
self._updateProgressDisplay();
|
||||
}
|
||||
},
|
||||
@@ -557,6 +574,16 @@ _.extend(Console.prototype, {
|
||||
self.verbose = verbose;
|
||||
},
|
||||
|
||||
// Get the current width of the Console.
|
||||
width: function () {
|
||||
var width = 80;
|
||||
var stream = process.stdout;
|
||||
if (stream && stream.isTTY && stream.columns) {
|
||||
width = stream.columns;
|
||||
}
|
||||
return width;
|
||||
},
|
||||
|
||||
// This can be called during long lived operations; it will keep the spinner spinning.
|
||||
// (This code used to be in Patience.nudge)
|
||||
//
|
||||
@@ -583,6 +610,38 @@ _.extend(Console.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
// Initializes and returns a new ConsoleOptions object. This allows us to call
|
||||
// 'instance of' on the ConsoleOptions in parseVariadicInput, by ensuring that
|
||||
// the object created with Console.options is, in fact, a new object.
|
||||
options: function (o) {
|
||||
return new ConsoleOptions(o);
|
||||
},
|
||||
|
||||
// Deal with the arguments to a variadic print function that also takes an
|
||||
// optional ConsoleOptions argument at the end.
|
||||
//
|
||||
// Returns an object with keys:
|
||||
// - options: The options that were passed in, or an empty object.
|
||||
// - message: Arguments to the original function, parsed as a string.
|
||||
//
|
||||
_parseVariadicInput: function (args) {
|
||||
var self = this;
|
||||
var msgArgs;
|
||||
var options;
|
||||
// If the last argument is an instance of ConsoleOptions, then we should
|
||||
// separate it out, and only send the first N-1 arguments to be parsed as a
|
||||
// message.
|
||||
if (_.last(args) instanceof ConsoleOptions) {
|
||||
msgArgs = _.initial(args);
|
||||
options = _.last(args).options;
|
||||
} else {
|
||||
msgArgs = args;
|
||||
options = {};
|
||||
}
|
||||
var message = self._format(msgArgs);
|
||||
return { message: message, options: options };
|
||||
},
|
||||
|
||||
isLevelEnabled: function (levelCode) {
|
||||
return (this.verbose || this._logThreshold <= levelCode);
|
||||
},
|
||||
@@ -591,9 +650,12 @@ _.extend(Console.prototype, {
|
||||
return this.isLevelEnabled(LEVEL_CODE_DEBUG);
|
||||
},
|
||||
|
||||
debug: function(/*arguments*/) {
|
||||
|
||||
// Don't pretty-fy this output by trying to, for example, line-wrap it. Just
|
||||
// print it to the screen as it is.
|
||||
rawDebug: function(/*arguments*/) {
|
||||
var self = this;
|
||||
if (!self.isDebugEnabled()) {
|
||||
if (! self.isDebugEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -601,13 +663,32 @@ _.extend(Console.prototype, {
|
||||
self._print(LEVEL_DEBUG, message);
|
||||
},
|
||||
|
||||
// By default, Console.debug automatically line wraps the output.
|
||||
//
|
||||
// Takes in an optional Console.options({}) argument at the end, with the
|
||||
// following keys:
|
||||
// - bulletPoint: start the first line with a given string, then offset the
|
||||
// subsequent lines by the length of that string. See _wrap for more details.
|
||||
// - indent: offset the entire string by a specific number of
|
||||
// characters. See _wrap for more details.
|
||||
//
|
||||
debug: function(/*arguments*/) {
|
||||
var self = this;
|
||||
if (! self.isDebugEnabled()) { return; }
|
||||
|
||||
var message = self._prettifyMessage(arguments);
|
||||
self._print(LEVEL_DEBUG, message);
|
||||
},
|
||||
|
||||
isInfoEnabled: function () {
|
||||
return this.isLevelEnabled(LEVEL_CODE_INFO);
|
||||
},
|
||||
|
||||
info: function(/*arguments*/) {
|
||||
// Don't pretty-fy this output by trying to, for example, line-wrap it. Just
|
||||
// print it to the screen as it is.
|
||||
rawInfo: function(/*arguments*/) {
|
||||
var self = this;
|
||||
if (!self.isInfoEnabled()) {
|
||||
if (! self.isInfoEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -615,13 +696,24 @@ _.extend(Console.prototype, {
|
||||
self._print(LEVEL_INFO, message);
|
||||
},
|
||||
|
||||
// Generally, we want to process the output for legibility, for example, by
|
||||
// wrapping it. For raw output (ex: stack traces, user logs, etc), use the
|
||||
// rawInfo function. For more information about options, see: debug.
|
||||
info: function(/*arguments*/) {
|
||||
var self = this;
|
||||
if (! self.isInfoEnabled()) { return; }
|
||||
|
||||
var message = self._prettifyMessage(arguments);
|
||||
self._print(LEVEL_INFO, message);
|
||||
},
|
||||
|
||||
isWarnEnabled: function () {
|
||||
return this.isLevelEnabled(LEVEL_CODE_WARN);
|
||||
},
|
||||
|
||||
warn: function(/*arguments*/) {
|
||||
rawWarn: function(/*arguments*/) {
|
||||
var self = this;
|
||||
if (!self.isWarnEnabled()) {
|
||||
if (! self.isWarnEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -629,19 +721,45 @@ _.extend(Console.prototype, {
|
||||
self._print(LEVEL_WARN, message);
|
||||
},
|
||||
|
||||
error: function(/*arguments*/) {
|
||||
// Generally, we want to process the output for legibility, for example, by
|
||||
// wrapping it. For raw output (ex: stack traces, user logs, etc), use the
|
||||
// rawWarn function. For more information about options, see: debug.
|
||||
warn: function(/* arguments */) {
|
||||
var self = this;
|
||||
if (! self.isWarnEnabled()) { return; }
|
||||
|
||||
var message = self._prettifyMessage(arguments);
|
||||
self._print(LEVEL_WARN, message);
|
||||
},
|
||||
|
||||
rawError: function(/*arguments*/) {
|
||||
var self = this;
|
||||
|
||||
var message = self._format(arguments);
|
||||
self._print(LEVEL_ERROR, message);
|
||||
},
|
||||
|
||||
_legacyWrite: function (level, message) {
|
||||
// Generally, we want to process the output for legibility, for example, by
|
||||
// wrapping it. For raw output (ex: stack traces, user logs, etc), use the
|
||||
// rawError function. For more information about options, see: debug.
|
||||
error: function(/*arguments*/) {
|
||||
var self = this;
|
||||
if(message.substr && message.substr(-1) == '\n') {
|
||||
message = message.substr(0, message.length - 1);
|
||||
}
|
||||
self._print(level, message);
|
||||
|
||||
var message = self._prettifyMessage(arguments);
|
||||
self._print(LEVEL_ERROR, message);
|
||||
},
|
||||
|
||||
_prettifyMessage: function (msgArguments) {
|
||||
var self = this;
|
||||
var parsedArgs = self._parseVariadicInput(msgArguments);
|
||||
var wrapOpts = {
|
||||
indent: parsedArgs.options.indent,
|
||||
bulletPoint: parsedArgs.options.bulletPoint
|
||||
};
|
||||
|
||||
var wrappedMessage = self._wrapText(parsedArgs.message, wrapOpts);
|
||||
wrappedMessage += "\n";
|
||||
return wrappedMessage;
|
||||
},
|
||||
|
||||
_print: function(level, message) {
|
||||
@@ -679,69 +797,95 @@ _.extend(Console.prototype, {
|
||||
}
|
||||
|
||||
if (style) {
|
||||
dest.write(style(message + '\n'));
|
||||
dest.write(style(message));
|
||||
} else {
|
||||
dest.write(message + '\n');
|
||||
dest.write(message);
|
||||
}
|
||||
|
||||
// XXX: Pause before showing the progress display, to prevent flicker/spewing messages
|
||||
// XXX: Pause before showing the progress display, to prevent
|
||||
// flicker/spewing messages
|
||||
// Repaint the progress display
|
||||
progressDisplay.repaint();
|
||||
},
|
||||
|
||||
// A wrapper around Console.info. Prints the message out in green (if pretty),
|
||||
// with the CHECKMARK as the bullet point in front of it.
|
||||
success: function (message) {
|
||||
var self = this;
|
||||
|
||||
if (!self._pretty) {
|
||||
return message;
|
||||
if (! self._pretty) {
|
||||
return self.info(message);
|
||||
}
|
||||
return chalk.green('\u2713 ' + message); // CHECK MARK
|
||||
var checkmark = chalk.green('\u2713'); // CHECKMARK
|
||||
return self.info(
|
||||
chalk.green(message),
|
||||
self.options({ bulletPoint: checkmark + " "}));
|
||||
},
|
||||
|
||||
fail: function (message) {
|
||||
// Wrapper around Console.info. Prints the message out in red (if pretty)
|
||||
// with the BALLOT X as the bullet point in front of it.
|
||||
failInfo: function (message) {
|
||||
var self = this;
|
||||
return self._fail(message, "info");
|
||||
},
|
||||
|
||||
// Wrapper around Console.warn. Prints the message out in red (if pretty)
|
||||
// with the ascii x as the bullet point in front of it.
|
||||
failWarn: function (message) {
|
||||
var self = this;
|
||||
return self._fail(message, "warn");
|
||||
},
|
||||
|
||||
// Print the message in red (if pretty) with an x bullet point in front of it.
|
||||
_fail: function (message, printFn) {
|
||||
var self = this;
|
||||
|
||||
if (!self._pretty) {
|
||||
return message;
|
||||
if (! self._pretty) {
|
||||
return printFn(message);
|
||||
}
|
||||
return chalk.red('\u2717 ' + message); // BALLOT X
|
||||
|
||||
var xmark = chalk.red('\u2717');
|
||||
return self[printFn](
|
||||
chalk.red(message),
|
||||
self.options({ bulletPoint: xmark + " " }));
|
||||
},
|
||||
|
||||
command: function (message) {
|
||||
return this.bold(message);
|
||||
},
|
||||
|
||||
url: function (message) {
|
||||
return this.underline(message);
|
||||
},
|
||||
|
||||
underline: function (message) {
|
||||
// Wrapper around Console.warn that prints a large "WARNING" label in front.
|
||||
labelWarn: function (message) {
|
||||
var self = this;
|
||||
|
||||
if (!self._pretty) {
|
||||
return message;
|
||||
}
|
||||
return chalk.underline(message);
|
||||
return self.warn(message, self.options({ bulletPoint: "WARNING: " }));
|
||||
},
|
||||
|
||||
bold: function (message) {
|
||||
// Wrappers around Console functions to prints an "=> " in front. Optional
|
||||
// indent to indent the arrow.
|
||||
arrowError: function (message, indent) {
|
||||
var self = this;
|
||||
|
||||
if (!self._pretty) {
|
||||
return message;
|
||||
}
|
||||
return chalk.bold(message);
|
||||
},
|
||||
|
||||
_format: function (logArguments) {
|
||||
return util.format.apply(util, logArguments);
|
||||
return self._arrowPrint("error", message, indent);
|
||||
},
|
||||
arrowWarn: function (message, indent) {
|
||||
var self = this;
|
||||
return self._arrowPrint("warn", message, indent);
|
||||
},
|
||||
arrowInfo: function (message, indent) {
|
||||
var self = this;
|
||||
return self._arrowPrint("info", message, indent);
|
||||
},
|
||||
_arrowPrint: function(printFn, message, indent) {
|
||||
var self = this;
|
||||
indent = indent || 0;
|
||||
return self[printFn](
|
||||
message,
|
||||
self.options({ bulletPoint: ARROW, indent: indent }));
|
||||
},
|
||||
|
||||
// A wrapper around console.error. Given an error and some background
|
||||
// information, print out the correct set of messages depending on verbose
|
||||
// level, etc.
|
||||
printError: function (err, info) {
|
||||
var self = this;
|
||||
|
||||
var message = err.message;
|
||||
if (!message) {
|
||||
if (! message) {
|
||||
message = "Unexpected error";
|
||||
if (self.verbose) {
|
||||
message += " (" + err.toString() + ")";
|
||||
@@ -754,18 +898,187 @@ _.extend(Console.prototype, {
|
||||
|
||||
self.error(message);
|
||||
if (self.verbose && err.stack) {
|
||||
self.info(err.stack);
|
||||
self.rawInfo(err.stack + "\n");
|
||||
}
|
||||
},
|
||||
|
||||
// A wrapper to print out buildmessage errors.
|
||||
printMessages: function (messages) {
|
||||
var self = this;
|
||||
|
||||
if (messages.hasMessages()) {
|
||||
self._print(LEVEL_ERROR, "\n" + messages.formatMessages());
|
||||
self.error("\n" + messages.formatMessages());
|
||||
}
|
||||
},
|
||||
|
||||
// Wrap commands in this function -- it ensures that commands don't get line
|
||||
// wrapped (ie: print 'meteor' at the end of the line, and 'create --example'
|
||||
// at the beginning of the next one).
|
||||
//
|
||||
// To use, wrap commands that you send into print functions with this
|
||||
// function, like so: Console.info(text + Console.command("meteor create
|
||||
// --example leaderboard") + moretext).
|
||||
//
|
||||
// If pretty print is on, this will also bold the commands.
|
||||
command: function (message) {
|
||||
var self = this;
|
||||
var unwrapped = self.noWrap(message);
|
||||
return self.bold(unwrapped);
|
||||
},
|
||||
|
||||
// Underline the URLs (if pretty print is on).
|
||||
url: function (message) {
|
||||
var self = this;
|
||||
// If we are going to print URLs with spaces, we should turn spaces into
|
||||
// things browsers understand.
|
||||
var unspaced =
|
||||
replaceAll(message, ' ', '%20');
|
||||
// There is no need to call noWrap here, since that only handles spaces (and
|
||||
// we have done that). If it ever handles things other than spaces, we
|
||||
// should make sure to call it here.
|
||||
return self.underline(unspaced);
|
||||
},
|
||||
|
||||
// Format a filepath to not wrap. This does NOT automatically escape spaces
|
||||
// (ie: add a slash in front so the user could copy paste the file path into a
|
||||
// terminal).
|
||||
path: function (message) {
|
||||
var self = this;
|
||||
// Make sure that we don't wrap this.
|
||||
var unwrapped = self.noWrap(message);
|
||||
return self.bold(unwrapped);
|
||||
},
|
||||
|
||||
// Do not wrap this substring when you send it into a non-raw print function.
|
||||
// DO NOT print the result of this call with a raw function.
|
||||
noWrap: function (message) {
|
||||
var noBlanks = replaceAll(message, ' ', SPACE_REPLACEMENT);
|
||||
return noBlanks;
|
||||
},
|
||||
|
||||
// A wrapper around the underline functionality of chalk.
|
||||
underline: function (message) {
|
||||
var self = this;
|
||||
|
||||
if (! self._pretty) {
|
||||
return message;
|
||||
}
|
||||
return chalk.underline(message);
|
||||
},
|
||||
|
||||
// A wrapper around the bold functionality of chalk.
|
||||
bold: function (message) {
|
||||
var self = this;
|
||||
|
||||
if (! self._pretty) {
|
||||
return message;
|
||||
}
|
||||
return chalk.bold(message);
|
||||
},
|
||||
|
||||
// Prints a two column table in a nice format:
|
||||
// The first column is printed entirely, the second only as space permits
|
||||
printTwoColumns : function (rows, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
|
||||
var longest = '';
|
||||
_.each(rows, function (row) {
|
||||
var col0 = row[0] || '';
|
||||
if (col0.length > longest.length)
|
||||
longest = col0;
|
||||
});
|
||||
|
||||
var pad = longest.replace(/./g, ' ');
|
||||
var width = self.width();
|
||||
|
||||
var out = '';
|
||||
_.each(rows, function (row) {
|
||||
var col0 = row[0] || '';
|
||||
var col1 = row[1] || '';
|
||||
var line = self.bold(col0) + pad.substr(col0.length);
|
||||
line += " " + col1;
|
||||
if (line.length > width) {
|
||||
line = line.substr(0, width - 3) + '...';
|
||||
}
|
||||
out += line + "\n";
|
||||
});
|
||||
|
||||
var level = options.level || self.LEVEL_INFO;
|
||||
out += "\n";
|
||||
self._print(level, out);
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
// Format logs according to the spec in utils.
|
||||
_format: function (logArguments) {
|
||||
return util.format.apply(util, logArguments);
|
||||
},
|
||||
|
||||
// Wraps long strings to the length of user's terminal. Inserts linebreaks
|
||||
// between words when nearing the end of the line. Returns the wrapped string
|
||||
// and takes the following arguments:
|
||||
//
|
||||
// text: the text to wrap
|
||||
// options:
|
||||
|
||||
// - bulletPoint: start the first line with a given string, then offset the
|
||||
// subsequent lines by the length of that string. For example, if the
|
||||
// bulletpoint is " => ", we would get:
|
||||
// " => some long message starts here
|
||||
// and then continues here."
|
||||
// - indent: offset the entire string by a specific number of
|
||||
// characters. For example:
|
||||
// " This entire message is indented
|
||||
// by two characters."
|
||||
//
|
||||
// Passing in both options will offset the bulletPoint by the indentation,
|
||||
// like so:
|
||||
// " this message is indented by two."
|
||||
// " => this mesage indented by two and
|
||||
// and also starts with an arrow."
|
||||
//
|
||||
// When printing commands in-line, it is best to wrap commands in with Console.command
|
||||
// to make sure that they don't get line-wrapped. See Console.command for more details.
|
||||
_wrapText: function (text, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
|
||||
// Compute the maximum offset on the bulk of the message.
|
||||
var maxIndent = 0;
|
||||
if (options.indent && options.indent > 0) {
|
||||
maxIndent = maxIndent + options.indent;
|
||||
}
|
||||
if (options.bulletPoint) {
|
||||
maxIndent = maxIndent + options.bulletPoint.length;
|
||||
}
|
||||
|
||||
// Get the maximum width, or if we are not running in a terminal (self-test,
|
||||
// for example), default to 80 columns.
|
||||
var max = self.width();
|
||||
|
||||
// Wrap the text using the npm wordwrap library.
|
||||
var wrappedText = wordwrap(maxIndent, max)(text);
|
||||
|
||||
// Insert the start string, if applicable.
|
||||
if (options.bulletPoint) {
|
||||
// Save the initial indent level.
|
||||
var initIndent = options.indent ?
|
||||
wrappedText.substring(0, options.indent) : "";
|
||||
// Add together the initial indent (if any), the bullet point and the
|
||||
// remainder of the message.
|
||||
wrappedText = initIndent + options.bulletPoint +
|
||||
wrappedText.substring(maxIndent);
|
||||
}
|
||||
|
||||
// If we have previously replaces any spaces, now is the time to bring them
|
||||
// back.
|
||||
wrappedText = replaceAll(wrappedText, SPACE_REPLACEMENT, ' ');
|
||||
return wrappedText;
|
||||
},
|
||||
|
||||
|
||||
// Enables the progress bar, or disables it when called with (false)
|
||||
enableProgressDisplay: function (enabled) {
|
||||
var self = this;
|
||||
@@ -789,12 +1102,12 @@ _.extend(Console.prototype, {
|
||||
|
||||
var newProgressDisplay;
|
||||
|
||||
if (!self._progressDisplayEnabled) {
|
||||
if (! self._progressDisplayEnabled) {
|
||||
newProgressDisplay = new ProgressDisplayNone();
|
||||
} else if ((!self._stream.isTTY) || (!self._pretty)) {
|
||||
} else if ((! self._stream.isTTY) || (! self._pretty)) {
|
||||
// No progress bar if not in pretty / on TTY.
|
||||
newProgressDisplay = new ProgressDisplayNone(self);
|
||||
} else if (self._stream.isTTY && !self._stream.columns) {
|
||||
} else if (self._stream.isTTY && ! self._stream.columns) {
|
||||
// We might be in a pseudo-TTY that doesn't support
|
||||
// clearLine() and cursorTo(...).
|
||||
// It's important that we only enter status message mode
|
||||
@@ -809,7 +1122,7 @@ _.extend(Console.prototype, {
|
||||
|
||||
// Start/stop the status poller, so we never block exit
|
||||
if (self._progressDisplayEnabled) {
|
||||
if (!self._statusPoller) {
|
||||
if (! self._statusPoller) {
|
||||
self._statusPoller = new StatusPoller(self);
|
||||
}
|
||||
} else {
|
||||
@@ -834,8 +1147,6 @@ _.extend(Console.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
Console.prototype.warning = Console.prototype.warn;
|
||||
|
||||
// options:
|
||||
// - echo (boolean): defaults to true
|
||||
// - prompt (string)
|
||||
|
||||
@@ -13,6 +13,7 @@ var _ = require('underscore');
|
||||
var buildmessage = require('./buildmessage.js');
|
||||
var ServiceConnection = require('./service-connection.js');
|
||||
var stats = require('./stats.js');
|
||||
var Console = require('./console.js').Console;
|
||||
|
||||
// If 'error' is an exception that we know how to report in a
|
||||
// user-friendly way, print an approprite message to stderr and return
|
||||
@@ -27,9 +28,9 @@ var handleError = function (error, galaxyName, messages) {
|
||||
if (error.errorType === "Meteor.Error") {
|
||||
var msg = messages[error.error];
|
||||
if (msg)
|
||||
process.stderr.write(msg + "\n");
|
||||
Console.error(msg);
|
||||
else if (error.message)
|
||||
process.stderr.write("Denied: " + error.message + "\n");
|
||||
Console.error("Denied: " + error.message);
|
||||
return 1;
|
||||
} else if (error.errorType === "DDP.ConnectionError") {
|
||||
// If we have an http/https URL for a galaxyName instead of a
|
||||
@@ -39,7 +40,7 @@ var handleError = function (error, galaxyName, messages) {
|
||||
if (m)
|
||||
galaxyName = m[1];
|
||||
|
||||
process.stderr.write(galaxyName + ": connection failed\n");
|
||||
Console.error(galaxyName + ": connection failed");
|
||||
return 1;
|
||||
} else {
|
||||
throw error;
|
||||
@@ -147,7 +148,7 @@ exports.deleteApp = function (app) {
|
||||
|
||||
try {
|
||||
conn.call("destroyApp", app);
|
||||
process.stdout.write("Deleted.\n");
|
||||
Console.info("Deleted.");
|
||||
} catch (e) {
|
||||
return handleError(e, galaxy);
|
||||
} finally {
|
||||
@@ -193,7 +194,7 @@ exports.deploy = function (options) {
|
||||
// concurrent with bundling.
|
||||
|
||||
if (! options.starball && ! messages.hasMessages()) {
|
||||
process.stdout.write('Deploying ' + options.app + '. Bundling...\n');
|
||||
Console.info('Deploying ' + options.app + '. Bundling...');
|
||||
var bundleResult = bundler.bundle({
|
||||
projectContext: options.projectContext,
|
||||
outputPath: bundlePath,
|
||||
@@ -230,12 +231,12 @@ exports.deploy = function (options) {
|
||||
}
|
||||
|
||||
if (messages.hasMessages()) {
|
||||
process.stdout.write("\nErrors prevented deploying:\n");
|
||||
process.stdout.write(messages.formatMessages());
|
||||
Console.info("\nErrors prevented deploying:");
|
||||
Console.info(messages.formatMessages());
|
||||
return 1;
|
||||
}
|
||||
|
||||
process.stdout.write('Uploading...\n');
|
||||
Console.info('Uploading...');
|
||||
|
||||
var galaxy = exports.discoverGalaxy(options.app);
|
||||
conn = galaxyServiceConnection(galaxy, "ultraworld");
|
||||
@@ -289,11 +290,11 @@ exports.deploy = function (options) {
|
||||
if (error || ((response.statusCode !== 200)
|
||||
&& (response.statusCode !== 201))) {
|
||||
if (error && error.message)
|
||||
process.stderr.write("Upload failed: " + error.message + "\n");
|
||||
Console.error("Upload failed: " + error.message);
|
||||
else
|
||||
process.stderr.write("Upload failed" +
|
||||
(response.statusCode ?
|
||||
" (" + response.statusCode + ")\n" : "\n"));
|
||||
Console.error("Upload failed" +
|
||||
(response.statusCode ?
|
||||
" (" + response.statusCode + ")" : ""));
|
||||
future['return'](false);
|
||||
} else
|
||||
future['return'](true);
|
||||
@@ -313,10 +314,10 @@ exports.deploy = function (options) {
|
||||
}
|
||||
|
||||
if (created)
|
||||
process.stderr.write(options.app + ": created app\n");
|
||||
Console.error(options.app + ": created app\n");
|
||||
|
||||
process.stderr.write(options.app + ": " +
|
||||
"pushed revision " + result.serial + "\n");
|
||||
Console.error(options.app + ": " +
|
||||
"pushed revision " + result.serial);
|
||||
return 0;
|
||||
} finally {
|
||||
// Close the connection to Galaxy (otherwise Node will continue running).
|
||||
|
||||
199
tools/deploy.js
199
tools/deploy.js
@@ -256,12 +256,15 @@ var authedRpc = function (options) {
|
||||
// password-protected app, instruct them to claim it with 'meteor
|
||||
// claim'.
|
||||
var printLegacyPasswordMessage = function (site) {
|
||||
Console.stderr.write(
|
||||
"\nThis site was deployed with an old version of Meteor that used\n" +
|
||||
"site passwords instead of user accounts. Now we have a much better\n" +
|
||||
"system, Meteor developer accounts.\n\n" +
|
||||
"If this is your site, please claim it into your account with\n" +
|
||||
" meteor claim " + site + "\n");
|
||||
Console.error(
|
||||
"\nThis site was deployed with an old version of Meteor that used " +
|
||||
"site passwords instead of user accounts. Now we have a much better " +
|
||||
"system, Meteor developer accounts.");
|
||||
Console.error();
|
||||
Console.error("If this is your site, please claim it into your account with");
|
||||
Console.error(
|
||||
Console.command("meteor claim " + site),
|
||||
Console.options({ indent: 2 }));
|
||||
};
|
||||
|
||||
// When the user is trying to do something with an app that they are not
|
||||
@@ -269,12 +272,16 @@ var printLegacyPasswordMessage = function (site) {
|
||||
// --add' or switch accounts.
|
||||
var printUnauthorizedMessage = function () {
|
||||
var username = auth.loggedInUsername();
|
||||
Console.stderr.write(
|
||||
"Sorry, that site belongs to a different user.\n" +
|
||||
(username ? "You are currently logged in as " + username + ".\n" : "") +
|
||||
"\nEither have the site owner use 'meteor authorized --add' to add you\n" +
|
||||
"as an authorized developer for the site, or switch to an authorized\n" +
|
||||
"account with 'meteor login'.\n");
|
||||
Console.error("Sorry, that site belongs to a different user.");
|
||||
if (username) {
|
||||
Console.error("You are currently logged in as " + username + ".");
|
||||
}
|
||||
Console.error();
|
||||
Console.error(
|
||||
"Either have the site owner use " +
|
||||
Console.command("'meteor authorized --add'") + " to add you as an " +
|
||||
"authorized developer for the site, or switch to an authorized account " +
|
||||
"with " + Console.command("'meteor login'") + ".");
|
||||
};
|
||||
|
||||
// Take a proposed sitename for deploying to. If it looks
|
||||
@@ -290,10 +297,10 @@ var canonicalizeSite = function (site) {
|
||||
// characters (url.parse will do something very strange if a component is
|
||||
// larger than 63, which is the maximum legal length).
|
||||
if (site.length > 63) {
|
||||
Console.stdout.write(
|
||||
"The maximum hostname length currently supported is 63 characters.\n" +
|
||||
site + " is too long.\n" +
|
||||
"Please try again with a shorter URL for your site.\n");
|
||||
Console.error(
|
||||
"The maximum hostname length currently supported is 63 characters: " +
|
||||
site + " is too long. " +
|
||||
"Please try again with a shorter URL for your site.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -304,16 +311,16 @@ site + " is too long.\n" +
|
||||
var parsed = require('url').parse(url);
|
||||
|
||||
if (! parsed.hostname) {
|
||||
Console.stdout.write(
|
||||
"Please specify a domain to connect to, such as www.example.com or\n" +
|
||||
"http://www.example.com/\n");
|
||||
Console.info(
|
||||
"Please specify a domain to connect to, such as www.example.com or " +
|
||||
"http://www.example.com/");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parsed.pathname != '/' || parsed.hash || parsed.query) {
|
||||
Console.stdout.write(
|
||||
"Sorry, Meteor does not yet support specific path URLs, such as\n" +
|
||||
"http://www.example.com/blog . Please specify the root of a domain.\n");
|
||||
Console.info(
|
||||
"Sorry, Meteor does not yet support specific path URLs, such as " +
|
||||
Console.url("http://www.example.com/blog") + " . Please specify the root of a domain.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -364,14 +371,13 @@ var bundleAndDeploy = function (options) {
|
||||
});
|
||||
|
||||
if (preflight.errorMessage) {
|
||||
Console.stderr.write("\nError deploying application: " +
|
||||
preflight.errorMessage + "\n");
|
||||
Console.error("Error deploying application: " + preflight.errorMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (preflight.protection === "password") {
|
||||
printLegacyPasswordMessage(site);
|
||||
Console.stderr.write("If it's not your site, please try a different name!\n");
|
||||
Console.error("If it's not your site, please try a different name!");
|
||||
return 1;
|
||||
|
||||
} else if (preflight.protection === "account" &&
|
||||
@@ -383,7 +389,7 @@ var bundleAndDeploy = function (options) {
|
||||
var buildDir = options.projectContext.getProjectLocalDirectory('build_tar');
|
||||
var bundlePath = path.join(buildDir, 'bundle');
|
||||
|
||||
Console.stdout.write('Deploying to ' + site + '.\n');
|
||||
Console.info('Deploying to ' + site + '.');
|
||||
|
||||
var settings = null;
|
||||
var messages = buildmessage.capture({
|
||||
@@ -408,8 +414,8 @@ var bundleAndDeploy = function (options) {
|
||||
}
|
||||
|
||||
if (messages.hasMessages()) {
|
||||
Console.stdout.write("\nErrors prevented deploying:\n");
|
||||
Console.stdout.write(messages.formatMessages());
|
||||
Console.info("\nErrors prevented deploying:");
|
||||
Console.info(messages.formatMessages());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -435,15 +441,14 @@ var bundleAndDeploy = function (options) {
|
||||
|
||||
|
||||
if (result.errorMessage) {
|
||||
Console.stderr.write("\nError deploying application: " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("\nError deploying application: " + result.errorMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var deployedAt = require('url').parse(result.payload.url);
|
||||
var hostname = deployedAt.hostname;
|
||||
|
||||
Console.stdout.write('Now serving at http://' + hostname + '\n');
|
||||
Console.info('Now serving at http://' + hostname);
|
||||
files.rm_recursive(buildDir);
|
||||
|
||||
if (! hostname.match(/meteor\.com$/)) {
|
||||
@@ -452,11 +457,12 @@ var bundleAndDeploy = function (options) {
|
||||
if (err || cnames[0] !== 'origin.meteor.com') {
|
||||
dns.resolve(hostname, 'A', function (err, addresses) {
|
||||
if (err || addresses[0] !== '107.22.210.133') {
|
||||
Console.stdout.write('-------------\n');
|
||||
Console.stdout.write("You've deployed to a custom domain.\n");
|
||||
Console.stdout.write("Please be sure to CNAME your hostname to origin.meteor.com,\n");
|
||||
Console.stdout.write("or set an A record to 107.22.210.133.\n");
|
||||
Console.stdout.write('-------------\n');
|
||||
Console.info('-------------');
|
||||
Console.info(
|
||||
"You've deployed to a custom domain.",
|
||||
"Please be sure to CNAME your hostname",
|
||||
"to origin.meteor.com, or set an A record to 107.22.210.133.");
|
||||
Console.info('-------------');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -479,12 +485,11 @@ var deleteApp = function (site) {
|
||||
});
|
||||
|
||||
if (result.errorMessage) {
|
||||
Console.stderr.write("Couldn't delete application: " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("Couldn't delete application: " + result.errorMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.stdout.write("Deleted.\n");
|
||||
Console.info("Deleted.");
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -505,8 +510,7 @@ var checkAuthThenSendRpc = function (site, operation, what) {
|
||||
});
|
||||
|
||||
if (preflight.errorMessage) {
|
||||
Console.stderr.write("Couldn't " + what + ": " +
|
||||
preflight.errorMessage + "\n");
|
||||
Console.error("Couldn't " + what + ": " + preflight.errorMessage);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -530,15 +534,17 @@ var checkAuthThenSendRpc = function (site, operation, what) {
|
||||
} else {
|
||||
// Shouldn't ever get here because we set the retry flag on the
|
||||
// login, but just in case.
|
||||
Console.stderr.write(
|
||||
"\nYou must be logged in to " + what + " for this app. Use 'meteor login'\n" +
|
||||
"to log in.\n\n" +
|
||||
"If you don't have a Meteor developer account yet, you can quickly\n" +
|
||||
"create one at www.meteor.com.\n");
|
||||
Console.error(
|
||||
"\nYou must be logged in to " + what + " for this app. Use " +
|
||||
Console.command("'meteor login'") + "to log in.");
|
||||
Console.error();
|
||||
Console.error(
|
||||
"If you don't have a Meteor developer account yet, you can quickly " +
|
||||
"create one at www.meteor.com.");
|
||||
return null;
|
||||
}
|
||||
} else { // User is logged in but not authorized for this app
|
||||
Console.stderr.write("\n");
|
||||
Console.error();
|
||||
printUnauthorizedMessage();
|
||||
return null;
|
||||
}
|
||||
@@ -554,8 +560,7 @@ var checkAuthThenSendRpc = function (site, operation, what) {
|
||||
});
|
||||
|
||||
if (result.errorMessage) {
|
||||
Console.stderr.write("Couldn't " + what + ": " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("Couldn't " + what + ": " + result.errorMessage);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -590,7 +595,7 @@ var logs = function (site) {
|
||||
if (result === null) {
|
||||
return 1;
|
||||
} else {
|
||||
Console.stdout.write(result.message);
|
||||
Console.info(result.message);
|
||||
auth.maybePrintRegistrationLink({ leadingNewline: true });
|
||||
return 0;
|
||||
}
|
||||
@@ -607,33 +612,35 @@ var listAuthorized = function (site) {
|
||||
expectPayload: []
|
||||
});
|
||||
if (result.errorMessage) {
|
||||
Console.stderr.write("Couldn't get authorized users list: " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("Couldn't get authorized users list: " + result.errorMessage);
|
||||
return 1;
|
||||
}
|
||||
var info = result.payload;
|
||||
|
||||
if (! _.has(info, 'protection')) {
|
||||
Console.stdout.write("<anyone>\n");
|
||||
Console.info("<anyone>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.protection === "password") {
|
||||
Console.stdout.write("<password>\n");
|
||||
Console.info("<password>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.protection === "account") {
|
||||
if (! _.has(info, 'authorized')) {
|
||||
Console.stderr.write("Couldn't get authorized users list: " +
|
||||
"You are not authorized\n");
|
||||
Console.error("Couldn't get authorized users list: " +
|
||||
"You are not authorized");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.stdout.write((auth.loggedInUsername() || "<you>") + "\n");
|
||||
Console.info((auth.loggedInUsername() || "<you>"));
|
||||
_.each(info.authorized, function (username) {
|
||||
if (username)
|
||||
Console.stdout.write(username + "\n");
|
||||
// Current username rules don't let you register anything that we might
|
||||
// want to split over multiple lines (ex: containing a space), but we
|
||||
// don't want confusion if we ever change some implementation detail.
|
||||
Console.rawInfo(username + "\n");
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
@@ -655,14 +662,13 @@ var changeAuthorized = function (site, action, username) {
|
||||
});
|
||||
|
||||
if (result.errorMessage) {
|
||||
Console.stderr.write("Couldn't change authorized users: " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("Couldn't change authorized users: " + result.errorMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.stdout.write(site + ": " +
|
||||
(action === "add" ? "added " : "removed ")
|
||||
+ username + "\n");
|
||||
Console.info(site + ": " +
|
||||
(action === "add" ? "added " : "removed ")
|
||||
+ username);
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -679,27 +685,28 @@ var claim = function (site) {
|
||||
operation: 'info',
|
||||
site: site
|
||||
});
|
||||
|
||||
if (infoResult.statusCode === 404) {
|
||||
Console.stderr.write(
|
||||
"There isn't a site deployed at that address. Use 'meteor deploy' if\n" +
|
||||
"you'd like to deploy your app here.\n");
|
||||
Console.error(
|
||||
"There isn't a site deployed at that address. Use " +
|
||||
Console.command("'meteor deploy'") + " " +
|
||||
"if you'd like to deploy your app here.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (infoResult.payload && infoResult.payload.protection === "account") {
|
||||
if (infoResult.payload.authorized)
|
||||
Console.stderr.write("That site already belongs to you.\n");
|
||||
Console.error("That site already belongs to you.\n");
|
||||
else
|
||||
Console.stderr.write("Sorry, that site belongs to someone else.\n");
|
||||
Console.error("Sorry, that site belongs to someone else.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (infoResult.payload &&
|
||||
infoResult.payload.protection === "password") {
|
||||
Console.stdout.write(
|
||||
"To claim this site and transfer it to your account, enter the\n" +
|
||||
"site password one last time.\n\n");
|
||||
Console.info(
|
||||
"To claim this site and transfer it to your account, enter the",
|
||||
"site password one last time.");
|
||||
Console.info();
|
||||
}
|
||||
|
||||
var result = authedRpc({
|
||||
@@ -713,29 +720,34 @@ var claim = function (site) {
|
||||
auth.pollForRegistrationCompletion();
|
||||
if (! auth.loggedInUsername() &&
|
||||
auth.registrationUrl()) {
|
||||
Console.stderr.write(
|
||||
"You need to set a password on your Meteor developer account before\n" +
|
||||
"you can claim sites. You can do that here in under a minute:\n\n" +
|
||||
auth.registrationUrl() + "\n\n");
|
||||
Console.error(
|
||||
"You need to set a password on your Meteor developer account before",
|
||||
"you can claim sites. You can do that here in under a minute:");
|
||||
Console.error(Console.url(auth.registrationUrl()));
|
||||
Console.error();
|
||||
} else {
|
||||
Console.stderr.write("Couldn't claim site: " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("Couldn't claim site: " + result.errorMessage);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.stdout.write(
|
||||
site + ": " + "successfully transferred to your account.\n" +
|
||||
"\n" +
|
||||
"Show authorized users with:\n" +
|
||||
" meteor authorized " + site + "\n" +
|
||||
"\n" +
|
||||
"Add authorized users with:\n" +
|
||||
" meteor authorized " + site + " --add <username>\n" +
|
||||
"\n" +
|
||||
"Remove authorized users with:\n" +
|
||||
" meteor authorized " + site + " --remove <user>\n" +
|
||||
"\n");
|
||||
Console.info(site + ": " + "successfully transferred to your account.");
|
||||
Console.info();
|
||||
Console.info("Show authorized users with:");
|
||||
Console.info(
|
||||
Console.command("meteor authorized " + site),
|
||||
Console.options({ indent: 2 }));
|
||||
Console.info();
|
||||
Console.info("Add authorized users with:");
|
||||
Console.info(
|
||||
Console.command("meteor authorized " + site + " --add <username>"),
|
||||
Console.options({ indent: 2 }));
|
||||
Console.info();
|
||||
Console.info("Remove authorized users with:");
|
||||
Console.info(
|
||||
Console.command("meteor authorized " + site + " --remove <username>"),
|
||||
Console.options({ indent: 2 }));
|
||||
Console.info();
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -748,19 +760,18 @@ var listSites = function () {
|
||||
});
|
||||
|
||||
if (result.errorMessage) {
|
||||
Console.stderr.write("Couldn't list sites: " +
|
||||
result.errorMessage + "\n");
|
||||
Console.error("Couldn't list sites: " + result.errorMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! result.payload ||
|
||||
! result.payload.sites ||
|
||||
! result.payload.sites.length) {
|
||||
Console.stdout.write("You don't have any sites yet.\n");
|
||||
Console.info("You don't have any sites yet.");
|
||||
} else {
|
||||
result.payload.sites.sort();
|
||||
_.each(result.payload.sites, function (site) {
|
||||
Console.stdout.write(site + "\n");
|
||||
Console.info(site);
|
||||
});
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -14,6 +14,7 @@ var isopackets = require("./isopackets.js");
|
||||
var isopackCacheModule = require('./isopack-cache.js');
|
||||
var packageMapModule = require('./package-map.js');
|
||||
var Future = require('fibers/future');
|
||||
var Console = require('./console.js').Console;
|
||||
|
||||
var rejectBadPath = function (p) {
|
||||
if (p.match(/\.\./))
|
||||
@@ -1090,8 +1091,8 @@ _.extend(Isopack.prototype, {
|
||||
// and similar to a isopacket load failure, it can just crash the app
|
||||
// instead of being handled nicely.
|
||||
if (messages.hasMessages()) {
|
||||
process.stderr.write("Errors prevented tool build:\n");
|
||||
process.stderr.write(messages.formatMessages());
|
||||
Console.error("Errors prevented tool build:");
|
||||
Console.error(messages.formatMessages());
|
||||
throw new Error("tool build failed?");
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ var newIsopacketBuildingCatalog = function () {
|
||||
});
|
||||
});
|
||||
if (messages.hasMessages()) {
|
||||
Console.error("=> Errors while scanning core packages:");
|
||||
Console.arrowError("Errors while scanning core packages:");
|
||||
Console.printMessages(messages);
|
||||
throw new Error("isopacket scan failed?");
|
||||
}
|
||||
|
||||
180
tools/main.js
180
tools/main.js
@@ -401,13 +401,13 @@ var springboard = function (rel, options) {
|
||||
// to! That's bad. Let's exit.
|
||||
if (options.fromApp) {
|
||||
Console.error(
|
||||
"Sorry, this project uses " + rel.getDisplayName() + ", which is not\n" +
|
||||
"installed and could not be downloaded. Please check to make sure that you\n" +
|
||||
"are online.");
|
||||
"Sorry, this project uses " + rel.getDisplayName() + ", which is not",
|
||||
"installed and could not be downloaded. Please check to make sure",
|
||||
"that you are online.");
|
||||
} else {
|
||||
Console.error(
|
||||
"Sorry, " + rel.getDisplayName() + " is not installed and could not be\n" +
|
||||
"downloaded. Please check to make sure that you are online.");
|
||||
"Sorry, " + rel.getDisplayName() + " is not installed and could not",
|
||||
"be downloaded. Please check to make sure that you are online.");
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -712,8 +712,8 @@ Fiber(function () {
|
||||
if (_.has(rawOptions, '--release')) {
|
||||
if (rawOptions['--release'].length > 1) {
|
||||
Console.error(
|
||||
"--release should only be passed once.\n" +
|
||||
"Try 'meteor help' for help.");
|
||||
"--release should only be passed once. " +
|
||||
"Try 'meteor help' for help.");
|
||||
process.exit(1);
|
||||
}
|
||||
releaseOverride = rawOptions['--release'][0];
|
||||
@@ -721,8 +721,8 @@ Fiber(function () {
|
||||
releaseExplicit = true;
|
||||
if (! releaseOverride) {
|
||||
Console.error(
|
||||
"The --release option needs a value.\n" +
|
||||
"Try 'meteor help' for help.");
|
||||
"The --release option needs a value. " +
|
||||
"Try 'meteor help' for help.");
|
||||
process.exit(1);
|
||||
}
|
||||
delete rawOptions['--release'];
|
||||
@@ -748,19 +748,21 @@ Fiber(function () {
|
||||
// shouldn't happen unless the user did it manually.
|
||||
if (appReleaseFile.noReleaseSpecified()) {
|
||||
Console.error(
|
||||
"Problem! This project has a .meteor/release file which is empty.\n" +
|
||||
"The file should either contain the release of Meteor that you want to use,\n" +
|
||||
"or the word 'none' if you will only use the project with unreleased\n" +
|
||||
"checkouts of Meteor. Please edit the .meteor/release file in the project\n" +
|
||||
"and change it to a valid Meteor release or 'none'.");
|
||||
"Problem! This project has a .meteor/release file which is empty.",
|
||||
"The file should either contain the release of Meteor that you want",
|
||||
"to use, or the word 'none' if you will only use the project with",
|
||||
"unreleased checkouts of Meteor. Please edit the .meteor/release",
|
||||
"file in the project and change it to a valid Meteor release or",
|
||||
"'none'.");
|
||||
process.exit(1);
|
||||
} else if (appReleaseFile.fileMissing()) {
|
||||
Console.error(
|
||||
"Problem! This project does not have a .meteor/release file.\n" +
|
||||
"The file should either contain the release of Meteor that you want to use,\n" +
|
||||
"or the word 'none' if you will only use the project with unreleased\n" +
|
||||
"checkouts of Meteor. Please edit the .meteor/release file in the project\n" +
|
||||
"and change it to a valid Meteor release or 'none'.");
|
||||
"Problem! This project does not have a .meteor/release file.",
|
||||
"The file should either contain the release of Meteor that you",
|
||||
"want to use, or the word 'none' if you will only use the project",
|
||||
"with unreleased checkouts of Meteor. Please edit the",
|
||||
".meteor/release file in the project and change it to a valid Meteor",
|
||||
"release or 'none'.");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -805,11 +807,12 @@ Fiber(function () {
|
||||
if (!releaseName) {
|
||||
if (catalog.refreshFailed) {
|
||||
Console.error(
|
||||
"The package catalog has no information about any Meteor releases, and we\n" +
|
||||
"had trouble connecting to the package server.");
|
||||
"The package catalog has no information about any Meteor",
|
||||
"releases, and we had trouble connecting to the package server.");
|
||||
} else {
|
||||
Console.error(
|
||||
"The package catalog has no information about any Meteor releases.");
|
||||
"The package catalog has no information about",
|
||||
"any Meteor releases.");
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -883,7 +886,8 @@ Fiber(function () {
|
||||
} else if (e instanceof files.OfflineError) {
|
||||
if (!catalog.refreshFailed) {
|
||||
// Warn if we didn't already warn.
|
||||
Console.warn("Unable to contact release server (are you offline?)");
|
||||
Console.warn(
|
||||
"Unable to contact release server (are you offline?)");
|
||||
}
|
||||
// Treat this like a failure to refresh the catalog
|
||||
// (map the old world to the new world)
|
||||
@@ -918,17 +922,18 @@ Fiber(function () {
|
||||
}
|
||||
if (catalog.refreshFailed) {
|
||||
Console.error(
|
||||
"This project says that it uses " + displayRelease + ", but\n" +
|
||||
"you don't have that version of Meteor installed, and we were unable to\n" +
|
||||
"contact Meteor's update servers to find out about it. Please edit the\n" +
|
||||
".meteor/release file in the project and change it to a valid Meteor\n" +
|
||||
"release, or go online.");
|
||||
"This project says that it uses " + displayRelease + ", but",
|
||||
"you don't have that version of Meteor installed, and we were",
|
||||
"unable to contact Meteor's update servers to find out about it.",
|
||||
"Please edit the .meteor/release file in the project and change",
|
||||
"it to a valid Meteor release, or go online.");
|
||||
} else {
|
||||
Console.error(
|
||||
"This project says that it uses " + displayRelease + ", but you don't have\n" +
|
||||
"that version of Meteor installed and the Meteor update servers\n" +
|
||||
"don't have it either. Please edit the .meteor/release file in\n" +
|
||||
"the project and change it to a valid Meteor release.");
|
||||
"This project says that it uses " + displayRelease + ", but you",
|
||||
"don't have that version of Meteor installed and the Meteor",
|
||||
"update servers don't have it either. Please edit the",
|
||||
".meteor/release file in the project and change it to a valid",
|
||||
"Meteor release.");
|
||||
}
|
||||
} else {
|
||||
throw new Error("can't load latest release?");
|
||||
@@ -971,12 +976,12 @@ Fiber(function () {
|
||||
if (rawOptions[fullName]) {
|
||||
if (rawOptions[fullName].length > 1) {
|
||||
Console.error("It doesn't make sense to pass " +
|
||||
fullName + " more than once.");
|
||||
fullName + " more than once.");
|
||||
process.exit(1);
|
||||
}
|
||||
if (_.size(rawOptions) > 1 || rawArgs.length !== 0 || command) {
|
||||
Console.error("Can't pass anything else along with " +
|
||||
value.name + ".");
|
||||
value.name + ".");
|
||||
process.exit(1);
|
||||
}
|
||||
command = value;
|
||||
@@ -1017,7 +1022,9 @@ Fiber(function () {
|
||||
|
||||
if (! _.has(walk, word)) {
|
||||
Console.error(
|
||||
"'" + commandName + "' is not a Meteor command. See 'meteor --help'.");
|
||||
Console.command("'" + commandName + "'") +
|
||||
" is not a Meteor command. See " +
|
||||
Console.command("'meteor --help'")+ ".");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -1036,7 +1043,8 @@ Fiber(function () {
|
||||
// They typed something like 'meteor admin' (when they were
|
||||
// supposed to type 'meteor admin grant' or something).
|
||||
Console.error(
|
||||
"Try 'meteor " + commandName + " help' for available commands.");
|
||||
"Try " + Console.command("'meteor " + commandName + " help'") + " " +
|
||||
"for available commands.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -1048,7 +1056,9 @@ Fiber(function () {
|
||||
// which case showHelp will be true and command will be null
|
||||
|
||||
if (showHelp) {
|
||||
Console.stdout.write(longHelp(commandName) + "\n");
|
||||
// XXX: Until we rewrite the longHelp function to cope with the new output
|
||||
// format, let's go with the static, painstakingly-formatted version.
|
||||
Console.rawInfo(longHelp(commandName) + "\n");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -1061,13 +1071,16 @@ Fiber(function () {
|
||||
var presentLong = _.has(rawOptions, "--" + optionName);
|
||||
var presentShort = _.has(optionInfo, 'short') &&
|
||||
_.has(rawOptions, "-" + optionInfo.short);
|
||||
var tryHelpMessage =
|
||||
"Try " + Console.command("'meteor help " + commandName + "'") + " " +
|
||||
"for help.";
|
||||
|
||||
|
||||
if (presentShort && presentLong) {
|
||||
// this would get caught below, but give a clearer error message
|
||||
Console.error(
|
||||
commandName + ": can't pass both -" + optionInfo.short + " and --" +
|
||||
optionName + ".\n" +
|
||||
"Try 'meteor help " + commandName + "' for help.");
|
||||
commandName + ": can't pass both -" + optionInfo.short + " and --" +
|
||||
optionName + ". " + tryHelpMessage);
|
||||
process.exit(1);
|
||||
}
|
||||
var helpfulOptionName = "--" + optionName +
|
||||
@@ -1086,8 +1099,10 @@ commandName + ": can't pass both -" + optionInfo.short + " and --" +
|
||||
// in the future, we could support multiple values, but we don't
|
||||
// for now since no command needs it
|
||||
Console.error(
|
||||
commandName + ": can only take one " + helpfulOptionName + " option.\n" +
|
||||
"Try 'meteor help " + commandName + "' for help.");
|
||||
Console.command(commandName) + ": can only take one " +
|
||||
Console.command(helpfulOptionName) + " option.");
|
||||
Console.error(tryHelpMessage);
|
||||
|
||||
process.exit(1);
|
||||
} else if (values.length === 1) {
|
||||
// OK, they provided exactly one value. Check its type and add
|
||||
@@ -1097,22 +1112,27 @@ commandName + ": can only take one " + helpfulOptionName + " option.\n" +
|
||||
// This option requires a value and they didn't give it one
|
||||
// (it was the last word on the command line).
|
||||
Console.error(
|
||||
commandName + ": the " + helpfulOptionName + " option needs a value.\n" +
|
||||
"Try 'meteor help " + commandName + "' for help.");
|
||||
Console.command(commandName) + ": the " +
|
||||
Console.command(helpfulOptionName) + " option needs a value.");
|
||||
Console.error(tryHelpMessage);
|
||||
|
||||
process.exit(1);
|
||||
} else if (optionInfo.type === Number) {
|
||||
if (! value.match(/^[0-9]+$/)) {
|
||||
Console.error(
|
||||
commandName + ": " + helpfulOptionName + " must be a number.\n" +
|
||||
"Try 'meteor help " + commandName + "' for help.");
|
||||
Console.command(commandName) + ": " +
|
||||
Console.command(helpfulOptionName) + " must be a number.");
|
||||
Console.error(tryHelpMessage);
|
||||
process.exit(1);
|
||||
}
|
||||
value = parseInt(value);
|
||||
} else if (optionInfo.type === Boolean) {
|
||||
if (!value) {
|
||||
Console.error(
|
||||
commandName + ": the " + helpfulOptionName + " option does not need a value.\n" +
|
||||
"Try 'meteor help " + commandName + "' for help.");
|
||||
Console.command(commandName) + ": the " +
|
||||
Console.command(helpfulOptionName) + " " +
|
||||
"option does not need a value.");
|
||||
Console.error(tryHelpMessage);
|
||||
process.exit(1);
|
||||
}
|
||||
value = true;
|
||||
@@ -1137,8 +1157,9 @@ commandName + ": the " + helpfulOptionName + " option does not need a value.\n"
|
||||
options[optionName] = optionInfo.default;
|
||||
} else if (optionInfo.required) {
|
||||
Console.error(
|
||||
commandName + ": the --" + optionName + " option is required.\n" +
|
||||
longHelp(commandName));
|
||||
Console.command(commandName) + ": the --" +
|
||||
Console.command(optionName) + " option is required.");
|
||||
Console.rawError(longHelp(commandName));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1147,23 +1168,26 @@ longHelp(commandName));
|
||||
// Check for unrecognized options.
|
||||
if (_.keys(rawOptions).length > 0) {
|
||||
Console.error(
|
||||
_.keys(rawOptions)[0] + ": unknown option.\n" +
|
||||
longHelp(commandName));
|
||||
Console.command(_.keys(rawOptions)[0]) + ": unknown option.");
|
||||
Console.rawError(
|
||||
longHelp(commandName));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check argument count.
|
||||
if (options.args.length < command.minArgs) {
|
||||
Console.error(
|
||||
commandName + ": not enough arguments.\n" +
|
||||
longHelp(commandName));
|
||||
Console.command(commandName) + ": not enough arguments.");
|
||||
Console.rawError(
|
||||
longHelp(commandName));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (options.args.length > command.maxArgs) {
|
||||
Console.error(
|
||||
commandName + ": too many arguments.\n" +
|
||||
longHelp(commandName));
|
||||
Console.command(commandName) + ": too many arguments.");
|
||||
Console.rawError(
|
||||
longHelp(commandName));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -1183,14 +1207,20 @@ longHelp(commandName));
|
||||
// since you'll default to the 'run' command which requires an
|
||||
// app. Be welcoming to our new developers!
|
||||
Console.error(
|
||||
commandName + ": You're not in a Meteor project directory.\n" +
|
||||
"\n" +
|
||||
"To create a new Meteor project:\n" +
|
||||
" meteor create <project name>\n" +
|
||||
"For example:\n" +
|
||||
" meteor create myapp\n" +
|
||||
"\n" +
|
||||
"For more help, see 'meteor --help'.");
|
||||
Console.command(commandName) +
|
||||
": You're not in a Meteor project directory.");
|
||||
Console.error();
|
||||
Console.error("To create a new Meteor project:");
|
||||
Console.error(
|
||||
Console.command("meteor create <project name>"),
|
||||
Console.options({ indent: 2 }));
|
||||
Console.error("For example:");
|
||||
Console.error(
|
||||
Console.command("meteor create myapp"),
|
||||
Console.options({ indent: 2 }));
|
||||
Console.error();
|
||||
Console.error(
|
||||
"For more help, see " + Console.command("'meteor --help'") + ".");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -1211,18 +1241,20 @@ commandName + ": You're not in a Meteor project directory.\n" +
|
||||
|
||||
if (! options.packageDir) {
|
||||
Console.error(
|
||||
commandName + ": You're not in a Meteor package directory.");
|
||||
Console.command(commandName) +
|
||||
": You're not in a Meteor package directory.");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (command.requiresRelease && ! release.current) {
|
||||
Console.error(
|
||||
"You must specify a Meteor version with --release when you work with this\n" +
|
||||
"project. It was created from an unreleased Meteor checkout and doesn't\n" +
|
||||
"have a version associated with it.\n" +
|
||||
"\n" +
|
||||
"You can permanently set a release for this project with 'meteor update'.");
|
||||
"You must specify a Meteor version with --release when you work with",
|
||||
"this project. It was created from an unreleased Meteor checkout and",
|
||||
"doesn't have a version associated with it.");
|
||||
Console.error(
|
||||
"You can permanently set a release for this project with " +
|
||||
Console.command("'meteor update'") + ".");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -1230,9 +1262,9 @@ commandName + ": You're not in a Meteor project directory.\n" +
|
||||
appReleaseFile && ! appReleaseFile.isCheckout()) {
|
||||
// For commands that work with apps, if we have overridden the
|
||||
// app's usual release by using a checkout, print a reminder banner.
|
||||
Console.warn(
|
||||
"=> Running Meteor from a checkout -- overrides project version (" +
|
||||
appReleaseFile.displayReleaseName + ")");
|
||||
Console.arrowWarn(
|
||||
"Running Meteor from a checkout -- overrides project version " +
|
||||
Console.noWrap("(" + appReleaseFile.displayReleaseName + ")"));
|
||||
}
|
||||
|
||||
// Now that we're ready to start executing the command, if we are in
|
||||
@@ -1264,7 +1296,7 @@ commandName + ": You're not in a Meteor project directory.\n" +
|
||||
throw new Error(
|
||||
"you meant 'throw new main.Foo', not 'throw main.Foo'");
|
||||
} else if (e instanceof main.ShowUsage) {
|
||||
Console.error(longHelp(commandName));
|
||||
Console.rawError(longHelp(commandName) + "\n");
|
||||
process.exit(1);
|
||||
} else if (e instanceof main.SpringboardToLatestRelease) {
|
||||
// Load the metadata for the latest release (or at least, the latest
|
||||
|
||||
@@ -69,7 +69,7 @@ _.extend(RunCommand.prototype, {
|
||||
self.process.stdout.on('data', function (data) {
|
||||
self.stdout = self.stdout + data;
|
||||
if (self.options.pipeOutput) {
|
||||
Console.stdout.write(data);
|
||||
Console.rawInfo(data);
|
||||
}
|
||||
if (self.options.onStdout) {
|
||||
self.options.onStdout(data);
|
||||
@@ -79,7 +79,7 @@ _.extend(RunCommand.prototype, {
|
||||
self.process.stderr.on('data', function (data) {
|
||||
self.stderr = self.stderr + data;
|
||||
if (self.options.pipeOutput) {
|
||||
Console.stderr.write(data);
|
||||
Console.rawError(data);
|
||||
}
|
||||
if (self.options.onStderr) {
|
||||
self.options.onStderr(data);
|
||||
@@ -121,4 +121,3 @@ _.extend(RunCommand.prototype, {
|
||||
});
|
||||
|
||||
exports.RunCommand = RunCommand;
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ _.extend(Runner.prototype, {
|
||||
// print the banner only once we've successfully bound the port
|
||||
if (! self.quiet && ! self.stopped) {
|
||||
runLog.log("[[[[[ " + self.banner + " ]]]]]\n");
|
||||
runLog.log("=> Started proxy.");
|
||||
runLog.log("Started proxy.", { arrow: true });
|
||||
}
|
||||
|
||||
self._startMongoAsync();
|
||||
@@ -142,7 +142,7 @@ _.extend(Runner.prototype, {
|
||||
if (! self.stopped && self.httpProxy) {
|
||||
self.httpProxy.start();
|
||||
if (! self.quiet) {
|
||||
runLog.log("=> Started http proxy.");
|
||||
runLog.log("Started http proxy.", { arrow: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ _.extend(Runner.prototype, {
|
||||
extraRunner.start();
|
||||
});
|
||||
if (! self.quiet && ! self.stopped)
|
||||
runLog.log("=> Started " + title + ".");
|
||||
runLog.log("Started " + title + ".", { arrow: true });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -162,18 +162,20 @@ _.extend(Runner.prototype, {
|
||||
self.appRunner.start();
|
||||
});
|
||||
if (! self.quiet && ! self.stopped)
|
||||
runLog.log("=> Started your app.");
|
||||
runLog.log("Started your app.", { arrow: true });
|
||||
}
|
||||
|
||||
if (! self.stopped && ! self.quiet)
|
||||
runLog.log("\n=> App running at: " + self.rootUrl);
|
||||
if (! self.stopped && ! self.quiet) {
|
||||
runLog.log("");
|
||||
runLog.log("App running at: " + self.rootUrl, { arrow: true });
|
||||
}
|
||||
|
||||
if (self.selenium && ! self.stopped) {
|
||||
buildmessage.enterJob({ title: "Starting Selenium" }, function () {
|
||||
self.selenium.start();
|
||||
});
|
||||
if (! self.quiet && ! self.stopped)
|
||||
runLog.log("=> Started Selenium.");
|
||||
runLog.log("Started Selenium.", { arrow: true });
|
||||
}
|
||||
|
||||
// XXX It'd be nice to (cosmetically) handle failure better. Right
|
||||
@@ -191,7 +193,7 @@ _.extend(Runner.prototype, {
|
||||
_startMongoFuture: function () {
|
||||
this.mongoRunner.start();
|
||||
if (! this.stopped && ! this.quiet) {
|
||||
runLog.log("=> Started MongoDB.");
|
||||
runLog.log("Started MongoDB.", { arrow: true });
|
||||
}
|
||||
}.future(),
|
||||
|
||||
@@ -321,25 +323,24 @@ exports.run = function (options) {
|
||||
runner.stop();
|
||||
|
||||
if (result.outcome === "conflicting-versions") {
|
||||
process.stderr.write(
|
||||
"The constraint solver could not find a set of package versions to use that would\n" +
|
||||
"satisfy the constraints of .meteor/versions and .meteor/packages. This could be\n" +
|
||||
"caused by conflicts in .meteor/versions, conflicts in .meteor/packages, and/or\n" +
|
||||
"inconsistent changes to the dependencies in local packages.");
|
||||
Console.error(
|
||||
"The constraint solver could not find a set of package versions to",
|
||||
"use that would satisfy the constraints of .meteor/versions and",
|
||||
".meteor/packages. This could be caused by conflicts in",
|
||||
".meteor/versions, conflicts in .meteor/packages, and/or",
|
||||
"inconsistent changes to the dependencies in local packages.");
|
||||
return 254;
|
||||
}
|
||||
|
||||
if (result.outcome === "outdated-cordova-plugins") {
|
||||
process.stderr.write(
|
||||
"Your app's Cordova plugins have changed.\n" +
|
||||
"Restart meteor to use the new set of plugins.\n");
|
||||
Console.error("Your app's Cordova plugins have changed.");
|
||||
Console.error("Restart meteor to use the new set of plugins.");
|
||||
return 254;
|
||||
}
|
||||
|
||||
if (result.outcome === "outdated-cordova-platforms") {
|
||||
process.stderr.write(
|
||||
"Your app's platforms have changed.\n" +
|
||||
"Restart meteor to use the new set of platforms.\n");
|
||||
Console.error("Your app's platforms have changed.");
|
||||
Console.error("Restart meteor to use the new set of platforms.");
|
||||
return 254;
|
||||
}
|
||||
|
||||
@@ -357,10 +358,9 @@ exports.run = function (options) {
|
||||
// this (which prevents weird errors) is a start.)
|
||||
var from = release.current.getDisplayName();
|
||||
var to = result.displayReleaseNeeded;
|
||||
process.stderr.write(
|
||||
"Your app has been updated to " + to + " from " + from +
|
||||
".\n" +
|
||||
"Restart meteor to use the new release.\n");
|
||||
Console.error(
|
||||
"Your app has been updated to " + to + " from " + from + ".",
|
||||
"Restart meteor to use the new release.");
|
||||
return 254;
|
||||
}
|
||||
|
||||
@@ -373,14 +373,14 @@ exports.run = function (options) {
|
||||
}
|
||||
|
||||
if (once && result.outcome === "bundle-fail") {
|
||||
process.stderr.write("=> Build failed:\n\n" +
|
||||
result.errors.formatMessages() + "\n");
|
||||
Console.arrowError("Build failed:\n\n" +
|
||||
result.errors.formatMessages());
|
||||
return 254;
|
||||
}
|
||||
|
||||
if (once && result.outcome === "terminated") {
|
||||
if (result.signal) {
|
||||
process.stderr.write("Killed (" + result.signal + ")\n");
|
||||
Console.error("Killed (" + result.signal + ")");
|
||||
return 255;
|
||||
} else if (typeof result.code === "number") {
|
||||
// We used to print 'Your application is exiting' here, but that
|
||||
|
||||
@@ -112,7 +112,7 @@ _.extend(AppProcess.prototype, {
|
||||
}));
|
||||
|
||||
self.proc.on('error', fiberHelpers.inBareFiber(function (err) {
|
||||
runLog.log("=> Couldn't spawn process: " + err.message);
|
||||
runLog.log("Couldn't spawn process: " + err.message, { arrow: true });
|
||||
|
||||
// node docs say that it might make both an 'error' and a
|
||||
// 'close' callback, so we use a guard to make sure we only call
|
||||
@@ -770,11 +770,11 @@ _.extend(AppRunner.prototype, {
|
||||
}
|
||||
|
||||
else if (runResult.outcome === "bundle-fail") {
|
||||
runLog.log("=> Errors prevented startup:\n\n" +
|
||||
runResult.errors.formatMessages());
|
||||
runLog.log("Errors prevented startup:\n\n" +
|
||||
runResult.errors.formatMessages(), { arrow: true });
|
||||
if (self.watchForChanges) {
|
||||
runLog.log("=> Your application has errors. " +
|
||||
"Waiting for file change.");
|
||||
runLog.log("Your application has errors. " +
|
||||
"Waiting for file change.", { arrow: true });
|
||||
Console.enableProgressDisplay(false);
|
||||
}
|
||||
}
|
||||
@@ -784,9 +784,9 @@ _.extend(AppRunner.prototype, {
|
||||
|
||||
else if (runResult.outcome === "terminated") {
|
||||
if (runResult.signal) {
|
||||
runLog.log('=> Exited from signal: ' + runResult.signal);
|
||||
runLog.log('Exited from signal: ' + runResult.signal, { arrow: true });
|
||||
} else if (runResult.code !== undefined) {
|
||||
runLog.log('=> Exited with code: ' + runResult.code);
|
||||
runLog.log('Exited with code: ' + runResult.code, { arrow: true });
|
||||
} else {
|
||||
// explanation should already have been logged
|
||||
}
|
||||
@@ -796,8 +796,9 @@ _.extend(AppRunner.prototype, {
|
||||
continue;
|
||||
|
||||
if (self.watchForChanges) {
|
||||
runLog.log("=> Your application is crashing. " +
|
||||
"Waiting for file change.");
|
||||
runLog.log("Your application is crashing. " +
|
||||
"Waiting for file change.",
|
||||
{ arrow: true });
|
||||
Console.enableProgressDisplay(false);
|
||||
}
|
||||
}
|
||||
@@ -824,7 +825,7 @@ _.extend(AppRunner.prototype, {
|
||||
// While we were waiting, did somebody stop() us?
|
||||
if (self.exitFuture)
|
||||
break;
|
||||
runLog.log("=> Modified -- restarting.");
|
||||
runLog.log("Modified -- restarting.", { arrow: true });
|
||||
Console.enableProgressDisplay(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -62,12 +62,12 @@ _.extend(RunLog.prototype, {
|
||||
|
||||
if (self.consecutiveRestartMessages) {
|
||||
self.consecutiveRestartMessages = null;
|
||||
Console.stdout.write("\n");
|
||||
Console.info();
|
||||
}
|
||||
|
||||
if (self.consecutiveClientRestartMessages) {
|
||||
self.consecutiveClientRestartMessages = null;
|
||||
Console.stdout.write("\n");
|
||||
Console.info();
|
||||
}
|
||||
|
||||
if (self.temporaryMessageLength) {
|
||||
@@ -93,16 +93,20 @@ _.extend(RunLog.prototype, {
|
||||
|
||||
self._clearSpecial();
|
||||
if (self.rawLogs)
|
||||
Console[isStderr ? "stderr" : "stdout"].write(line + "\n");
|
||||
Console[isStderr ? "rawError" : "rawInfo"](line + "\n");
|
||||
else
|
||||
Console.stdout.write(Log.format(obj, { color: true }) + "\n");
|
||||
Console.rawInfo(Log.format(obj, { color: true }) + "\n");
|
||||
|
||||
// XXX deal with test server logging differently?!
|
||||
},
|
||||
|
||||
log: function (msg) {
|
||||
// Log the message.
|
||||
// msg: message
|
||||
// options:
|
||||
// - arrow: if true, preface with => and wrap accordingly.
|
||||
log: function (msg, options) {
|
||||
var self = this;
|
||||
|
||||
options = options || {};
|
||||
var obj = {
|
||||
time: new Date,
|
||||
message: msg
|
||||
@@ -113,7 +117,11 @@ _.extend(RunLog.prototype, {
|
||||
self._record(obj);
|
||||
|
||||
self._clearSpecial();
|
||||
Console.stdout.write(msg + "\n");
|
||||
|
||||
// Process the options. By default, we want to wordwrap the message with
|
||||
// Console.info. If we ask for raw output, then we don't want to do that. If
|
||||
// we ask for an arrow, we want to wrap around with => as the bulletPoint.
|
||||
Console[options.arrow ? 'arrowInfo' : 'info'](msg);
|
||||
},
|
||||
|
||||
// Write a message to the terminal that will get overwritten by the
|
||||
|
||||
@@ -30,8 +30,8 @@ var runVelocity = function (url) {
|
||||
|
||||
ddpConnection.subscribe("VelocityTestReports", {
|
||||
onError: function () {
|
||||
Console.stderr.write("failed to subscribe to VelocityTestReports "
|
||||
+ "subscription");
|
||||
Console.error("failed to subscribe to VelocityTestReports " +
|
||||
"subscription");
|
||||
// XXX tell user to add velocity:core
|
||||
// XXX these also fire if the user turns on autopublish
|
||||
}, onReady: function () {
|
||||
@@ -65,8 +65,8 @@ var runVelocity = function (url) {
|
||||
var isFinished = false;
|
||||
ddpConnection.subscribe("VelocityAggregateReports", {
|
||||
onError: function () {
|
||||
Console.stderr.write("failed to subscribe to " +
|
||||
"VelocityAggregateReports subscription");
|
||||
Console.error("failed to subscribe to " +
|
||||
"VelocityAggregateReports subscription");
|
||||
}, onReady: function () {
|
||||
this.connection.registerStore("velocityAggregateReports", {
|
||||
update: function (msg) {
|
||||
@@ -113,8 +113,8 @@ var runVelocity = function (url) {
|
||||
|
||||
ddpConnection.subscribe("VelocityMirrors", {
|
||||
onError: function (err) {
|
||||
Console.stderr.write("failed to subscribe to VelocityMirrors " +
|
||||
"subscription", err);
|
||||
Console.error("failed to subscribe to VelocityMirrors " +
|
||||
"subscription", err);
|
||||
}, onReady: function () {
|
||||
this.connection.registerStore("velocityMirrors", {
|
||||
update: function (msg) {
|
||||
|
||||
@@ -171,7 +171,7 @@ var newSelfTestCatalog = function () {
|
||||
});
|
||||
});
|
||||
if (messages.hasMessages()) {
|
||||
Console.error("=> Errors while scanning core packages:");
|
||||
Console.arrowError("Errors while scanning core packages:");
|
||||
Console.printMessages(messages);
|
||||
throw new Error("scan failed?");
|
||||
}
|
||||
@@ -240,7 +240,7 @@ _.extend(Matcher.prototype, {
|
||||
var self = this;
|
||||
|
||||
if (self.buf.length > 0) {
|
||||
console.log("Extra junk is ", self.buf);
|
||||
Console.info("Extra junk is :", self.buf);
|
||||
throw new TestFailure('junk-at-end', { run: self.run });
|
||||
}
|
||||
},
|
||||
@@ -1639,22 +1639,22 @@ var listTests = function (options) {
|
||||
var testList = getFilteredTests(options);
|
||||
|
||||
if (! testList.allTests.length) {
|
||||
Console.stderr.write("No tests defined.\n");
|
||||
Console.error("No tests defined.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
_.each(_.groupBy(testList.filteredTests, 'file'), function (tests, file) {
|
||||
Console.stdout.write(file + ':\n');
|
||||
Console.rawInfo(file + ':\n');
|
||||
_.each(tests, function (test) {
|
||||
Console.stdout.write(' - ' + test.name +
|
||||
(test.tags.length ? ' [' + test.tags.join(' ') + ']'
|
||||
: ''));
|
||||
Console.rawInfo(' - ' + test.name +
|
||||
(test.tags.length ? ' [' + test.tags.join(' ') + ']'
|
||||
: ''));
|
||||
});
|
||||
});
|
||||
|
||||
Console.stderr.write('\n');
|
||||
Console.stderr.write(testList.filteredTests.length + " tests listed.");
|
||||
Console.stderr.write(testList.generateSkipReport());
|
||||
Console.error();
|
||||
Console.error(testList.filteredTests.length + " tests listed.");
|
||||
Console.error(testList.generateSkipReport());
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1669,7 +1669,7 @@ var runTests = function (options) {
|
||||
var testList = getFilteredTests(options);
|
||||
|
||||
if (! testList.allTests.length) {
|
||||
Console.stderr.write("No tests defined.\n");
|
||||
Console.error("No tests defined.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1689,7 +1689,7 @@ var runTests = function (options) {
|
||||
if (e instanceof TestFailure) {
|
||||
failure = e;
|
||||
} else {
|
||||
Console.stderr.write("exception\n\n");
|
||||
Console.error("exception\n");
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
@@ -1698,84 +1698,85 @@ var runTests = function (options) {
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
Console.stderr.write("fail!\n");
|
||||
Console.error("fail!");
|
||||
failedTests.push(test);
|
||||
testList.notifyFailed(test);
|
||||
|
||||
var frames = parseStack.parse(failure);
|
||||
var relpath = path.relative(files.getCurrentToolsDir(),
|
||||
frames[0].file);
|
||||
Console.stderr.write(" => " + failure.reason + " at " +
|
||||
relpath + ":" + frames[0].line + "\n");
|
||||
Console.rawError(" => " + failure.reason + " at " +
|
||||
relpath + ":" + frames[0].line + "\n");
|
||||
if (failure.reason === 'no-match') {
|
||||
Console.stderr.write(" => Pattern: " + failure.details.pattern + "\n");
|
||||
Console.arrowError("Pattern: " + failure.details.pattern, 2);
|
||||
}
|
||||
if (failure.reason === "wrong-exit-code") {
|
||||
var s = function (status) {
|
||||
return status.signal || ('' + status.code) || "???";
|
||||
};
|
||||
|
||||
Console.stderr.write(" => Expected: " + s(failure.details.expected) +
|
||||
"; actual: " + s(failure.details.actual) + "\n");
|
||||
Console.rawError(" => " + "Expected: " + s(failure.details.expected) +
|
||||
"; actual: " + s(failure.details.actual) + "\n");
|
||||
}
|
||||
if (failure.reason === 'expected-exception') {
|
||||
}
|
||||
if (failure.reason === 'not-equal') {
|
||||
Console.stderr.write(
|
||||
" => Expected: " + JSON.stringify(failure.details.expected) +
|
||||
"; actual: " + JSON.stringify(failure.details.actual) + "\n");
|
||||
Console.rawError(
|
||||
" => " + "Expected: " + JSON.stringify(failure.details.expected) +
|
||||
"; actual: " + JSON.stringify(failure.details.actual) + "\n");
|
||||
}
|
||||
|
||||
if (failure.details.run) {
|
||||
failure.details.run.outputLog.end();
|
||||
var lines = failure.details.run.outputLog.get();
|
||||
if (! lines.length) {
|
||||
Console.stderr.write(" => No output\n");
|
||||
Console.arrowError("No output", 2);
|
||||
} else {
|
||||
var historyLines = options.historyLines || 100;
|
||||
|
||||
Console.stderr.write(" => Last " + historyLines + " lines:\n");
|
||||
Console.arrowError("Last " + historyLines + " lines:", 2
|
||||
);
|
||||
_.each(lines.slice(-historyLines), function (line) {
|
||||
Console.stderr.write(" " +
|
||||
(line.channel === "stderr" ? "2| " : "1| ") +
|
||||
line.text +
|
||||
(line.bare ? "%" : "") + "\n");
|
||||
Console.rawError(" " +
|
||||
(line.channel === "stderr" ? "2| " : "1| ") +
|
||||
line.text +
|
||||
(line.bare ? "%" : "") + "\n");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (failure.details.messages) {
|
||||
Console.stderr.write(" => Errors while building:\n");
|
||||
Console.stderr.write(failure.details.messages.formatMessages());
|
||||
Console.arrowError("Errors while building:", 2);
|
||||
Console.rawError(failure.details.messages.formatMessages() + "\n");
|
||||
}
|
||||
} else {
|
||||
var durationMs = +(new Date) - startTime;
|
||||
Console.stderr.write("ok (" + durationMs + " ms)\n");
|
||||
Console.error("ok (" + durationMs + " ms)");
|
||||
}
|
||||
});
|
||||
|
||||
testList.saveTestState();
|
||||
|
||||
if (totalRun > 0)
|
||||
Console.stderr.write("\n");
|
||||
Console.error();
|
||||
|
||||
Console.stderr.write(testList.generateSkipReport());
|
||||
Console.error(testList.generateSkipReport());
|
||||
|
||||
if (testList.filteredTests.length === 0) {
|
||||
Console.stderr.write("No tests run.\n");
|
||||
Console.error("No tests run.");
|
||||
return 0;
|
||||
} else if (failedTests.length === 0) {
|
||||
var disclaimers = '';
|
||||
if (testList.filteredTests.length < testList.allTests.length)
|
||||
disclaimers += " other";
|
||||
Console.stderr.write("All" + disclaimers + " tests passed.\n");
|
||||
Console.error("All" + disclaimers + " tests passed.");
|
||||
return 0;
|
||||
} else {
|
||||
var failureCount = failedTests.length;
|
||||
Console.stderr.write(failureCount + " failure" +
|
||||
(failureCount > 1 ? "s" : "") + ":\n");
|
||||
Console.error(failureCount + " failure" +
|
||||
(failureCount > 1 ? "s" : "") + ":");
|
||||
_.each(failedTests, function (test) {
|
||||
Console.stderr.write(" - " + test.file + ": " + test.name);
|
||||
Console.rawError(" - " + test.file + ": " + test.name + "\n");
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -118,11 +118,14 @@ var recordPackages = function (options) {
|
||||
|
||||
var logErrorIfInCheckout = function (err) {
|
||||
if (files.inCheckout() || process.env.METEOR_PACKAGE_STATS_TEST_OUTPUT) {
|
||||
Console.stderr.write("Failed to record package usage.\n");
|
||||
Console.stderr.write(
|
||||
"(This error is hidden when you are not running Meteor from a checkout.)\n");
|
||||
Console.stderr.write(err.stack || err);
|
||||
Console.stderr.write("\n\n");
|
||||
Console.warn("Failed to record package usage.");
|
||||
Console.warn(
|
||||
"(This error is hidden when you are not running Meteor from a",
|
||||
"checkout.)");
|
||||
var printErr = err.stack || err;
|
||||
Console.rawWarn(printErr + "\n");
|
||||
Console.warn();
|
||||
Console.warn();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
2
tools/tests/cordova-platforms.js
vendored
2
tools/tests/cordova-platforms.js
vendored
@@ -35,7 +35,7 @@ selftest.define("add cordova platforms", function () {
|
||||
run.match("added");
|
||||
|
||||
run = s.run("remove-platform", "foo");
|
||||
run.match("foo: platform is not");
|
||||
run.matchErr("foo: platform is not");
|
||||
|
||||
run = s.run("remove-platform", "android");
|
||||
run.match("removed");
|
||||
|
||||
@@ -872,7 +872,7 @@ selftest.define("add package with no builds", ["net"], function () {
|
||||
|
||||
var run = s.run("add", "glasser:binary-package-with-no-builds");
|
||||
run.waitSecs(10);
|
||||
run.matchErr("No compatible build found for " +
|
||||
run.matchErr("No compatible build found for\n" +
|
||||
"glasser:binary-package-with-no-builds@1.0.0");
|
||||
run.expectExit(1);
|
||||
});
|
||||
|
||||
@@ -79,7 +79,8 @@ selftest.define("springboard", ['checkout', 'net'], function () {
|
||||
run = s.run();
|
||||
run.matchErr("offline");
|
||||
run.matchErr("it uses Meteor strange");
|
||||
run.matchErr("don't have that version of Meteor installed");
|
||||
run.matchErr("don't have that version");
|
||||
run.matchErr("of Meteor installed");
|
||||
run.matchErr("update servers");
|
||||
run.expectExit(1);
|
||||
|
||||
@@ -186,7 +187,8 @@ selftest.define("checkout", ['checkout'], function () {
|
||||
s.write(".meteor/release", "something");
|
||||
run = s.run("list");
|
||||
run.readErr("=> Running Meteor from a checkout");
|
||||
run.matchErr("project version (Meteor something)\n");
|
||||
run.matchErr("project version");
|
||||
run.matchErr("(Meteor something)\n");
|
||||
run.expectExit(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -112,49 +112,8 @@ exports.printPackageList = function (items, options) {
|
||||
};
|
||||
rows = _.sortBy(rows, alphaSort);
|
||||
|
||||
return utils.printTwoColumns(rows, options);
|
||||
};
|
||||
|
||||
// XXX: Move to e.g. formatters.js?
|
||||
// Prints a two column table in a nice format:
|
||||
// The first column is printed entirely, the second only as space permits
|
||||
exports.printTwoColumns = function (rows, options) {
|
||||
options = options || {};
|
||||
|
||||
var longest = '';
|
||||
_.each(rows, function (row) {
|
||||
var col0 = row[0] || '';
|
||||
if (col0.length > longest.length)
|
||||
longest = col0;
|
||||
});
|
||||
|
||||
var pad = longest.replace(/./g, ' ');
|
||||
|
||||
var width = 80;
|
||||
var stream = process.stdout;
|
||||
if (stream && stream.isTTY && stream.columns) {
|
||||
width = stream.columns;
|
||||
}
|
||||
|
||||
var Console = require("./console.js").Console;
|
||||
|
||||
var out = '';
|
||||
_.each(rows, function (row) {
|
||||
var col0 = row[0] || '';
|
||||
var col1 = row[1] || '';
|
||||
var line = Console.bold(col0) + pad.substr(col0.length);
|
||||
line += " " + col1;
|
||||
if (line.length > width) {
|
||||
line = line.substr(0, width - 3) + '...';
|
||||
}
|
||||
out += line + "\n";
|
||||
});
|
||||
|
||||
// XXX: Naughty call to 'private' function
|
||||
var level = options.level || Console.LEVEL_INFO;
|
||||
Console._print(level, out);
|
||||
|
||||
return out;
|
||||
var Console = require('./console.js').Console;
|
||||
return Console.printTwoColumns(rows, options);
|
||||
};
|
||||
|
||||
// Determine a human-readable hostname for this computer. Prefer names
|
||||
@@ -300,7 +259,8 @@ exports.validatePackageNameOrExit = function (packageName, options) {
|
||||
} catch (e) {
|
||||
if (!e.versionParserError)
|
||||
throw e;
|
||||
process.stderr.write("Error: " + e.message + "\n");
|
||||
var Console = require('./console.js').Console;
|
||||
Console.error(e.message, Console.options({ bulletPoint: "Error: " }));
|
||||
// lazy-load main: old bundler tests fail if you add a circular require to
|
||||
// this file
|
||||
var main = require('./main.js');
|
||||
|
||||
Reference in New Issue
Block a user