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 'cr_lf_remover.dart'; |
15 import 'entrypoint.dart'; | 16 import 'entrypoint.dart'; |
16 import 'exit_codes.dart' as exit_codes; | 17 import 'exit_codes.dart' as exit_codes; |
17 import 'io.dart'; | 18 import 'io.dart'; |
18 import 'log.dart' as log; | 19 import 'log.dart' as log; |
19 import 'utils.dart'; | 20 import 'utils.dart'; |
20 | 21 |
21 /// All signals that can be caught by a Dart process. | 22 /// All signals that can be caught by a Dart process. |
22 /// | 23 /// |
23 /// This intentionally omits SIGINT. SIGINT usually comes from a user pressing | 24 /// This intentionally omits SIGINT. SIGINT usually comes from a user pressing |
24 /// Control+C on the terminal, and the terminal automatically passes the signal | 25 /// Control+C on the terminal, and the terminal automatically passes the signal |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 | 121 |
121 vmArgs.add(executableUrl.toString()); | 122 vmArgs.add(executableUrl.toString()); |
122 vmArgs.addAll(args); | 123 vmArgs.addAll(args); |
123 | 124 |
124 var process = await Process.start(Platform.executable, vmArgs); | 125 var process = await Process.start(Platform.executable, vmArgs); |
125 | 126 |
126 _forwardSignals(process); | 127 _forwardSignals(process); |
127 | 128 |
128 // Note: we're not using process.std___.pipe(std___) here because | 129 // Note: we're not using process.std___.pipe(std___) here because |
129 // that prevents pub from also writing to the output streams. | 130 // that prevents pub from also writing to the output streams. |
130 process.stderr.listen(stderr.add); | 131 _forwardOutput(process.stderr, stderr); |
131 process.stdout.listen(stdout.add); | 132 _forwardOutput(process.stdout, stdout); |
132 stdin.listen(process.stdin.add); | 133 stdin.listen(process.stdin.add); |
133 | 134 |
134 return process.exitCode; | 135 return process.exitCode; |
135 } | 136 } |
136 | 137 |
137 /// Returns the URL the VM should use to load the executable at [path]. | 138 /// Returns the URL the VM should use to load the executable at [path]. |
138 /// | 139 /// |
139 /// [path] must be relative to the root of [package]. If [path] doesn't exist, | 140 /// [path] must be relative to the root of [package]. If [path] doesn't exist, |
140 /// returns `null`. | 141 /// returns `null`. |
141 Future<Uri> _executableUrl(Entrypoint entrypoint, String package, String path, | 142 Future<Uri> _executableUrl(Entrypoint entrypoint, String package, String path, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 stdin2 = pair.last; | 225 stdin2 = pair.last; |
225 } | 226 } |
226 | 227 |
227 runProcess(input) async { | 228 runProcess(input) async { |
228 var process = await Process.start(Platform.executable, vmArgs); | 229 var process = await Process.start(Platform.executable, vmArgs); |
229 | 230 |
230 _forwardSignals(process); | 231 _forwardSignals(process); |
231 | 232 |
232 // Note: we're not using process.std___.pipe(std___) here because | 233 // Note: we're not using process.std___.pipe(std___) here because |
233 // that prevents pub from also writing to the output streams. | 234 // that prevents pub from also writing to the output streams. |
234 process.stderr.listen(stderr.add); | 235 _forwardOutput(process.stderr, stderr); |
235 process.stdout.listen(stdout.add); | 236 _forwardOutput(process.stdout, stdout); |
236 input.listen(process.stdin.add); | 237 input.listen(process.stdin.add); |
237 | 238 |
238 return process.exitCode; | 239 return process.exitCode; |
239 } | 240 } |
240 | 241 |
241 var exitCode = await runProcess(stdin1); | 242 var exitCode = await runProcess(stdin1); |
242 if (recompile == null || exitCode != 253) return exitCode; | 243 if (recompile == null || exitCode != 253) return exitCode; |
243 | 244 |
244 // Exit code 253 indicates that the snapshot version was out-of-date. If we | 245 // Exit code 253 indicates that the snapshot version was out-of-date. If we |
245 // can recompile, do so. | 246 // can recompile, do so. |
246 await recompile(); | 247 await recompile(); |
247 return runProcess(stdin2); | 248 return runProcess(stdin2); |
248 } | 249 } |
249 | 250 |
250 /// Forwards all catchable signals to [process]. | 251 /// Forwards all catchable signals to [process]. |
251 void _forwardSignals(Process process) { | 252 void _forwardSignals(Process process) { |
252 // See [_catchableSignals]. | 253 // See [_catchableSignals]. |
253 ProcessSignal.SIGINT.watch().listen( | 254 ProcessSignal.SIGINT.watch().listen( |
254 (_) => log.fine("Ignoring SIGINT in pub.")); | 255 (_) => log.fine("Ignoring SIGINT in pub.")); |
255 | 256 |
256 for (var signal in _catchableSignals) { | 257 for (var signal in _catchableSignals) { |
257 signal.watch().listen((_) { | 258 signal.watch().listen((_) { |
258 log.fine("Forwarding $signal to running process."); | 259 log.fine("Forwarding $signal to running process."); |
259 process.kill(signal); | 260 process.kill(signal); |
260 }); | 261 }); |
261 } | 262 } |
262 } | 263 } |
263 | 264 |
| 265 /// Forwards output from a Process's output stream to the corresponding stream |
| 266 /// for pub. |
| 267 /// |
| 268 /// On Windows, this replaces any CR LF sequences in the process's output with |
| 269 /// just LF to work around sdk#19334. |
| 270 void _forwardOutput(Stream<List<int>> stream, Sink<List<int>> sink) { |
| 271 if (Platform.isWindows) { |
| 272 log.fine("filtering out CR LF"); |
| 273 stream = const CRLFRemover().bind(stream); |
| 274 } |
| 275 stream.listen(sink.add); |
| 276 } |
| 277 |
264 /// Runs the executable snapshot at [snapshotPath]. | 278 /// Runs the executable snapshot at [snapshotPath]. |
265 Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath, | 279 Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath, |
266 List<String> args) { | 280 List<String> args) { |
267 return runSnapshot(snapshotPath, args, checked: true, recompile: () { | 281 return runSnapshot(snapshotPath, args, checked: true, recompile: () { |
268 log.fine("Precompiled executable is out of date."); | 282 log.fine("Precompiled executable is out of date."); |
269 return entrypoint.precompileExecutables(); | 283 return entrypoint.precompileExecutables(); |
270 }); | 284 }); |
271 } | 285 } |
OLD | NEW |