OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.executable; | 5 library pub.executable; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'package:barback/barback.dart'; | 10 import 'package:barback/barback.dart'; |
11 import 'package:path/path.dart' as p; | 11 import 'package:path/path.dart' as p; |
12 import 'package:stack_trace/stack_trace.dart'; | 12 import 'package:stack_trace/stack_trace.dart'; |
13 | 13 |
14 import 'barback/asset_environment.dart'; | 14 import 'barback/asset_environment.dart'; |
15 import 'entrypoint.dart'; | 15 import 'entrypoint.dart'; |
16 import 'exit_codes.dart' as exit_codes; | 16 import 'exit_codes.dart' as exit_codes; |
17 import 'io.dart'; | 17 import 'io.dart'; |
18 import 'log.dart' as log; | 18 import 'log.dart' as log; |
19 import 'sdk.dart' as sdk; | |
20 import 'utils.dart'; | 19 import 'utils.dart'; |
21 | 20 |
22 /// Runs [executable] from [package] reachable from [entrypoint]. | 21 /// Runs [executable] from [package] reachable from [entrypoint]. |
23 /// | 22 /// |
24 /// The executable string is a relative Dart file path using native path | 23 /// The executable string is a relative Dart file path using native path |
25 /// separators without a trailing ".dart" extension. It is contained within | 24 /// separators without a trailing ".dart" extension. It is contained within |
26 /// [package], which should either be the entrypoint package or an immediate | 25 /// [package], which should either be the entrypoint package or an immediate |
27 /// dependency of it. | 26 /// dependency of it. |
28 /// | 27 /// |
29 /// Arguments from [args] will be passed to the spawned Dart application. | 28 /// Arguments from [args] will be passed to the spawned Dart application. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 123 |
125 log.error("$message."); | 124 log.error("$message."); |
126 log.fine(new Chain.forTrace(stackTrace)); | 125 log.fine(new Chain.forTrace(stackTrace)); |
127 return exit_codes.NO_INPUT; | 126 return exit_codes.NO_INPUT; |
128 }); | 127 }); |
129 } | 128 } |
130 | 129 |
131 /// Runs the snapshot at [path] with [args] and hooks its stdout, stderr, and | 130 /// Runs the snapshot at [path] with [args] and hooks its stdout, stderr, and |
132 /// sdtin to this process's. | 131 /// sdtin to this process's. |
133 /// | 132 /// |
| 133 /// If [recompile] is passed, it's called if the snapshot is out-of-date. It's |
| 134 /// expected to regenerate a snapshot at [path], after which the snapshot will |
| 135 /// be re-run. It may return a Future. |
| 136 /// |
| 137 /// If [checked] is set, runs the snapshot in checked mode. |
| 138 /// |
134 /// Returns the snapshot's exit code. | 139 /// Returns the snapshot's exit code. |
135 /// | 140 /// |
136 /// This doesn't do any validation of the snapshot's SDK version. | 141 /// This doesn't do any validation of the snapshot's SDK version. |
137 Future<int> runSnapshot(String path, Iterable<String> args) async { | 142 Future<int> runSnapshot(String path, Iterable<String> args, {recompile(), |
| 143 bool checked: false}) async { |
138 var vmArgs = [path]..addAll(args); | 144 var vmArgs = [path]..addAll(args); |
139 | 145 |
140 var process = await Process.start(Platform.executable, vmArgs); | 146 // TODO(nweiz): pass a flag to silence the "Wrong full snapshot version" |
141 // Note: we're not using process.std___.pipe(std___) here because | 147 // message when issue 20784 is fixed. |
142 // that prevents pub from also writing to the output streams. | 148 if (checked) vmArgs.insert(0, "--checked"); |
143 process.stderr.listen(stderr.add); | |
144 process.stdout.listen(stdout.add); | |
145 stdin.listen(process.stdin.add); | |
146 | 149 |
147 return process.exitCode; | 150 // We need to split stdin so that we can send the same input both to the |
| 151 // first and second process, if we start more than one. |
| 152 var stdin1; |
| 153 var stdin2; |
| 154 if (recompile == null) { |
| 155 stdin1 = stdin; |
| 156 } else { |
| 157 var pair = tee(stdin); |
| 158 stdin1 = pair.first; |
| 159 stdin2 = pair.last; |
| 160 } |
| 161 |
| 162 runProcess(input) async { |
| 163 var process = await Process.start(Platform.executable, vmArgs); |
| 164 |
| 165 // Note: we're not using process.std___.pipe(std___) here because |
| 166 // that prevents pub from also writing to the output streams. |
| 167 process.stderr.listen(stderr.add); |
| 168 process.stdout.listen(stdout.add); |
| 169 input.listen(process.stdin.add); |
| 170 |
| 171 return process.exitCode; |
| 172 } |
| 173 |
| 174 var exitCode = await runProcess(stdin1); |
| 175 if (recompile == null || exitCode != 255) return exitCode; |
| 176 |
| 177 // Exit code 255 indicates that the snapshot version was out-of-date. If we |
| 178 // can recompile, do so. |
| 179 await recompile(); |
| 180 return runProcess(stdin2); |
148 } | 181 } |
149 | 182 |
150 /// Runs the executable snapshot at [snapshotPath]. | 183 /// Runs the executable snapshot at [snapshotPath]. |
151 Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath, | 184 Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath, |
152 List<String> args) async { | 185 List<String> args) { |
153 // If the snapshot was compiled with a different SDK version, we need to | 186 return runSnapshot(snapshotPath, args, checked: true, recompile: () { |
154 // recompile it. | 187 log.fine("Precompiled executable is out of date."); |
155 var sdkVersionPath = p.join(".pub", "bin", "sdk-version"); | 188 return entrypoint.precompileExecutables(); |
156 if (!fileExists(sdkVersionPath) || | 189 }); |
157 readTextFile(sdkVersionPath) != "${sdk.version}\n") { | |
158 log.fine("Precompiled executables are out of date."); | |
159 await entrypoint.precompileExecutables(); | |
160 } | |
161 | |
162 // TODO(rnystrom): Use cascade here when async_await compiler supports it. | |
163 // See: https://github.com/dart-lang/async_await/issues/26. | |
164 var vmArgs = ["--checked", snapshotPath]; | |
165 vmArgs.addAll(args); | |
166 | |
167 var process = await Process.start(Platform.executable, vmArgs); | |
168 // Note: we're not using process.std___.pipe(std___) here because | |
169 // that prevents pub from also writing to the output streams. | |
170 process.stderr.listen(stderr.add); | |
171 process.stdout.listen(stdout.add); | |
172 stdin.listen(process.stdin.add); | |
173 | |
174 return process.exitCode; | |
175 } | 190 } |
OLD | NEW |