OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library command_deploy; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:math' as math; | |
9 | |
10 import 'package:analyzer_experimental/analyzer.dart'; | |
11 import 'package:pathos/path.dart' as path; | |
12 | |
13 import 'command.dart'; | |
14 import 'dart.dart' as dart; | |
15 import 'io.dart'; | |
16 import 'log.dart' as log; | |
17 import 'utils.dart'; | |
18 | |
19 final _arrow = getSpecial('\u2192', '=>'); | |
20 | |
21 /// 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 "
| |
22 class DeployCommand extends PubCommand { | |
23 final description = "Copy and compile all Dart entrypoints in the 'web' " | |
24 "directory."; | |
25 final usage = "pub deploy [options]"; | |
26 final aliases = const ["settle-up"]; | |
27 | |
28 // TODO(nweiz): make these configurable. | |
29 /// The path to the source directory of the deployment. | |
30 String get source => path.join(entrypoint.root.dir, 'web'); | |
31 | |
32 /// The path to the target directory of the deployment. | |
33 String get target => path.join(entrypoint.root.dir, 'deploy'); | |
34 | |
35 /// The set of Dart entrypoints in [source] that should be compiled to [out]. | |
36 final _entrypoints = new List<String>(); | |
37 | |
38 var _maxVerbLength; | |
39 var _maxSourceLength; | |
40 | |
41 Future onRun() { | |
42 if (!dirExists(source)) { | |
43 throw new ApplicationException("There is no '$source' directory."); | |
44 } | |
45 | |
46 return entrypoint.packageFiles(beneath: source).then((files) { | |
47 log.message("Finding entrypoints..."); | |
48 _findEntrypoints(files); | |
49 _computeLogSize(); | |
50 | |
51 cleanDir(target); | |
52 _logAction("Copying", "${path.relative(source)}/", | |
53 "${path.relative(target)}/"); | |
54 copyFiles(files.where((file) => path.extension(file) != '.dart'), | |
55 source, target); | |
56 | |
57 return Future.forEach(_entrypoints, (sourceFile) { | |
58 var targetFile = | |
59 path.join(target, path.relative(sourceFile, from: source)); | |
60 var relativeTargetFile = path.relative(targetFile); | |
61 var relativeSourceFile = path.relative(sourceFile); | |
62 | |
63 ensureDir(path.dirname(targetFile)); | |
64 _logAction("Compiling", relativeSourceFile, "$relativeTargetFile.js"); | |
65 // TODO(nweiz): print dart2js errors/warnings in red. | |
66 return dart.compile(sourceFile, packageRoot: entrypoint.packagesDir) | |
67 .then((js) { | |
68 writeTextFile("$targetFile.js", js, dontLogContents: true); | |
69 _logAction("Compiling", relativeSourceFile, "$relativeTargetFile"); | |
70 return dart.compile(sourceFile, | |
71 packageRoot: entrypoint.packagesDir, toDart: true); | |
72 }).then((dart) { | |
73 writeTextFile(targetFile, dart, dontLogContents: true); | |
74 // TODO(nweiz): we should put dart.js files next to any HTML file | |
75 // rather than any entrypoint. An HTML file could import an entrypoint | |
76 // that's not adjacent. | |
77 _maybeAddDartJs(path.dirname(targetFile)); | |
78 }); | |
79 }); | |
80 }); | |
81 } | |
82 | |
83 /// Populates [_entrypoints] with all of the Dart entrypoints in [files]. | |
84 /// [files] should be a list of paths in [source]. | |
85 void _findEntrypoints(List<String> files) { | |
86 for (var file in files) { | |
87 if (path.extension(file) != '.dart') continue; | |
88 try { | |
89 if (!dart.isEntrypoint(parseDartFile(file))) continue; | |
90 } on FormatException catch (e) { | |
91 log.warning(e.message); | |
92 continue; | |
93 } | |
94 _entrypoints.add(file); | |
95 } | |
96 // Sort to ensure a deterministic order of compilation and output. | |
97 _entrypoints.sort(); | |
98 } | |
99 | |
100 /// Computes the maximum widths of words that will be used in log output for | |
101 /// 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.
| |
102 void _computeLogSize() { | |
103 _maxVerbLength = ["Copying", "Compiling"] | |
104 .map((verb) => verb.length).reduce(math.max); | |
105 var sourceLengths = new List.from( | |
106 _entrypoints.map((file) => path.relative(file).length)) | |
107 ..add("${path.relative(source)}/".length); | |
108 if (_shouldAddDartJs) sourceLengths.add("package:browser/dart.js".length); | |
109 _maxSourceLength = sourceLengths.reduce(math.max); | |
110 } | |
111 | |
112 /// Log a deployment action. | |
113 void _logAction(String verb, String source, String target) { | |
114 verb = padRight(verb, _maxVerbLength); | |
115 source = padRight(source, _maxSourceLength); | |
116 log.message("$verb $source $_arrow $target"); | |
117 } | |
118 | |
119 // TODO(nweiz): do something more principled when issue 6101 is fixed. | |
120 /// If this package depends non-transitively on the `browser` package, this | |
121 /// ensures that the `dart.js` file is copied into [directory], under | |
122 /// `packages/browser/`. | |
123 void _maybeAddDartJs(String directory) { | |
124 var jsPath = path.join(directory, 'packages', 'browser', 'dart.js'); | |
125 // TODO(nweiz): warn if they don't depend on browser? | |
126 if (!_shouldAddDartJs || fileExists(jsPath)) return; | |
127 | |
128 _logAction("Copying", "package:browser/dart.js", path.relative(jsPath)); | |
129 ensureDir(path.dirname(jsPath)); | |
130 copyFile(path.join(entrypoint.packagesDir, 'browser', 'dart.js'), jsPath); | |
131 } | |
132 | |
133 /// Whether we should copy the browser package's dart.js file into the | |
134 /// deployed app. | |
135 bool get _shouldAddDartJs { | |
136 return !_entrypoints.isEmpty && | |
137 entrypoint.root.dependencies.any((dep) => | |
138 dep.name == 'browser' && dep.source.name == 'hosted'); | |
139 } | |
140 } | |
OLD | NEW |