Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: pkg/polymer/lib/deploy.dart

Issue 23898009: Switch polymer's build.dart to use the new linter. This CL does the following (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: addressing john comments (part 2) - renamed files Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/polymer/lib/component_build.dart ('k') | pkg/polymer/lib/dwc.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /** 5 /**
6 * **Note**: If you already have a `build.dart` in your application, we
7 * recommend to use the `package:polymer/builder.dart` library instead.
8
6 * Temporary deploy command used to create a version of the app that can be 9 * Temporary deploy command used to create a version of the app that can be
7 * compiled with dart2js and deployed. Following pub layout conventions, this 10 * compiled with dart2js and deployed. Following pub layout conventions, this
8 * script will treat any HTML file under a package 'web/' and 'test/' 11 * script will treat any HTML file under a package 'web/' and 'test/'
9 * directories as entry points. 12 * directories as entry points.
10 * 13 *
11 * From an application package you can run deploy by creating a small program 14 * From an application package you can run deploy by creating a small program
12 * as follows: 15 * as follows:
13 * 16 *
14 * import "package:polymer/deploy.dart" as deploy; 17 * import "package:polymer/deploy.dart" as deploy;
15 * main() => deploy.main(); 18 * main() => deploy.main();
16 * 19 *
17 * This library should go away once `pub deploy` can be configured to run 20 * This library should go away once `pub deploy` can be configured to run
18 * barback transformers. 21 * barback transformers.
19 */ 22 */
20 library polymer.deploy; 23 library polymer.deploy;
21 24
22 import 'dart:async'; 25 import 'dart:async';
23 import 'dart:convert';
24 import 'dart:io'; 26 import 'dart:io';
25 27
26 import 'package:barback/barback.dart'; 28 import 'package:args/args.dart';
27 import 'package:path/path.dart' as path; 29 import 'package:path/path.dart' as path;
28 import 'package:polymer/src/transform.dart' show phases; 30 import 'package:polymer/src/barback_runner.dart';
29 import 'package:stack_trace/stack_trace.dart'; 31 import 'package:polymer/src/transform.dart';
30 import 'package:yaml/yaml.dart';
31 import 'package:args/args.dart';
32 32
33 main() { 33 main() {
34 var args = _parseArgs(new Options().arguments); 34 var args = _parseArgs(new Options().arguments);
35 if (args == null) return; 35 if (args == null) exit(1);
36 36
37 var test = args['test']; 37 var test = args['test'];
38 if (test != null) { 38 var outDir = args['out'];
39 _initForTest(test); 39 var options = (test == null)
40 } 40 ? new BarbackOptions(createDeployPhases(new TransformOptions()), outDir)
41 : _createTestOptions(test, outDir);
42 if (options == null) exit(1);
41 43
42 print('polymer/deploy.dart: creating a deploy target for "$_currentPackage"'); 44 print('polymer/deploy.dart: creating a deploy target for '
43 var outDir = args['out']; 45 '"${options.currentPackage}"');
44 _run(outDir, test != null).then( 46
45 (_) => print('Done! All files written to "$outDir"')); 47 runBarback(options)
48 .then((_) => print('Done! All files written to "$outDir"'))
49 .catchError(_reportErrorAndExit);
46 } 50 }
47 51
48 // TODO(jmesserly): the current deploy/barback architecture is very unfriendly 52 BarbackOptions _createTestOptions(String testFile, String outDir) {
49 // to deploying a single test. We need to fix it somehow but it isn't clear yet.
50 void _initForTest(String testFile) {
51 var testDir = path.normalize(path.dirname(testFile)); 53 var testDir = path.normalize(path.dirname(testFile));
52 54
53 // A test must be allowed to import things in the package. 55 // A test must be allowed to import things in the package.
54 // So we must find its package root, given the entry point. We can do this 56 // So we must find its package root, given the entry point. We can do this
55 // by walking up to find pubspec.yaml. 57 // by walking up to find pubspec.yaml.
56 var pubspecDir = _findDirWithFile(path.absolute(testDir), 'pubspec.yaml'); 58 var pubspecDir = _findDirWithFile(path.absolute(testDir), 'pubspec.yaml');
57 if (pubspecDir == null) { 59 if (pubspecDir == null) {
58 print('error: pubspec.yaml file not found, please run this script from ' 60 print('error: pubspec.yaml file not found, please run this script from '
59 'your package root directory or a subdirectory.'); 61 'your package root directory or a subdirectory.');
60 exit(1); 62 return null;
61 } 63 }
62 64
63 _currentPackage = '_test'; 65 var phases = createDeployPhases(new TransformOptions(
64 _packageDirs = {'_test' : pubspecDir}; 66 '_test', [path.relative(testFile, from: pubspecDir)]));
67 return new BarbackOptions(phases, outDir,
68 currentPackage: '_test',
69 packageDirs: {'_test' : pubspecDir},
70 transformTests: true);
65 } 71 }
66 72
67 String _findDirWithFile(String dir, String filename) { 73 String _findDirWithFile(String dir, String filename) {
68 while (!new File(path.join(dir, filename)).existsSync()) { 74 while (!new File(path.join(dir, filename)).existsSync()) {
69 var parentDir = path.dirname(dir); 75 var parentDir = path.dirname(dir);
70 // If we reached root and failed to find it, bail. 76 // If we reached root and failed to find it, bail.
71 if (parentDir == dir) return null; 77 if (parentDir == dir) return null;
72 dir = parentDir; 78 dir = parentDir;
73 } 79 }
74 return dir; 80 return dir;
75 } 81 }
76 82
77 /** 83 void _reportErrorAndExit(e) {
78 * API exposed for testing purposes. Runs this deploy command but prentend that 84 var trace = getAttachedStackTrace(e);
79 * the sources under [webDir] belong to package 'test'. 85 print('Uncaught error: $e');
80 */ 86 if (trace != null) print(trace);
81 Future runForTest(String webDir, String outDir) { 87 exit(1);
82 _currentPackage = 'test';
83
84 // associate package dirs with their location in the repo:
85 _packageDirs = {'test' : '.'};
86 _addPackages('..');
87 _addPackages('../third_party');
88 _addPackages('../../third_party/pkg');
89 return _run(webDir, outDir);
90 } 88 }
91 89
92 _addPackages(String dir) {
93 for (var packageDir in new Directory(dir).listSync().map((d) => d.path)) {
94 _packageDirs[path.basename(packageDir)] = packageDir;
95 }
96 }
97
98 Future _run(String outDir, bool includeTests) {
99 var barback = new Barback(new _PolymerDeployProvider());
100 _initializeBarback(barback, includeTests);
101 _attachListeners(barback);
102 return _emitAllFiles(barback, 'web', outDir).then(
103 (_) => includeTests ? _emitAllFiles(barback, 'test', outDir) : null);
104 }
105
106 /** Tell barback which transformers to use and which assets to process. */
107 void _initializeBarback(Barback barback, bool includeTests) {
108 var assets = [];
109 void addAssets(String package, String subDir) {
110 for (var filepath in _listDir(package, subDir)) {
111 assets.add(new AssetId(package, filepath));
112 }
113 }
114
115 for (var package in _packageDirs.keys) {
116 // Do not process packages like 'polymer' where there is nothing to do.
117 if (_ignoredPackages.contains(package)) continue;
118 barback.updateTransformers(package, phases);
119
120 // notify barback to process anything under 'lib' and 'asset'
121 addAssets(package, 'lib');
122 addAssets(package, 'asset');
123 }
124
125 // In case of the current package, include also 'web'.
126 addAssets(_currentPackage, 'web');
127 if (includeTests) addAssets(_currentPackage, 'test');
128
129 barback.updateSources(assets);
130 }
131
132 /** Return the relative path of each file under [subDir] in a [package]. */
133 Iterable<String> _listDir(String package, String subDir) {
134 var packageDir = _packageDirs[package];
135 if (packageDir == null) return const [];
136 var dir = new Directory(path.join(packageDir, subDir));
137 if (!dir.existsSync()) return const [];
138 return dir.listSync(recursive: true, followLinks: false)
139 .where((f) => f is File)
140 .map((f) => path.relative(f.path, from: packageDir));
141 }
142
143 /** Attach error listeners on [barback] so we can report errors. */
144 void _attachListeners(Barback barback) {
145 // Listen for errors and results
146 barback.errors.listen((e) {
147 var trace = getAttachedStackTrace(e);
148 if (trace != null) {
149 print(Trace.format(trace));
150 }
151 print('error running barback: $e');
152 exit(1);
153 });
154
155 barback.results.listen((result) {
156 if (!result.succeeded) {
157 print("build failed with errors: ${result.errors}");
158 exit(1);
159 }
160 });
161 }
162
163 /** Ensure [dirpath] exists. */
164 void _ensureDir(var dirpath) {
165 new Directory(dirpath).createSync(recursive: true);
166 }
167
168 /**
169 * Emits all outputs of [barback] and copies files that we didn't process (like
170 * polymer's libraries).
171 */
172 Future _emitAllFiles(Barback barback, String webDir, String outDir) {
173 return barback.getAllAssets().then((assets) {
174 // Copy all the assets we transformed
175 var futures = [];
176 for (var asset in assets) {
177 var id = asset.id;
178 var filepath;
179 if (id.package == _currentPackage && id.path.startsWith('$webDir/')) {
180 filepath = path.join(outDir, id.path);
181 } else if (id.path.startsWith('lib/')) {
182 filepath = path.join(outDir, webDir, 'packages', id.package,
183 id.path.substring(4));
184 } else {
185 // TODO(sigmund): do something about other assets?
186 continue;
187 }
188
189 _ensureDir(path.dirname(filepath));
190 var writer = new File(filepath).openWrite();
191 futures.add(writer.addStream(asset.read()).then((_) => writer.close()));
192 }
193 return Future.wait(futures);
194 }).then((_) {
195 // Copy also all the files we didn't process
196 var futures = [];
197 for (var package in _ignoredPackages) {
198 for (var relpath in _listDir(package, 'lib')) {
199 var inpath = path.join(_packageDirs[package], relpath);
200 var outpath = path.join(outDir, webDir, 'packages', package,
201 relpath.substring(4));
202 _ensureDir(path.dirname(outpath));
203
204 var writer = new File(outpath).openWrite();
205 futures.add(writer.addStream(new File(inpath).openRead())
206 .then((_) => writer.close()));
207 }
208 }
209 return Future.wait(futures);
210 });
211 }
212
213 /** A simple provider that reads files directly from the pub cache. */
214 class _PolymerDeployProvider implements PackageProvider {
215
216 Iterable<String> get packages => _packageDirs.keys;
217 _PolymerDeployProvider();
218
219 Future<Asset> getAsset(AssetId id) =>
220 new Future.value(new Asset.fromPath(id, path.join(
221 _packageDirs[id.package],
222 // Assets always use the posix style paths
223 path.joinAll(path.posix.split(id.path)))));
224 }
225
226
227 /** The current package extracted from the pubspec.yaml file. */
228 String _currentPackage = () {
229 var pubspec = new File('pubspec.yaml');
230 if (!pubspec.existsSync()) {
231 print('error: pubspec.yaml file not found, please run this script from '
232 'your package root directory.');
233 return null;
234 }
235 return loadYaml(pubspec.readAsStringSync())['name'];
236 }();
237
238 /**
239 * Maps package names to the path in the file system where to find the sources
240 * of such package. This map will contain an entry for the current package and
241 * everything it depends on (extracted via `pub list-pacakge-dirs`).
242 */
243 Map<String, String> _packageDirs = () {
244 var pub = path.join(path.dirname(new Options().executable),
245 Platform.isWindows ? 'pub.bat' : 'pub');
246 var result = Process.runSync(pub, ['list-package-dirs']);
247 if (result.exitCode != 0) {
248 print("unexpected error invoking 'pub':");
249 print(result.stdout);
250 print(result.stderr);
251 exit(result.exitCode);
252 }
253 var map = JSON.decode(result.stdout)["packages"];
254 map.forEach((k, v) { map[k] = path.dirname(v); });
255 map[_currentPackage] = '.';
256 return map;
257 }();
258
259 /**
260 * Internal packages used by polymer which we can copy directly to the output
261 * folder without having to process them with barback.
262 */
263 // TODO(sigmund): consider computing this list by recursively parsing
264 // pubspec.yaml files in the [_packageDirs].
265 final Set<String> _ignoredPackages =
266 (const [ 'analyzer_experimental', 'args', 'barback', 'browser', 'csslib',
267 'custom_element', 'fancy_syntax', 'html5lib', 'html_import', 'js',
268 'logging', 'mdv', 'meta', 'mutation_observer', 'observe', 'path',
269 'polymer', 'polymer_expressions', 'serialization', 'shadow_dom',
270 'source_maps', 'stack_trace', 'unittest',
271 'unmodifiable_collection', 'yaml'
272 ]).toSet();
273
274 ArgResults _parseArgs(arguments) { 90 ArgResults _parseArgs(arguments) {
275 var parser = new ArgParser() 91 var parser = new ArgParser()
276 ..addFlag('help', abbr: 'h', help: 'Displays this help message.', 92 ..addFlag('help', abbr: 'h', help: 'Displays this help message.',
277 defaultsTo: false, negatable: false) 93 defaultsTo: false, negatable: false)
278 ..addOption('out', abbr: 'o', help: 'Directory where to generated files.', 94 ..addOption('out', abbr: 'o', help: 'Directory to generate files into.',
279 defaultsTo: 'out') 95 defaultsTo: 'out')
280 ..addOption('test', help: 'Deploy the test at the given path.\n' 96 ..addOption('test', help: 'Deploy the test at the given path.\n'
281 'Note: currently this will deploy all tests in its directory,\n' 97 'Note: currently this will deploy all tests in its directory,\n'
282 'but it will eventually deploy only the specified test.'); 98 'but it will eventually deploy only the specified test.');
283 try { 99 try {
284 var results = parser.parse(arguments); 100 var results = parser.parse(arguments);
285 if (results['help']) { 101 if (results['help']) {
286 _showUsage(parser); 102 _showUsage(parser);
287 return null; 103 return null;
288 } 104 }
289 return results; 105 return results;
290 } on FormatException catch (e) { 106 } on FormatException catch (e) {
291 print(e.message); 107 print(e.message);
292 _showUsage(parser); 108 _showUsage(parser);
293 return null; 109 return null;
294 } 110 }
295 } 111 }
296 112
297 _showUsage(parser) { 113 _showUsage(parser) {
298 print('Usage: dart package:polymer/deploy.dart [options]'); 114 print('Usage: dart --package-root=packages/ '
115 'package:polymer/deploy.dart [options]');
299 print(parser.getUsage()); 116 print(parser.getUsage());
300 } 117 }
OLDNEW
« no previous file with comments | « pkg/polymer/lib/component_build.dart ('k') | pkg/polymer/lib/dwc.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698