Index: sdk/lib/_internal/pub/lib/src/command/run.dart |
diff --git a/sdk/lib/_internal/pub/lib/src/command/run.dart b/sdk/lib/_internal/pub/lib/src/command/run.dart |
index 73b62be8b425e433c0ab2575ae089b1623b2aa3a..5973ca78bc1ae743f63126694358719fba37edaf 100644 |
--- a/sdk/lib/_internal/pub/lib/src/command/run.dart |
+++ b/sdk/lib/_internal/pub/lib/src/command/run.dart |
@@ -39,6 +39,8 @@ class RunCommand extends PubCommand { |
} |
var environment; |
+ var package = entrypoint.root.name; |
+ var rootDir; |
var scriptPath; |
var args; |
return AssetEnvironment.create(entrypoint, BarbackMode.RELEASE, |
@@ -55,40 +57,64 @@ class RunCommand extends PubCommand { |
var script = commandOptions.rest[0]; |
args = commandOptions.rest.skip(1).toList(); |
+ // A command like "foo:bar" runs the "bar" script from the "foo" package. |
+ // If there is no colon prefix, default to the root package. |
+ if (script.contains(":")) { |
Sean Eagan
2014/06/20 12:42:38
Instead of inventing a syntax for this:
pub r
Bob Nystrom
2014/06/20 17:35:27
My hunch is that this will be a very common use ca
|
+ var components = split1(script, ":"); |
+ package = components[0]; |
+ script = components[1]; |
+ |
+ var dep = entrypoint.root.immediateDependencies.firstWhere( |
+ (dep) => dep.name == package, orElse: () => null); |
+ if (dep == null) { |
+ if (environment.graph.packages.containsKey(package)) { |
+ dataError('Package "$package" is not an immediate dependency.\n' |
+ 'Cannot run executables in transitive dependencies.'); |
+ } else { |
+ dataError('Could not find package "$package". Did you forget to ' |
+ 'add a dependency?'); |
+ } |
+ } |
+ } |
+ |
// If the command has a path separator, then it's a path relative to the |
// root of the package. Otherwise, it's implicitly understood to be in |
// "bin". |
- var rootDir; |
var parts = path.split(script); |
if (parts.length > 1) { |
- scriptPath = "$script.dart"; |
+ if (package != entrypoint.root.name) { |
+ usageError("Can not run an executable in a subdirectory of a " |
+ "dependency."); |
+ } |
+ |
+ scriptPath = "${path.url.joinAll(parts.skip(1))}.dart"; |
rootDir = parts.first; |
} else { |
- scriptPath = "bin/$script.dart"; |
+ scriptPath = "$script.dart"; |
rootDir = "bin"; |
} |
- // Serve the entire root-most directory containing the entrypoint. That |
- // ensures that, for example, things like `import '../../utils.dart';` |
- // will work from within some deeply nested script. |
- return environment.serveDirectory(rootDir); |
+ if (package == entrypoint.root.name) { |
+ // Serve the entire root-most directory containing the entrypoint. That |
+ // ensures that, for example, things like `import '../../utils.dart';` |
+ // will work from within some deeply nested script. |
+ return environment.serveDirectory(rootDir); |
+ } else { |
+ // For other packages, always use the "bin" directory. |
+ return environment.servePackageBinDirectory(package); |
+ } |
}).then((server) { |
// Try to make sure the entrypoint script exists (or is generated) before |
// we spawn the process to run it. |
return environment.barback.getAssetById( |
- new AssetId(entrypoint.root.name, scriptPath)).then((_) { |
- return environment.getUrlsForAssetPath(scriptPath).then((urls) { |
- // Should only be bound to one port. |
- assert(urls.length == 1); |
- |
- // Run in checked mode. |
- // TODO(rnystrom): Make this configurable. |
- args.insert(0, "--checked"); |
- |
- // The URL to the Dart entrypoint comes before the script arguments. |
- args.insert(1, urls[0].toString()); |
- return Process.start(Platform.executable, args); |
- }).then((process) { |
+ new AssetId(package, path.url.join(rootDir, scriptPath))).then((_) { |
+ |
+ // Run in checked mode. |
+ // TODO(rnystrom): Make this configurable. |
+ var mode = "--checked"; |
+ args = [mode, server.url.resolve(scriptPath).toString()]..addAll(args); |
+ |
+ return Process.start(Platform.executable, args).then((process) { |
// Note: we're not using process.std___.pipe(std___) here because |
// that prevents pub from also writing to the output streams. |
process.stderr.listen(stderr.add); |
@@ -100,7 +126,12 @@ class RunCommand extends PubCommand { |
}).catchError((error, stackTrace) { |
if (error is! AssetNotFoundException) throw error; |
- log.error("Could not find $scriptPath."); |
+ var message = "Could not find ${path.join(rootDir, scriptPath)}"; |
+ if (package != entrypoint.root.name) { |
+ message += " in package $package"; |
+ } |
+ |
+ log.error("$message."); |
log.fine(new Chain.forTrace(stackTrace)); |
return flushThenExit(exit_codes.NO_INPUT); |
}); |