mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Eliminate context.appDir. Introduce requiresApp.
This commit is contained in:
@@ -53,12 +53,11 @@ var hostedWithGalaxy = function (site) {
|
||||
//
|
||||
// If called from a run that isn't in an app directory, print an error
|
||||
// and kill the process!
|
||||
var findMongoPort = function (context, cmd) {
|
||||
var findMongoPort = function (appDir) {
|
||||
var fut = new Future;
|
||||
|
||||
main.requireDirInApp(context, cmd);
|
||||
var mongo_runner = require(path.join(__dirname, 'mongo_runner.js'));
|
||||
mongo_runner.find_mongo_port(context.appDir, function (port) {
|
||||
mongo_runner.find_mongo_port(appDir, function (port) {
|
||||
fut.return(port);
|
||||
});
|
||||
|
||||
@@ -72,7 +71,7 @@ var findMongoPort = function (context, cmd) {
|
||||
// Prints the Meteor architecture name of this host
|
||||
main.registerCommand({
|
||||
name: '--arch',
|
||||
maxArgs: 0
|
||||
requiresRelease: false
|
||||
}, function (options) {
|
||||
var archinfo = require('./archinfo.js');
|
||||
console.log(archinfo.host());
|
||||
@@ -84,7 +83,7 @@ main.registerCommand({
|
||||
// (making this useful to scripts).
|
||||
main.registerCommand({
|
||||
name: '--version',
|
||||
maxArgs: 0
|
||||
requiresRelease: false
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
|
||||
@@ -104,7 +103,7 @@ main.registerCommand({
|
||||
// Internal use only.
|
||||
main.registerCommand({
|
||||
name: '--built-by',
|
||||
maxArgs: 0
|
||||
requiresRelease: false
|
||||
}, function (options) {
|
||||
var packages = require('./packages.js');
|
||||
console.log(packages.BUILT_BY);
|
||||
@@ -120,7 +119,7 @@ main.registerCommand({
|
||||
// manifest and all of the packages in it.
|
||||
main.registerCommand({
|
||||
name: '--get-ready',
|
||||
maxArgs: 0
|
||||
requiresRelease: false
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
|
||||
@@ -142,6 +141,7 @@ main.registerCommand({
|
||||
|
||||
main.registerCommand({
|
||||
name: 'run',
|
||||
requiresApp: true,
|
||||
options: {
|
||||
port: { type: Number, short: "p", default: 3000 },
|
||||
production: { type: Boolean },
|
||||
@@ -156,7 +156,6 @@ main.registerCommand({
|
||||
}
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
main.requireDirInApp(context, "run");
|
||||
|
||||
if (files.usesWarehouse() &&
|
||||
context.appReleaseVersion !== 'none' &&
|
||||
@@ -168,7 +167,7 @@ main.registerCommand({
|
||||
|
||||
auth.tryRevokeOldTokens({timeout: 1000});
|
||||
|
||||
runner.run(context, {
|
||||
runner.run(options.appDir, context, {
|
||||
port: options.port,
|
||||
rawLogs: options['raw-logs'],
|
||||
minify: options.production,
|
||||
@@ -278,7 +277,10 @@ main.registerCommand({
|
||||
options: {
|
||||
// Undocumented flag (used, eg, by upgrade-to-engine.js).
|
||||
'dont-fetch-latest': { type: Boolean }
|
||||
}
|
||||
},
|
||||
// We have to be able to work without a release, since 'meteor
|
||||
// update' is how you fix apps that don't have a release.
|
||||
requiresRelease: false
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
|
||||
@@ -318,7 +320,7 @@ main.registerCommand({
|
||||
|
||||
// If we're not in an app, then we're done (other than maybe printing some
|
||||
// stuff).
|
||||
if (! context.appDir) {
|
||||
if (! options.appDir) {
|
||||
if (options["dont-fetch-latest"])
|
||||
return;
|
||||
if (options.release || didGlobalUpdateWithoutSpringboarding) {
|
||||
@@ -326,6 +328,11 @@ main.registerCommand({
|
||||
// update (with springboarding, in which case --release is set, or
|
||||
// without springboarding, in which case didGlobalUpdate is set),
|
||||
// print this message.
|
||||
//
|
||||
// (Realize that if they specified --release, the release has
|
||||
// already been installed by virtue of the install/springboard
|
||||
// process that runs at startup even before command starts
|
||||
// running.)
|
||||
console.log("Installed. Run 'meteor update' inside of a particular project\n" +
|
||||
"directory to update that project to Meteor %s.",
|
||||
context.releaseVersion);
|
||||
@@ -341,7 +348,7 @@ main.registerCommand({
|
||||
}
|
||||
|
||||
// Otherwise, we have to upgrade the app too, if the release changed.
|
||||
var appRelease = project.getMeteorReleaseVersion(context.appDir);
|
||||
var appRelease = project.getMeteorReleaseVersion(options.appDir);
|
||||
if (appRelease !== null && appRelease === context.releaseVersion) {
|
||||
if (triedToGloballyUpdateButFailed) {
|
||||
console.log(
|
||||
@@ -357,7 +364,7 @@ main.registerCommand({
|
||||
}
|
||||
|
||||
// Write the release to .meteor/release.
|
||||
project.writeMeteorReleaseVersion(context.appDir,
|
||||
project.writeMeteorReleaseVersion(options.appDir,
|
||||
context.releaseVersion);
|
||||
|
||||
// Find upgraders (in order) necessary to upgrade the app for the new
|
||||
@@ -371,7 +378,7 @@ main.registerCommand({
|
||||
var upgraders = _.difference(context.releaseManifest.upgraders || [],
|
||||
oldManifest.upgraders || []);
|
||||
_.each(upgraders, function (upgrader) {
|
||||
require("./upgraders.js").runUpgrader(upgrader, context.appDir);
|
||||
require("./upgraders.js").runUpgrader(upgrader, options.appDir);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -379,12 +386,12 @@ main.registerCommand({
|
||||
// order to update it for the new release .
|
||||
// XXX add app packages to .meteor/packages here for linker upgrade!
|
||||
console.log("%s: updated to Meteor %s.",
|
||||
path.basename(context.appDir), context.releaseVersion);
|
||||
path.basename(options.appDir), context.releaseVersion);
|
||||
|
||||
// Print any notices relevant to this upgrade.
|
||||
// XXX This doesn't include package-specific notices for packages that
|
||||
// are included transitively (eg, packages used by app packages).
|
||||
var packages = project.get_packages(context.appDir);
|
||||
var packages = project.get_packages(options.appDir);
|
||||
warehouse.printNotices(appRelease, context.releaseVersion, packages);
|
||||
});
|
||||
|
||||
@@ -397,17 +404,15 @@ main.registerCommand({
|
||||
hidden: true,
|
||||
minArgs: 1,
|
||||
maxArgs: 1,
|
||||
options: {
|
||||
}
|
||||
requiresApp: true
|
||||
}, function (options) {
|
||||
var upgrader = options.args[0];
|
||||
var context = options.context;
|
||||
main.requireDirInApp(context, "run-upgrader");
|
||||
|
||||
var upgraders = require("./upgraders.js");
|
||||
console.log("%s: running upgrader %s.",
|
||||
path.basename(context.appDir), upgrader);
|
||||
upgraders.runUpgrader(upgrader, context.appDir);
|
||||
path.basename(options.appDir), upgrader);
|
||||
upgraders.runUpgrader(upgrader, options.appDir);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -418,14 +423,13 @@ main.registerCommand({
|
||||
name: 'add',
|
||||
minArgs: 1,
|
||||
maxArgs: Infinity,
|
||||
requiresApp: true
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
|
||||
main.requireDirInApp(context, 'add');
|
||||
|
||||
var all = context.library.list();
|
||||
var using = {};
|
||||
_.each(project.get_packages(context.appDir), function (name) {
|
||||
_.each(project.get_packages(options.appDir), function (name) {
|
||||
using[name] = true;
|
||||
});
|
||||
|
||||
@@ -435,7 +439,7 @@ main.registerCommand({
|
||||
} else if (name in using) {
|
||||
process.stderr.write(name + ": already using\n");
|
||||
} else {
|
||||
project.add_package(context.appDir, name);
|
||||
project.add_package(options.appDir, name);
|
||||
var note = all[name].metadata.summary || '';
|
||||
process.stderr.write(name + ": " + note + "\n");
|
||||
}
|
||||
@@ -450,14 +454,12 @@ main.registerCommand({
|
||||
name: 'remove',
|
||||
minArgs: 1,
|
||||
maxArgs: Infinity,
|
||||
options: {
|
||||
}
|
||||
requiresApp: true
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
|
||||
main.requireDirInApp(context, 'remove');
|
||||
var using = {};
|
||||
_.each(project.get_packages(context.appDir), function (name) {
|
||||
_.each(project.get_packages(options.appDir), function (name) {
|
||||
using[name] = true;
|
||||
});
|
||||
|
||||
@@ -465,7 +467,7 @@ main.registerCommand({
|
||||
if (! (name in using)) {
|
||||
process.stderr.write(name + ": not in project\n");
|
||||
} else {
|
||||
project.remove_package(context.appDir, name);
|
||||
project.remove_package(options.appDir, name);
|
||||
process.stderr.write(name + ": removed\n");
|
||||
}
|
||||
});
|
||||
@@ -477,6 +479,7 @@ main.registerCommand({
|
||||
|
||||
main.registerCommand({
|
||||
name: 'list',
|
||||
requiresApp: true,
|
||||
options: {
|
||||
using: { type: Boolean }
|
||||
}
|
||||
@@ -484,8 +487,7 @@ main.registerCommand({
|
||||
var context = options.context;
|
||||
|
||||
if (options.using) {
|
||||
main.requireDirInApp(context, 'list --using');
|
||||
var using = project.get_packages(context.appDir);
|
||||
var using = project.get_packages(options.appDir);
|
||||
|
||||
if (using.length) {
|
||||
_.each(using, function (name) {
|
||||
@@ -502,7 +504,6 @@ main.registerCommand({
|
||||
return;
|
||||
}
|
||||
|
||||
main.requireDirInApp(context, 'list');
|
||||
var list = context.library.list();
|
||||
var names = _.keys(list);
|
||||
names.sort();
|
||||
@@ -522,6 +523,7 @@ main.registerCommand({
|
||||
name: 'bundle',
|
||||
minArgs: 1,
|
||||
maxArgs: 1,
|
||||
requiresApp: true,
|
||||
options: {
|
||||
debug: { type: Boolean },
|
||||
// Undocumented
|
||||
@@ -540,13 +542,12 @@ main.registerCommand({
|
||||
|
||||
var context = options.context;
|
||||
|
||||
main.requireDirInApp(context, "bundle");
|
||||
var buildDir = path.join(context.appDir, '.meteor', 'local', 'build_tar');
|
||||
var buildDir = path.join(options.appDir, '.meteor', 'local', 'build_tar');
|
||||
var bundle_path = path.join(buildDir, 'bundle');
|
||||
var output_path = path.resolve(options.args[0]); // get absolute path
|
||||
|
||||
var bundler = require(path.join(__dirname, 'bundler.js'));
|
||||
var bundleResult = bundler.bundle(context.appDir, bundle_path, {
|
||||
var bundleResult = bundler.bundle(options.appDir, bundle_path, {
|
||||
nodeModulesMode: options['for-deploy'] ? 'skip' : 'copy',
|
||||
minify: ! options.debug,
|
||||
releaseStamp: context.releaseVersion,
|
||||
@@ -576,14 +577,17 @@ main.registerCommand({
|
||||
maxArgs: 1,
|
||||
options: {
|
||||
url: { type: Boolean, short: 'U' }
|
||||
},
|
||||
requiresApp: function (options) {
|
||||
return options.args.length === 0;
|
||||
}
|
||||
}, function (options) {
|
||||
var mongoUrl;
|
||||
|
||||
if (options.length === 0) {
|
||||
if (options.args.length === 0) {
|
||||
// localhost mode
|
||||
var fut = new Future;
|
||||
var mongoPort = findMongoPort(options.context, "mongo");
|
||||
var mongoPort = findMongoPort(options.appDir);
|
||||
if (! mongoPort) {
|
||||
process.stdout.write(
|
||||
"mongo: Meteor isn't running.\n" +
|
||||
@@ -625,7 +629,8 @@ main.registerCommand({
|
||||
name: 'reset',
|
||||
// Doesn't actually take an argument, but we want to print an custom
|
||||
// error message if they try to pass one.
|
||||
maxArgs: 1
|
||||
maxArgs: 1,
|
||||
requiresApp: true
|
||||
}, function (options) {
|
||||
if (options.args.length !== 0) {
|
||||
process.stderr.write(
|
||||
@@ -638,7 +643,7 @@ main.registerCommand({
|
||||
return 1;
|
||||
}
|
||||
|
||||
var isRunning = !! findMongoPort(options.context, "reset");
|
||||
var isRunning = !! findMongoPort(options.appDir);
|
||||
if (isRunning) {
|
||||
process.stderr.write(
|
||||
"reset: Meteor is running.\n" +
|
||||
@@ -648,7 +653,7 @@ main.registerCommand({
|
||||
return 1;
|
||||
}
|
||||
|
||||
var localDir = path.join(options.context.appDir, '.meteor', 'local');
|
||||
var localDir = path.join(options.appDir, '.meteor', 'local');
|
||||
files.rm_recursive(localDir);
|
||||
|
||||
process.stdout.write("Project reset.\n");
|
||||
@@ -674,6 +679,9 @@ main.registerCommand({
|
||||
// application as an admin app, so that it will be available in
|
||||
// Galaxy admin interface.
|
||||
admin: { type: Boolean }
|
||||
},
|
||||
requiresApp: function (options) {
|
||||
return options.delete || options.star ? false : true;
|
||||
}
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
@@ -706,8 +714,9 @@ main.registerCommand({
|
||||
|
||||
// We don't need to be in an app if we're not going to run the bundler.
|
||||
var starball = options.star;
|
||||
if (! starball)
|
||||
main.requireDirInApp(context, "deploy");
|
||||
// XXX I think this is only supported for deploying to Galaxy, so it
|
||||
// should print an error if you try to pass --starball while
|
||||
// deploying to Meteor.
|
||||
|
||||
var settings = undefined;
|
||||
if (options.settings)
|
||||
@@ -727,7 +736,7 @@ main.registerCommand({
|
||||
var deployGalaxy = require('./deploy-galaxy.js');
|
||||
deployGalaxy.deploy({
|
||||
app: site,
|
||||
appDir: context.appDir,
|
||||
appDir: options.appDir,
|
||||
settings: settings,
|
||||
context: context,
|
||||
starball: starball,
|
||||
@@ -741,7 +750,7 @@ main.registerCommand({
|
||||
});
|
||||
} else {
|
||||
deploy.bundleAndDeploy({
|
||||
appDir: context.appDir,
|
||||
appDir: options.appDir,
|
||||
site: site,
|
||||
settings: settings,
|
||||
bundleOptions: {
|
||||
@@ -914,17 +923,17 @@ main.registerCommand({
|
||||
// run multiple "test-packages" commands in parallel without them stomping
|
||||
// on each other.
|
||||
//
|
||||
// Note: context.appDir now is DIFFERENT from
|
||||
// Note: testRunnerAppDir is DIFFERENT from
|
||||
// bundleOptions.library.appDir: we are bundling the test
|
||||
// runner app, but finding app packages from the current app (if any).
|
||||
context.appDir = files.mkdtemp('meteor-test-run');
|
||||
files.cp_r(path.join(__dirname, 'test-runner-app'), context.appDir);
|
||||
project.add_package(context.appDir,
|
||||
var testRunnerAppDir = files.mkdtemp('meteor-test-run');
|
||||
files.cp_r(path.join(__dirname, 'test-runner-app'), testRunnerAppDir);
|
||||
project.add_package(testRunnerAppDir,
|
||||
options['driver-package'] || 'test-in-browser');
|
||||
|
||||
if (options.deploy) {
|
||||
deploy.bundleAndDeploy({
|
||||
appDir: context.appDir,
|
||||
appDir: testRunnerAppDir,
|
||||
site: options.deploy,
|
||||
settings: options.settings && runner.getSettings(options.settings),
|
||||
bundleOptions: {
|
||||
@@ -936,7 +945,7 @@ main.registerCommand({
|
||||
}
|
||||
});
|
||||
} else {
|
||||
runner.run(context, {
|
||||
runner.run(testRunnerAppDir, context, {
|
||||
port: options.port,
|
||||
minify: options.production,
|
||||
once: options.once,
|
||||
@@ -958,11 +967,11 @@ main.registerCommand({
|
||||
}, function (options) {
|
||||
var context = options.context;
|
||||
|
||||
if (context.appDir) {
|
||||
if (options.appDir) {
|
||||
// The library doesn't know about other programs in your app. Let's blow
|
||||
// away their .build directories if they have them, and not rebuild
|
||||
// them. Sort of hacky, but eh.
|
||||
var programsDir = path.join(context.appDir, 'programs');
|
||||
var programsDir = path.join(options.appDir, 'programs');
|
||||
try {
|
||||
var programs = fs.readdirSync(programsDir);
|
||||
} catch (e) {
|
||||
@@ -1086,9 +1095,7 @@ main.registerCommand({
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
main.registerCommand({
|
||||
name: 'whoami',
|
||||
options: {
|
||||
}
|
||||
name: 'whoami'
|
||||
}, function (options) {
|
||||
return auth.whoAmICommand(options);
|
||||
});
|
||||
|
||||
@@ -124,6 +124,8 @@ _.extend(exports, {
|
||||
return test_dir;
|
||||
},
|
||||
|
||||
// Determine if 'filepath' (a path, or omit for cwd) is within an
|
||||
// app directory. If so, return the top-level app directory.
|
||||
findAppDir: function (filepath) {
|
||||
return files.find_upwards(files.is_app_dir, filepath);
|
||||
},
|
||||
|
||||
187
tools/main.js
187
tools/main.js
@@ -19,13 +19,24 @@ var main = exports;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var Command = function (options) {
|
||||
this.name = options.name;
|
||||
this.minArgs = options.minArgs || 0;
|
||||
this.maxArgs = this.minArgs || 0;
|
||||
this.options = options.options || {};
|
||||
this.raw = options.raw || false;
|
||||
this.hidden = options.hidden || false;
|
||||
this.func = options.func;
|
||||
options = _.extend({
|
||||
minArgs: 0,
|
||||
options: {},
|
||||
requiresApp: false,
|
||||
requiresRelease: true,
|
||||
raw: false,
|
||||
hidden: false
|
||||
}, options);
|
||||
|
||||
if (! _.has(options, 'maxArgs'))
|
||||
options.maxArgs = options.minArgs;
|
||||
|
||||
_.each(["name", "func"], function (key) {
|
||||
if (! _.has(options, key))
|
||||
throw new Error("command missing '" + key + "'?");
|
||||
});
|
||||
|
||||
_.extend(this, options);
|
||||
|
||||
_.each(this.options, function (value, key) {
|
||||
if (! _.has(value, 'type'))
|
||||
@@ -71,6 +82,35 @@ main.ShowUsage = function () {};
|
||||
// - short: single character short alias (eg, 'p' for 'port', to do -p 3000)
|
||||
// - default: value to use if none supplied
|
||||
// - required: true if required (incompatible with 'default')
|
||||
// - requiresApp: does this command work with an app? possible values:
|
||||
// - true if an app is required, and command must be run inside an
|
||||
// app. The command will be run using the app's Meteor release
|
||||
// (unless overridden by --release or a checkout). An 'appDir'
|
||||
// option will be passed with the absolute path to the app's
|
||||
// top-level directory, and an error will be printed if the
|
||||
// command isn't run from inside an app.
|
||||
// - false if an app is not required. But if the command does happen
|
||||
// to have been run from an app, 'appDir' will be
|
||||
// provided. Moreover, in that case, we will still use the version
|
||||
// of this program that goes with the Meteor release of the
|
||||
// app. This is not ideal but is necessary for 'meteor help' to
|
||||
// behave in a sane way in our current system. (XXX In the future
|
||||
// we should separate the build system out into a package that is
|
||||
// versioned with the release, and then take the CLI tool out of
|
||||
// the release and always use the latest available version.)
|
||||
// - function: some apps determine whether they use an app based on
|
||||
// their arguments (eg, 'deploy' versus 'deploy --delete'). for
|
||||
// these, set usesApp to a function that takes 'options' (same as
|
||||
// would be received by the actual command function) and returns
|
||||
// true or false.
|
||||
// - requiresRelease: defaults to true. Set to false if this command
|
||||
// doesn't need a functioning Meteor release to be available (that
|
||||
// is, if the command does not need the ability to resolve
|
||||
// packages). There is only one case where this comes up: if you
|
||||
// create an app with a checkout (so that it has no release), and
|
||||
// then run that app with released Meteor. Normally this just prints
|
||||
// an error saying that you have to pick a release, but you can
|
||||
// disable that by setting this flag to false.
|
||||
// - raw: if true, option parsing is completely skipped (including
|
||||
// --release and --help). To be activated the command will need to be
|
||||
// literally the first argument, and it will need to do its own option
|
||||
@@ -190,9 +230,6 @@ var setReleaseVersion = function (context, version) {
|
||||
//
|
||||
// Keys in context:
|
||||
//
|
||||
// - appDir: if 'meteor' was run from inside a project (a project has a file
|
||||
// .meteor/packages), the absolute path to the top-level project directory
|
||||
//
|
||||
// - releaseVersion: the actual Meteor release that we are now
|
||||
// using. if running from a checkout, "none". else we have a
|
||||
// release, either from --release on the command line, the release
|
||||
@@ -239,9 +276,10 @@ var setReleaseVersion = function (context, version) {
|
||||
// - authToken
|
||||
//
|
||||
// Arguments to calculateContext:
|
||||
// - appDir: if non-null, the app
|
||||
// - releaseOverride: if non-null, the --release the user asked for on
|
||||
// the command line
|
||||
var calculateContext = function (releaseOverride) {
|
||||
var calculateContext = function (appDir, releaseOverride) {
|
||||
var context = {};
|
||||
|
||||
var calculateReleaseVersion = function () {
|
||||
@@ -264,13 +302,11 @@ var calculateContext = function (releaseOverride) {
|
||||
warehouse.latestRelease();
|
||||
};
|
||||
|
||||
var appDir = files.findAppDir();
|
||||
context.appDir = appDir && path.resolve(appDir);
|
||||
context.globalReleaseVersion = calculateReleaseVersion();
|
||||
|
||||
if (context.appDir) {
|
||||
if (appDir) {
|
||||
context.appReleaseVersion =
|
||||
project.getMeteorReleaseVersion(context.appDir) ||
|
||||
project.getMeteorReleaseVersion(appDir) ||
|
||||
(files.usesWarehouse() ? warehouse.latestRelease() : 'none');
|
||||
}
|
||||
context.userReleaseOverride = !!releaseOverride;
|
||||
@@ -284,14 +320,14 @@ var calculateContext = function (releaseOverride) {
|
||||
|
||||
// Prints a message if $METEOR_TOOLS_DEBUG is set.
|
||||
// XXX We really should have a better logging system.
|
||||
// XXX XXX there is only one call anywhere to this (in toolsSpringboard)
|
||||
// XXX XXX there are only two calls anywhere to this (they're here in this file)
|
||||
var toolsDebugMessage = function (msg) {
|
||||
if (process.env.METEOR_TOOLS_DEBUG)
|
||||
console.log("[TOOLS DEBUG] " + msg);
|
||||
};
|
||||
|
||||
// As the first step of running the Meteor CLI, check which Meteor
|
||||
// release we should be running against. Then, check whether the
|
||||
// release we shouldb e running against. Then, check whether the
|
||||
// tools corresponding to that release is the same as the one
|
||||
// we're running. If not, springboard to the right tools (after
|
||||
// having fetched it to the local warehouse)
|
||||
@@ -403,47 +439,6 @@ var longHelp = function (commandName) {
|
||||
// XXX XXX XXX stuff that should go away
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// XXX refactor/remove
|
||||
//
|
||||
// If we're not in an app directory, die with an error message.
|
||||
//
|
||||
// @param cmd {String} The command that was run. Used when printing
|
||||
// error message.
|
||||
main.requireDirInApp = function (context, cmd) {
|
||||
if (context.appDir) {
|
||||
// XXX this is an inelegant place to put these checks, but it is pretty
|
||||
// accurate for now: "all the commands that need an app and don't do
|
||||
// something special with releases" (ie, everything but create, update,
|
||||
// help, logs, mongo SITE, test-packages, and deploy -D).
|
||||
if (!files.usesWarehouse() && context.appReleaseVersion !== 'none') {
|
||||
console.log(
|
||||
"=> Running Meteor from a checkout -- overrides project version (%s)",
|
||||
context.appReleaseVersion);
|
||||
console.log();
|
||||
}
|
||||
if (files.usesWarehouse() && context.releaseVersion === 'none') {
|
||||
logging.die(
|
||||
"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'.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
// This is where you end up if you type 'meteor' with no args. Be gentle to
|
||||
// the noobs..
|
||||
logging.die(cmd + ": 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'.");
|
||||
};
|
||||
|
||||
|
||||
// XXX refactor/remove
|
||||
// called by the update command - we need to find another way to do this
|
||||
main.hackContextForUpdateMaybeSpringboard = function (context) {
|
||||
@@ -604,7 +599,35 @@ Fiber(function () {
|
||||
delete parsed.release;
|
||||
}
|
||||
|
||||
var context = calculateContext(releaseOverride);
|
||||
var appDir = files.findAppDir();
|
||||
if (appDir)
|
||||
appDir = path.resolve(appDir);
|
||||
var context = calculateContext(appDir, releaseOverride);
|
||||
|
||||
// (NB: At this point, we might be in an inconsistent state where we
|
||||
// have context.releaseVersion === 'none' and no manifest, as if we
|
||||
// were in a checkout; yet we are not in a checkout, and thus we
|
||||
// can't resolve packages. This happens if you create a project with
|
||||
// a checkout and then run it with a release. We'll check for this
|
||||
// in a moment.)
|
||||
|
||||
if (files.usesWarehouse() && context.releaseVersion === 'none') {
|
||||
// We are in an app that was created with a checkout and has not
|
||||
// been given a proper release, but we're not running from a
|
||||
// checkout anymore, so we don't know what release to use. The
|
||||
// user needs to tell us either with --release or by 'meteor
|
||||
// update'ing the project to a release.
|
||||
//
|
||||
// We used to allow this for commands that had requiresApp false.
|
||||
|
||||
logging.die(
|
||||
"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'.");
|
||||
}
|
||||
|
||||
|
||||
// If we're not running the correct tools, fetch it and
|
||||
// re-run. Do *not* do this if we are in a checkout, or if
|
||||
@@ -815,6 +838,52 @@ longHelp(commandName) + "\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// We know we have a valid command and options. Now check to see if
|
||||
// the command can only be run from an app dir, and add the appDir
|
||||
// option if running from an app.
|
||||
var requiresApp = command.requiresApp;
|
||||
if (typeof requiresApp === "function")
|
||||
requiresApp = requiresApp(options);
|
||||
|
||||
if (appDir)
|
||||
options.appDir = appDir;
|
||||
|
||||
if (requiresApp && ! options.appDir) {
|
||||
// This is where you end up if you type 'meteor' with no args,
|
||||
// since you'll default to the 'run' command which requires an
|
||||
// app. Be welcoming to our new developers!
|
||||
process.stderr.write(
|
||||
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'.\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (options.requiresRelease &&
|
||||
(files.usesWarehouse() && context.releaseVersion === 'none')) {
|
||||
process.stderr.write(
|
||||
"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'.\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (options.requiresApp &&
|
||||
(! files.usesWarehouse() && context.appReleaseVersion !== 'none')) {
|
||||
// For commands that work with apps, if we have overridden the
|
||||
// app's usual release by using a checkout, print a reminder banner.
|
||||
process.stdout.write(
|
||||
"=> Running Meteor from a checkout -- overrides project version (%s)\n\n",
|
||||
context.appReleaseVersion);
|
||||
}
|
||||
|
||||
// Now that we're ready to start executing the command, if we are in
|
||||
// startup time profiling mode, print the profile.
|
||||
if (showRequireProfile)
|
||||
|
||||
@@ -147,10 +147,10 @@ exports.launchMongo = function (options) {
|
||||
'mongod');
|
||||
|
||||
// store data in app_dir
|
||||
var dbPath = path.join(options.context.appDir, '.meteor', 'local', 'db');
|
||||
var dbPath = path.join(options.appDir, '.meteor', 'local', 'db');
|
||||
files.mkdir_p(dbPath, 0755);
|
||||
// add .gitignore if needed.
|
||||
files.add_to_gitignore(path.join(options.context.appDir, '.meteor'), 'local');
|
||||
files.add_to_gitignore(path.join(options.appDir, '.meteor'), 'local');
|
||||
|
||||
find_mongo_and_kill_it_dead(options.port, function (err) {
|
||||
Fiber(function (){
|
||||
|
||||
13
tools/run.js
13
tools/run.js
@@ -405,13 +405,13 @@ exports.getSettings = function (filename, watchSet) {
|
||||
//
|
||||
//
|
||||
// banner can be used to replace the application path that is normally
|
||||
// printed on startup (context.appDir) with an arbitrary string, for
|
||||
// printed on startup (appDir) with an arbitrary string, for
|
||||
// example if you autogenerated an app in a temp file to run tests
|
||||
exports.run = function (context, options) {
|
||||
exports.run = function (appDir, context, options) {
|
||||
var outerPort = options.port || 3000;
|
||||
var innerPort = outerPort + 1;
|
||||
var mongoPort = outerPort + 2;
|
||||
var bundlePath = path.join(context.appDir, '.meteor', 'local', 'build');
|
||||
var bundlePath = path.join(appDir, '.meteor', 'local', 'build');
|
||||
// Allow override and use of external mongo. Matches code in launch_mongo.
|
||||
var mongoUrl = process.env.MONGO_URL ||
|
||||
("mongodb://127.0.0.1:" + mongoPort + "/meteor");
|
||||
@@ -515,7 +515,7 @@ exports.run = function (context, options) {
|
||||
// though; there's not a real app to update there!)
|
||||
if (files.usesWarehouse() && !context.userReleaseOverride &&
|
||||
!options.testPackages) {
|
||||
var newAppRelease = project.getMeteorReleaseVersion(context.appDir) ||
|
||||
var newAppRelease = project.getMeteorReleaseVersion(appDir) ||
|
||||
warehouse.latestRelease();
|
||||
if (newAppRelease !== context.appReleaseVersion) {
|
||||
console.error("Your app has been updated to Meteor %s from " +
|
||||
@@ -529,7 +529,7 @@ exports.run = function (context, options) {
|
||||
serverLog = [];
|
||||
|
||||
// Bundle up the app
|
||||
var bundleResult = bundler.bundle(context.appDir, bundlePath, bundleOpts);
|
||||
var bundleResult = bundler.bundle(appDir, bundlePath, bundleOpts);
|
||||
var watchSet = bundleResult.watchSet;
|
||||
if (bundleResult.errors) {
|
||||
logToClients({stdout: "=> Errors prevented startup:\n\n" +
|
||||
@@ -614,6 +614,7 @@ exports.run = function (context, options) {
|
||||
Fiber(function () {
|
||||
Status.mongoHandle = mongo_runner.launchMongo({
|
||||
context: context,
|
||||
appDir: appDir,
|
||||
port: mongoPort,
|
||||
onListen: function () { // On Mongo startup complete
|
||||
// don't print mongo startup is slow warning.
|
||||
@@ -672,7 +673,7 @@ exports.run = function (context, options) {
|
||||
};
|
||||
|
||||
startProxy(outerPort, innerPort, function () {
|
||||
var banner = options.banner || files.pretty_path(context.appDir);
|
||||
var banner = options.banner || files.pretty_path(appDir);
|
||||
process.stdout.write("[[[[[ " + banner + " ]]]]]\n\n");
|
||||
|
||||
mongoStartupPrintTimer = setTimeout(function () {
|
||||
|
||||
Reference in New Issue
Block a user