| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library pub.command.build; | 5 library pub.command.build; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:barback/barback.dart'; | 9 import 'package:barback/barback.dart'; |
| 10 import 'package:path/path.dart' as path; | 10 import 'package:path/path.dart' as path; |
| 11 | 11 |
| 12 import '../barback/build_environment.dart'; | 12 import '../barback/build_environment.dart'; |
| 13 import '../command.dart'; | |
| 14 import '../exit_codes.dart' as exit_codes; | 13 import '../exit_codes.dart' as exit_codes; |
| 15 import '../io.dart'; | 14 import '../io.dart'; |
| 16 import '../log.dart' as log; | 15 import '../log.dart' as log; |
| 17 import '../utils.dart'; | 16 import '../utils.dart'; |
| 17 import 'barback.dart'; |
| 18 | 18 |
| 19 final _arrow = getSpecial('\u2192', '=>'); | 19 final _arrow = getSpecial('\u2192', '=>'); |
| 20 | 20 |
| 21 /// The set of top level directories in the entrypoint package that can be | |
| 22 /// built. | |
| 23 final _allowedBuildDirectories = new Set<String>.from([ | |
| 24 "benchmark", "bin", "example", "test", "web" | |
| 25 ]); | |
| 26 | |
| 27 /// Handles the `build` pub command. | 21 /// Handles the `build` pub command. |
| 28 class BuildCommand extends PubCommand { | 22 class BuildCommand extends BarbackCommand { |
| 29 String get description => "Apply transformers to build a package."; | 23 String get description => "Apply transformers to build a package."; |
| 30 String get usage => "pub build [options] [directories...]"; | 24 String get usage => "pub build [options] [directories...]"; |
| 31 List<String> get aliases => const ["deploy", "settle-up"]; | 25 List<String> get aliases => const ["deploy", "settle-up"]; |
| 32 bool get takesArguments => true; | |
| 33 | 26 |
| 34 // TODO(nweiz): make this configurable. | 27 // TODO(nweiz): make this configurable. |
| 35 /// The path to the application's build output directory. | 28 /// The path to the application's build output directory. |
| 36 String get target => 'build'; | 29 String get target => 'build'; |
| 37 | 30 |
| 38 /// The build mode. | 31 BarbackMode get defaultMode => BarbackMode.RELEASE; |
| 39 BarbackMode get mode => new BarbackMode(commandOptions["mode"]); | 32 |
| 33 List<String> get defaultSourceDirectories => ["web"]; |
| 40 | 34 |
| 41 /// The number of files that have been built and written to disc so far. | 35 /// The number of files that have been built and written to disc so far. |
| 42 int builtFiles = 0; | 36 int builtFiles = 0; |
| 43 | 37 |
| 44 /// The names of the top-level build directories that will be built. | |
| 45 final buildDirectories = new Set<String>(); | |
| 46 | |
| 47 BuildCommand() { | 38 BuildCommand() { |
| 48 commandParser.addOption("format", | 39 commandParser.addOption("format", |
| 49 help: "How output should be displayed.", | 40 help: "How output should be displayed.", |
| 50 allowed: ["text", "json"], defaultsTo: "text"); | 41 allowed: ["text", "json"], defaultsTo: "text"); |
| 51 | |
| 52 commandParser.addOption("mode", defaultsTo: BarbackMode.RELEASE.toString(), | |
| 53 help: "Mode to run transformers in."); | |
| 54 | |
| 55 commandParser.addFlag("all", help: "Build all buildable directories.", | |
| 56 defaultsTo: false, negatable: false); | |
| 57 } | 42 } |
| 58 | 43 |
| 59 Future onRun() { | 44 Future onRunTransformerCommand() { |
| 60 log.json.enabled = commandOptions["format"] == "json"; | |
| 61 | |
| 62 _parseBuildDirectories(); | |
| 63 cleanDir(target); | 45 cleanDir(target); |
| 64 | 46 |
| 65 var errorsJson = []; | 47 var errorsJson = []; |
| 66 var logJson = []; | 48 var logJson = []; |
| 67 | 49 |
| 68 // Since this server will only be hit by the transformer loader and isn't | 50 // Since this server will only be hit by the transformer loader and isn't |
| 69 // user-facing, just use an IPv4 address to avoid a weird bug on the | 51 // user-facing, just use an IPv4 address to avoid a weird bug on the |
| 70 // OS X buildbots. | 52 // OS X buildbots. |
| 71 return BuildEnvironment.create(entrypoint, "127.0.0.1", 0, mode, | 53 return BuildEnvironment.create(entrypoint, "127.0.0.1", 0, mode, |
| 72 WatcherType.NONE, useDart2JS: true) | 54 WatcherType.NONE, useDart2JS: true) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 90 if (log.json.enabled) { | 72 if (log.json.enabled) { |
| 91 environment.barback.log.listen( | 73 environment.barback.log.listen( |
| 92 (entry) => logJson.add(_logEntryToJson(entry))); | 74 (entry) => logJson.add(_logEntryToJson(entry))); |
| 93 } | 75 } |
| 94 | 76 |
| 95 return log.progress("Building ${entrypoint.root.name}", () { | 77 return log.progress("Building ${entrypoint.root.name}", () { |
| 96 // Register all of the build directories. | 78 // Register all of the build directories. |
| 97 // TODO(rnystrom): We don't actually need to bind servers for these, we | 79 // TODO(rnystrom): We don't actually need to bind servers for these, we |
| 98 // just need to add them to barback's sources. Add support to | 80 // just need to add them to barback's sources. Add support to |
| 99 // BuildEnvironment for going the latter without the former. | 81 // BuildEnvironment for going the latter without the former. |
| 100 return Future.wait(buildDirectories.map( | 82 return Future.wait(sourceDirectories.map( |
| 101 (dir) => environment.serveDirectory(dir))).then((_) { | 83 (dir) => environment.serveDirectory(dir))).then((_) { |
| 102 | 84 |
| 103 return environment.barback.getAllAssets(); | 85 return environment.barback.getAllAssets(); |
| 104 }); | 86 }); |
| 105 }).then((assets) { | 87 }).then((assets) { |
| 106 // Find all of the JS entrypoints we built. | 88 // Find all of the JS entrypoints we built. |
| 107 var dart2JSEntrypoints = assets | 89 var dart2JSEntrypoints = assets |
| 108 .where((asset) => asset.id.path.endsWith(".dart.js")) | 90 .where((asset) => asset.id.path.endsWith(".dart.js")) |
| 109 .map((asset) => asset.id); | 91 .map((asset) => asset.id); |
| 110 | 92 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 130 log.json.message({ | 112 log.json.message({ |
| 131 "buildResult": "failure", | 113 "buildResult": "failure", |
| 132 "errors": errorsJson, | 114 "errors": errorsJson, |
| 133 "log": logJson | 115 "log": logJson |
| 134 }); | 116 }); |
| 135 | 117 |
| 136 return flushThenExit(exit_codes.DATA); | 118 return flushThenExit(exit_codes.DATA); |
| 137 }); | 119 }); |
| 138 } | 120 } |
| 139 | 121 |
| 140 /// Parses the command-line arguments to determine the set of top-level | |
| 141 /// directories to build. | |
| 142 /// | |
| 143 /// If there are no arguments to `pub build`, this will just be "web". | |
| 144 /// | |
| 145 /// If the `--all` flag is set, then it will be all buildable directories | |
| 146 /// that exist. | |
| 147 /// | |
| 148 /// Otherwise, all arguments should be the names of directories to include. | |
| 149 /// | |
| 150 /// Throws an exception if the arguments are invalid. | |
| 151 void _parseBuildDirectories() { | |
| 152 if (commandOptions["all"]) { | |
| 153 if (commandOptions.rest.isNotEmpty) { | |
| 154 usageError( | |
| 155 'Build directory names are not allowed if "--all" is passed.'); | |
| 156 } | |
| 157 | |
| 158 // Include every build directory that exists in the package. | |
| 159 var allowed = _allowedBuildDirectories.where( | |
| 160 (d) => dirExists(path.join(entrypoint.root.dir, d))); | |
| 161 | |
| 162 if (allowed.isEmpty) { | |
| 163 var buildDirs = toSentence(ordered(_allowedBuildDirectories.map( | |
| 164 (name) => '"$name"'))); | |
| 165 dataError('There are no buildable directories.\n' | |
| 166 'The supported directories are $buildDirs.'); | |
| 167 } | |
| 168 | |
| 169 buildDirectories.addAll(allowed); | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 buildDirectories.addAll(commandOptions.rest); | |
| 174 | |
| 175 // If no directory were specified, default to "web". | |
| 176 if (buildDirectories.isEmpty) { | |
| 177 buildDirectories.add("web"); | |
| 178 } | |
| 179 | |
| 180 // Make sure the arguments are known directories. | |
| 181 var disallowed = buildDirectories.where( | |
| 182 (dir) => !_allowedBuildDirectories.contains(dir)); | |
| 183 if (disallowed.isNotEmpty) { | |
| 184 var dirs = pluralize("directory", disallowed.length, | |
| 185 plural: "directories"); | |
| 186 var names = toSentence(ordered(disallowed).map((name) => '"$name"')); | |
| 187 var allowed = toSentence(ordered(_allowedBuildDirectories.map( | |
| 188 (name) => '"$name"'))); | |
| 189 usageError('Unsupported build $dirs $names.\n' | |
| 190 'The allowed directories are $allowed.'); | |
| 191 } | |
| 192 | |
| 193 // Make sure all of the build directories exist. | |
| 194 var missing = buildDirectories.where( | |
| 195 (dir) => !dirExists(path.join(entrypoint.root.dir, dir))); | |
| 196 | |
| 197 if (missing.length == 1) { | |
| 198 dataError('Directory "${missing.single}" does not exist.'); | |
| 199 } else if (missing.isNotEmpty) { | |
| 200 var names = toSentence(ordered(missing).map((name) => '"$name"')); | |
| 201 dataError('Directories $names do not exist.'); | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 /// Writes [asset] to the appropriate build directory. | 122 /// Writes [asset] to the appropriate build directory. |
| 206 /// | 123 /// |
| 207 /// If [asset] is in the special "assets" directory, writes it to every | 124 /// If [asset] is in the special "assets" directory, writes it to every |
| 208 /// build directory. | 125 /// build directory. |
| 209 Future _writeAsset(Asset asset) { | 126 Future _writeAsset(Asset asset) { |
| 210 // In release mode, strip out .dart files since all relevant ones have been | 127 // In release mode, strip out .dart files since all relevant ones have been |
| 211 // compiled to JavaScript already. | 128 // compiled to JavaScript already. |
| 212 if (mode == BarbackMode.RELEASE && asset.id.extension == ".dart") { | 129 if (mode == BarbackMode.RELEASE && asset.id.extension == ".dart") { |
| 213 return new Future.value(); | 130 return new Future.value(); |
| 214 } | 131 } |
| 215 | 132 |
| 216 var destPath = _idtoPath(asset.id); | 133 var destPath = _idtoPath(asset.id); |
| 217 | 134 |
| 218 // If the asset is from a public directory, copy it into all of the | 135 // If the asset is from a public directory, copy it into all of the |
| 219 // top-level build directories. | 136 // top-level build directories. |
| 220 if (path.isWithin("assets", destPath) || | 137 if (path.isWithin("assets", destPath) || |
| 221 path.isWithin("packages", destPath)) { | 138 path.isWithin("packages", destPath)) { |
| 222 return Future.wait(buildDirectories.map((buildDir) => | 139 return Future.wait(sourceDirectories.map((buildDir) => |
| 223 _writeOutputFile(asset, path.join(buildDir, destPath)))); | 140 _writeOutputFile(asset, path.join(buildDir, destPath)))); |
| 224 } | 141 } |
| 225 | 142 |
| 226 return _writeOutputFile(asset, destPath); | 143 return _writeOutputFile(asset, destPath); |
| 227 } | 144 } |
| 228 | 145 |
| 229 /// Converts [id] to a relative path in the output directory for that asset. | 146 /// Converts [id] to a relative path in the output directory for that asset. |
| 230 /// | 147 /// |
| 231 /// This corresponds to the URL that could be used to request that asset from | 148 /// This corresponds to the URL that could be used to request that asset from |
| 232 /// pub serve. | 149 /// pub serve. |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 "end": { | 269 "end": { |
| 353 "line": entry.span.end.line, | 270 "line": entry.span.end.line, |
| 354 "column": entry.span.end.column | 271 "column": entry.span.end.column |
| 355 }, | 272 }, |
| 356 }; | 273 }; |
| 357 } | 274 } |
| 358 | 275 |
| 359 return data; | 276 return data; |
| 360 } | 277 } |
| 361 } | 278 } |
| OLD | NEW |