Chromium Code Reviews| Index: sdk/lib/_internal/pub/lib/src/command_deploy.dart |
| diff --git a/sdk/lib/_internal/pub/lib/src/command_deploy.dart b/sdk/lib/_internal/pub/lib/src/command_deploy.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..51d2bd067d02f31cd4a3d092a3b37749f6021636 |
| --- /dev/null |
| +++ b/sdk/lib/_internal/pub/lib/src/command_deploy.dart |
| @@ -0,0 +1,140 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +library command_deploy; |
| + |
| +import 'dart:async'; |
| +import 'dart:math' as math; |
| + |
| +import 'package:analyzer_experimental/analyzer.dart'; |
| +import 'package:pathos/path.dart' as path; |
| + |
| +import 'command.dart'; |
| +import 'dart.dart' as dart; |
| +import 'io.dart'; |
| +import 'log.dart' as log; |
| +import 'utils.dart'; |
| + |
| +final _arrow = getSpecial('\u2192', '=>'); |
| + |
| +/// Handles the `deploy` pub command. |
|
Andrei Mouravski
2013/05/10 21:56:34
Probably should mention what exactly it does and m
nweiz
2013/05/13 21:59:45
This isn't the place for that. We'll add full docu
Andrei Mouravski
2013/05/13 22:40:33
You don't have to add much, and it might be valuab
nweiz
2013/05/13 23:32:59
The class itself includes as much information as "
|
| +class DeployCommand extends PubCommand { |
| + final description = "Copy and compile all Dart entrypoints in the 'web' " |
| + "directory."; |
| + final usage = "pub deploy [options]"; |
| + final aliases = const ["settle-up"]; |
| + |
| + // TODO(nweiz): make these configurable. |
| + /// The path to the source directory of the deployment. |
| + String get source => path.join(entrypoint.root.dir, 'web'); |
| + |
| + /// The path to the target directory of the deployment. |
| + String get target => path.join(entrypoint.root.dir, 'deploy'); |
| + |
| + /// The set of Dart entrypoints in [source] that should be compiled to [out]. |
| + final _entrypoints = new List<String>(); |
| + |
| + var _maxVerbLength; |
| + var _maxSourceLength; |
| + |
| + Future onRun() { |
| + if (!dirExists(source)) { |
| + throw new ApplicationException("There is no '$source' directory."); |
| + } |
| + |
| + return entrypoint.packageFiles(beneath: source).then((files) { |
| + log.message("Finding entrypoints..."); |
| + _findEntrypoints(files); |
| + _computeLogSize(); |
| + |
| + cleanDir(target); |
| + _logAction("Copying", "${path.relative(source)}/", |
| + "${path.relative(target)}/"); |
| + copyFiles(files.where((file) => path.extension(file) != '.dart'), |
| + source, target); |
| + |
| + return Future.forEach(_entrypoints, (sourceFile) { |
| + var targetFile = |
| + path.join(target, path.relative(sourceFile, from: source)); |
| + var relativeTargetFile = path.relative(targetFile); |
| + var relativeSourceFile = path.relative(sourceFile); |
| + |
| + ensureDir(path.dirname(targetFile)); |
| + _logAction("Compiling", relativeSourceFile, "$relativeTargetFile.js"); |
| + // TODO(nweiz): print dart2js errors/warnings in red. |
| + return dart.compile(sourceFile, packageRoot: entrypoint.packagesDir) |
| + .then((js) { |
| + writeTextFile("$targetFile.js", js, dontLogContents: true); |
| + _logAction("Compiling", relativeSourceFile, "$relativeTargetFile"); |
| + return dart.compile(sourceFile, |
| + packageRoot: entrypoint.packagesDir, toDart: true); |
| + }).then((dart) { |
| + writeTextFile(targetFile, dart, dontLogContents: true); |
| + // TODO(nweiz): we should put dart.js files next to any HTML file |
| + // rather than any entrypoint. An HTML file could import an entrypoint |
| + // that's not adjacent. |
| + _maybeAddDartJs(path.dirname(targetFile)); |
| + }); |
| + }); |
| + }); |
| + } |
| + |
| + /// Populates [_entrypoints] with all of the Dart entrypoints in [files]. |
| + /// [files] should be a list of paths in [source]. |
| + void _findEntrypoints(List<String> files) { |
| + for (var file in files) { |
| + if (path.extension(file) != '.dart') continue; |
| + try { |
| + if (!dart.isEntrypoint(parseDartFile(file))) continue; |
| + } on FormatException catch (e) { |
| + log.warning(e.message); |
| + continue; |
| + } |
| + _entrypoints.add(file); |
| + } |
| + // Sort to ensure a deterministic order of compilation and output. |
| + _entrypoints.sort(); |
| + } |
| + |
| + /// Computes the maximum widths of words that will be used in log output for |
| + /// the deploy command. |
|
Andrei Mouravski
2013/05/10 22:25:02
Please document that this should be run after _fin
nweiz
2013/05/13 21:59:45
Done.
|
| + void _computeLogSize() { |
| + _maxVerbLength = ["Copying", "Compiling"] |
| + .map((verb) => verb.length).reduce(math.max); |
| + var sourceLengths = new List.from( |
| + _entrypoints.map((file) => path.relative(file).length)) |
| + ..add("${path.relative(source)}/".length); |
| + if (_shouldAddDartJs) sourceLengths.add("package:browser/dart.js".length); |
| + _maxSourceLength = sourceLengths.reduce(math.max); |
| + } |
| + |
| + /// Log a deployment action. |
| + void _logAction(String verb, String source, String target) { |
| + verb = padRight(verb, _maxVerbLength); |
| + source = padRight(source, _maxSourceLength); |
| + log.message("$verb $source $_arrow $target"); |
| + } |
| + |
| + // TODO(nweiz): do something more principled when issue 6101 is fixed. |
| + /// If this package depends non-transitively on the `browser` package, this |
| + /// ensures that the `dart.js` file is copied into [directory], under |
| + /// `packages/browser/`. |
| + void _maybeAddDartJs(String directory) { |
| + var jsPath = path.join(directory, 'packages', 'browser', 'dart.js'); |
| + // TODO(nweiz): warn if they don't depend on browser? |
| + if (!_shouldAddDartJs || fileExists(jsPath)) return; |
| + |
| + _logAction("Copying", "package:browser/dart.js", path.relative(jsPath)); |
| + ensureDir(path.dirname(jsPath)); |
| + copyFile(path.join(entrypoint.packagesDir, 'browser', 'dart.js'), jsPath); |
| + } |
| + |
| + /// Whether we should copy the browser package's dart.js file into the |
| + /// deployed app. |
| + bool get _shouldAddDartJs { |
| + return !_entrypoints.isEmpty && |
| + entrypoint.root.dependencies.any((dep) => |
| + dep.name == 'browser' && dep.source.name == 'hosted'); |
| + } |
| +} |