| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|  | 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. | 
|  | 4 | 
|  | 5 /** | 
|  | 6  * Common logic to make it easy to run the polymer linter and deploy tool. | 
|  | 7  * | 
|  | 8  * The functions in this library are designed to make it easier to create | 
|  | 9  * `build.dart` files. A `build.dart` file is a Dart script that can be invoked | 
|  | 10  * from the command line, but that can also invoked automatically by the Dart | 
|  | 11  * Editor whenever a file in your project changes or when selecting some menu | 
|  | 12  * options, such as 'Reanalyze Sources'. | 
|  | 13  * | 
|  | 14  * To work correctly, place the `build.dart` in the root of your project (where | 
|  | 15  * pubspec.yaml lives). The file must be named exactly `build.dart`. | 
|  | 16  * | 
|  | 17  * It's quite likely that in the near future `build.dart` will be replaced with | 
|  | 18  * something else.  For example, `pub deploy` will deal with deploying | 
|  | 19  * applications automatically, and the Dart Editor might provide other | 
|  | 20  * mechanisms to hook linters. | 
|  | 21  * | 
|  | 22  * There are three important functions exposed by this library [build], [lint], | 
|  | 23  * and [deploy]. The following examples show common uses of these functions when | 
|  | 24  * writing a `build.dart` file. | 
|  | 25  * | 
|  | 26  * **Example 1**: Uses build.dart to run the linter tool. | 
|  | 27  * | 
|  | 28  *     import 'dart:io'; | 
|  | 29  *     import 'package:polymer/builder.dart'; | 
|  | 30  * | 
|  | 31  *     main() { | 
|  | 32  *        lint(); | 
|  | 33  *     } | 
|  | 34  * | 
|  | 35  * **Example 2**: Runs the linter and creates a deployable version of the app | 
|  | 36  * every time. | 
|  | 37  * | 
|  | 38  *     import 'dart:io'; | 
|  | 39  *     import 'package:polymer/builder.dart'; | 
|  | 40  * | 
|  | 41  *     main() { | 
|  | 42  *        lint().then(() => deploy()); | 
|  | 43  *     } | 
|  | 44  * | 
|  | 45  * **Example 3**: Runs the linter, but conditionally does the deploy step. See | 
|  | 46  * [parseOptions] for a description of options parsed automatically by this | 
|  | 47  * helper library. | 
|  | 48  * | 
|  | 49  *     import 'dart:io'; | 
|  | 50  *     import 'package:polymer/builder.dart'; | 
|  | 51  * | 
|  | 52  *     main() { | 
|  | 53  *        var options = parseOptions(); | 
|  | 54  *        lint().then(() { | 
|  | 55  *          if (options.forceDeploy) deploy(); | 
|  | 56  *        }); | 
|  | 57  *     } | 
|  | 58  * | 
|  | 59  * **Example 4**: Same as above, but uses [build] (which internally calls [lint] | 
|  | 60  * and [deploy]). | 
|  | 61  * | 
|  | 62  *     import 'dart:io'; | 
|  | 63  *     import 'package:polymer/builder.dart'; | 
|  | 64  * | 
|  | 65  *     main() { | 
|  | 66  *        build(); | 
|  | 67  *     } | 
|  | 68  * | 
|  | 69  * **Example 5**: Like the previous example, but indicates to the linter and | 
|  | 70  * deploy tool which files are actually used as entry point files. See the | 
|  | 71  * documentation of [build] below for more details. | 
|  | 72  * | 
|  | 73  *     import 'dart:io'; | 
|  | 74  *     import 'package:polymer/builder.dart'; | 
|  | 75  * | 
|  | 76  *     main() { | 
|  | 77  *        build(entryPoints: ['web/index.html']); | 
|  | 78  *     } | 
|  | 79  */ | 
|  | 80 library polymer.builder; | 
|  | 81 | 
|  | 82 import 'dart:async'; | 
|  | 83 import 'dart:io'; | 
|  | 84 | 
|  | 85 import 'package:args/args.dart'; | 
|  | 86 | 
|  | 87 import 'src/barback_runner.dart'; | 
|  | 88 import 'src/linter.dart'; | 
|  | 89 import 'src/transform.dart'; | 
|  | 90 | 
|  | 91 | 
|  | 92 /** | 
|  | 93  * Runs the polymer linter on any relevant file in your package, such as any | 
|  | 94  * .html file under 'lib/', 'asset/', and 'web/'. And, if requested, creates a | 
|  | 95  * directory suitable for deploying a Polymer application to a server. | 
|  | 96  * | 
|  | 97  * The [entryPoints] list contains files under web/ that should be treated as | 
|  | 98  * entry points. Each entry on this list is a relative path from the package | 
|  | 99  * root (for example 'web/index.html'). If null, all files under 'web/' are | 
|  | 100  * treated as possible entry points. | 
|  | 101  * | 
|  | 102  * Options are read from the command line arguments, but you can override them | 
|  | 103  * passing the [options] argument. The deploy operation is run only when the | 
|  | 104  * command-line argument `--deploy` is present, or equivalently when | 
|  | 105  * `options.forceDeploy` is true. | 
|  | 106  * | 
|  | 107  * The linter and deploy steps needs to know the name of the [currentPackage] | 
|  | 108  * and the location where to find the code for any package it depends on | 
|  | 109  * ([packageDirs]). This is inferred automatically, but can be overriden if | 
|  | 110  * those arguments are provided. | 
|  | 111  */ | 
|  | 112 Future build({List<String> entryPoints, CommandLineOptions options, | 
|  | 113     String currentPackage, Map<String, String> packageDirs}) { | 
|  | 114   if (options == null) options = _options; | 
|  | 115   return lint(entryPoints: entryPoints, options: options, | 
|  | 116       currentPackage: currentPackage, packageDirs: packageDirs).then((res) { | 
|  | 117     if (options.forceDeploy) { | 
|  | 118       return deploy(entryPoints: entryPoints, options: options, | 
|  | 119           currentPackage: currentPackage, packageDirs: packageDirs); | 
|  | 120     } | 
|  | 121   }); | 
|  | 122 } | 
|  | 123 | 
|  | 124 | 
|  | 125 /** | 
|  | 126  * Runs the polymer linter on any relevant file in your package, | 
|  | 127  * such as any .html file under 'lib/', 'asset/', and 'web/'. | 
|  | 128  * | 
|  | 129  * The [entryPoints] list contains files under web/ that should be treated as | 
|  | 130  * entry points. Each entry on this list is a relative path from the package | 
|  | 131  * root (for example 'web/index.html'). If null, all files under 'web/' are | 
|  | 132  * treated as possible entry points. | 
|  | 133  * | 
|  | 134  * Options are read from the command line arguments, but you can override them | 
|  | 135  * passing the [options] argument. | 
|  | 136  * | 
|  | 137  * The linter needs to know the name of the [currentPackage] and the location | 
|  | 138  * where to find the code for any package it depends on ([packageDirs]). This is | 
|  | 139  * inferred automatically, but can be overriden if those arguments are provided. | 
|  | 140  */ | 
|  | 141 Future lint({List<String> entryPoints, CommandLineOptions options, | 
|  | 142     String currentPackage, Map<String, String> packageDirs}) { | 
|  | 143   if (options == null) options = _options; | 
|  | 144   if (currentPackage == null) currentPackage = readCurrentPackageFromPubspec(); | 
|  | 145   var linterOptions = new TransformOptions(currentPackage, entryPoints); | 
|  | 146   var formatter = options.machineFormat ? jsonFormatter : consoleFormatter; | 
|  | 147   var linter = new Linter(linterOptions, formatter); | 
|  | 148   return runBarback(new BarbackOptions([[linter]], null, | 
|  | 149       currentPackage: currentPackage, packageDirs: packageDirs)).then((assets) { | 
|  | 150     var messages = {}; | 
|  | 151     var futures = []; | 
|  | 152     for (var asset in assets) { | 
|  | 153       var id = asset.id; | 
|  | 154       if (id.package == currentPackage && id.path.endsWith('.messages')) { | 
|  | 155         futures.add(asset.readAsString().then((content) { | 
|  | 156           if (content.isEmpty) return; | 
|  | 157           messages[id] = content; | 
|  | 158         })); | 
|  | 159       } | 
|  | 160     } | 
|  | 161 | 
|  | 162     return Future.wait(futures).then((_) { | 
|  | 163       // Print messages sorting by package and filepath. | 
|  | 164       var orderedKeys = messages.keys.toList(); | 
|  | 165       orderedKeys.sort((a, b) { | 
|  | 166         int packageCompare = a.package.compareTo(b.package); | 
|  | 167         if (packageCompare != 0) return packageCompare; | 
|  | 168         return a.path.compareTo(b.path); | 
|  | 169       }); | 
|  | 170 | 
|  | 171       for (var key in orderedKeys) { | 
|  | 172         print(messages[key]); | 
|  | 173       } | 
|  | 174     }); | 
|  | 175   }); | 
|  | 176 } | 
|  | 177 | 
|  | 178 /** | 
|  | 179  * Creates a directory suitable for deploying a Polymer application to a server. | 
|  | 180  * | 
|  | 181  * **Note**: this function will be replaced in the future by the `pub deploy` | 
|  | 182  * command. | 
|  | 183  * | 
|  | 184  * The [entryPoints] list contains files under web/ that should be treated as | 
|  | 185  * entry points. Each entry on this list is a relative path from the package | 
|  | 186  * root (for example 'web/index.html'). If null, all files under 'web/' are | 
|  | 187  * treated as possible entry points. | 
|  | 188  * | 
|  | 189  * Options are read from the command line arguments, but you can override them | 
|  | 190  * passing the [options] list. | 
|  | 191  * | 
|  | 192  * The deploy step needs to know the name of the [currentPackage] and the | 
|  | 193  * location where to find the code for any package it depends on | 
|  | 194  * ([packageDirs]). This is inferred automatically, but can be overriden if | 
|  | 195  * those arguments are provided. | 
|  | 196  */ | 
|  | 197 Future deploy({List<String> entryPoints, CommandLineOptions options, | 
|  | 198     String currentPackage, Map<String, String> packageDirs}) { | 
|  | 199   if (options == null) options = _options; | 
|  | 200   if (currentPackage == null) currentPackage = readCurrentPackageFromPubspec(); | 
|  | 201   var barbackOptions = new BarbackOptions( | 
|  | 202       createDeployPhases(new TransformOptions(currentPackage, entryPoints)), | 
|  | 203       options.outDir, currentPackage: currentPackage, | 
|  | 204       packageDirs: packageDirs); | 
|  | 205   return runBarback(barbackOptions) | 
|  | 206       .then((_) => print('Done! All files written to "${options.outDir}"')); | 
|  | 207 } | 
|  | 208 | 
|  | 209 | 
|  | 210 /** | 
|  | 211  * Options that may be used either in build.dart or by the linter and deploy | 
|  | 212  * tools. | 
|  | 213  */ | 
|  | 214 class CommandLineOptions { | 
|  | 215   /** Files marked as changed. */ | 
|  | 216   final List<String> changedFiles; | 
|  | 217 | 
|  | 218   /** Files marked as removed. */ | 
|  | 219   final List<String> removedFiles; | 
|  | 220 | 
|  | 221   /** Whether to clean intermediate artifacts, if any. */ | 
|  | 222   final bool clean; | 
|  | 223 | 
|  | 224   /** Whether to do a full build (as if all files have changed). */ | 
|  | 225   final bool full; | 
|  | 226 | 
|  | 227   /** Whether to print results using a machine parseable format. */ | 
|  | 228   final bool machineFormat; | 
|  | 229 | 
|  | 230   /** Whether the force deploy option was passed in the command line. */ | 
|  | 231   final bool forceDeploy; | 
|  | 232 | 
|  | 233   /** Location where to generate output files. */ | 
|  | 234   final String outDir; | 
|  | 235 | 
|  | 236   CommandLineOptions(this.changedFiles, this.removedFiles, this.clean, | 
|  | 237       this.full, this.machineFormat, this.forceDeploy, this.outDir); | 
|  | 238 } | 
|  | 239 | 
|  | 240 /** Options parsed directly from the command line arguments. */ | 
|  | 241 CommandLineOptions _options = parseOptions(); | 
|  | 242 | 
|  | 243 /** | 
|  | 244  * Parse command-line arguments and return a [CommandLineOptions] object. The | 
|  | 245  * following flags are parsed by this method. | 
|  | 246  * | 
|  | 247  *   * `--changed file-path`: notify of a file change. | 
|  | 248  *   * `--removed file-path`: notify that a file was removed. | 
|  | 249  *   * `--clean`: remove temporary artifacts (if any) | 
|  | 250  *   * `--full`: build everything, similar to marking every file as changed | 
|  | 251  *   * `--machine`: produce output that can be parsed by tools, such as the Dart | 
|  | 252  *     Editor. | 
|  | 253  *   * `--deploy`: force deploy. | 
|  | 254  *   * `--help`: print documentation for each option and exit. | 
|  | 255  * | 
|  | 256  * Currently not all the flags are used by [lint] or [deploy] above, but they | 
|  | 257  * are available so they can be used from your `build.dart`. For instance, see | 
|  | 258  * the top-level library documentation for an example that uses the force-deploy | 
|  | 259  * option to conditionally call [deploy]. | 
|  | 260  * | 
|  | 261  * If this documentation becomes out of date, the best way to discover which | 
|  | 262  * flags are supported is to invoke this function from your build.dart, and run | 
|  | 263  * it with the `--help` command-line flag. | 
|  | 264  */ | 
|  | 265 CommandLineOptions parseOptions([List<String> args]) { | 
|  | 266   var parser = new ArgParser() | 
|  | 267     ..addOption('changed', help: 'The file has changed since the last build.', | 
|  | 268         allowMultiple: true) | 
|  | 269     ..addOption('removed', help: 'The file was removed since the last build.', | 
|  | 270         allowMultiple: true) | 
|  | 271     ..addFlag('clean', negatable: false, | 
|  | 272         help: 'Remove any build artifacts (if any).') | 
|  | 273     ..addFlag('full', negatable: false, help: 'perform a full build') | 
|  | 274     ..addFlag('machine', negatable: false, | 
|  | 275         help: 'Produce warnings in a machine parseable format.') | 
|  | 276     ..addFlag('deploy', negatable: false, | 
|  | 277         help: 'Whether to force deploying.') | 
|  | 278     ..addOption('out', abbr: 'o', help: 'Directory to generate files into.', | 
|  | 279         defaultsTo: 'out') | 
|  | 280     ..addFlag('help', abbr: 'h', | 
|  | 281         negatable: false, help: 'Displays this help and exit.'); | 
|  | 282   var res = parser.parse(args == null ? new Options().arguments : args); | 
|  | 283   if (res['help']) { | 
|  | 284     print('A build script that invokes the polymer linter and deploy tools.'); | 
|  | 285     print('Usage: dart build.dart [options]'); | 
|  | 286     print('\nThese are valid options expected by build.dart:'); | 
|  | 287     print(parser.getUsage()); | 
|  | 288     exit(0); | 
|  | 289   } | 
|  | 290   return new CommandLineOptions(res['changed'], res['removed'], res['clean'], | 
|  | 291       res['full'], res['machine'], res['deploy'], res['out']); | 
|  | 292 } | 
| OLD | NEW | 
|---|