OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'dart:io'; | 5 import 'dart:io'; |
6 import 'dart:async'; | 6 import 'dart:async'; |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:convert'; |
| 9 |
| 10 import 'util.dart'; |
8 | 11 |
9 final String cit = Platform.isWindows ? 'cit.bat' : 'cit'; | 12 final String cit = Platform.isWindows ? 'cit.bat' : 'cit'; |
10 | 13 |
| 14 enum LogdogExitKind { |
| 15 /// Normal program termination with a negative exit code. |
| 16 normal, |
| 17 |
| 18 /// Program killed due to error output. |
| 19 error, |
| 20 |
| 21 /// Program killed due to timeout. |
| 22 timeout, |
| 23 } |
| 24 |
11 class LogdogException implements Exception { | 25 class LogdogException implements Exception { |
| 26 final List<String> command; |
12 final int errorCode; | 27 final int errorCode; |
13 final String stdout; | 28 final String stdout; |
14 final String stderr; | 29 final String stderr; |
| 30 final LogdogExitKind exitKind; |
15 | 31 |
16 LogdogException(this.errorCode, this.stdout, this.stderr); | 32 LogdogException( |
| 33 this.command, this.errorCode, this.stdout, this.stderr, this.exitKind); |
17 LogdogException.fromProcessResult(ProcessResult result) | 34 LogdogException.fromProcessResult(ProcessResult result) |
18 : this(result.exitCode, result.stdout, result.stderr); | 35 : this(null, result.exitCode, result.stdout, result.stderr, |
| 36 LogdogExitKind.normal); |
19 | 37 |
20 toString() => "Error during logdog execution:\n$stderr"; | 38 toString() => "Error during logdog execution" |
| 39 "${command != null ? ' `${command.join(' ')}`': ''}" |
| 40 ":\n$stderr"; |
21 } | 41 } |
22 | 42 |
23 bool logdogCheckDone = false; | 43 bool logdogCheckDone = false; |
24 | 44 |
25 void checkLogdog({bool tryToInstall: true}) { | 45 void checkLogdog({bool tryToInstall: true}) { |
26 if (logdogCheckDone) return; | 46 if (logdogCheckDone) return; |
27 var result = Process.runSync(cit, []); | 47 var result = Process.runSync(cit, []); |
28 if (result.exitCode != 0) { | 48 if (result.exitCode != 0) { |
29 print("cit (from depot_tools) must be in the path."); | 49 print("cit (from depot_tools) must be in the path."); |
30 throw new StateError("cit not accessible"); | 50 throw new StateError("cit not accessible"); |
31 } | 51 } |
32 String stdout = result.stdout; | 52 String stdout = result.stdout; |
33 if (stdout.contains("logdog")) { | 53 if (stdout.contains("logdog")) { |
34 logdogCheckDone = true; | 54 logdogCheckDone = true; |
35 return; | 55 return; |
36 } | 56 } |
37 if (tryToInstall) { | 57 if (tryToInstall) { |
38 print("logdog isn't yet installed. Installation might take some time"); | 58 print("logdog isn't yet installed. Installation might take some time"); |
39 result = Process.runSync(cit, ["logdog"]); | 59 result = Process.runSync(cit, ["logdog"]); |
40 checkLogdog(tryToInstall: false); | 60 checkLogdog(tryToInstall: false); |
41 } else { | 61 } else { |
42 print("Couldn't install logdog"); | 62 print("Couldn't install logdog"); |
43 throw new StateError("logdog not accessible"); | 63 throw new StateError("logdog not accessible"); |
44 } | 64 } |
45 } | 65 } |
46 | 66 |
47 String logdog(List<String> args) { | 67 Future<String> logdog(List<String> args, |
| 68 {bool exitOnError: true, |
| 69 Duration timeout: const Duration(seconds: 10)}) async { |
48 checkLogdog(); | 70 checkLogdog(); |
49 args = args.toList()..insert(0, "logdog"); | 71 args = args.toList()..insert(0, "logdog"); |
50 var result = Process.runSync(cit, args); | 72 |
51 if (result.exitCode == 0) return result.stdout; | 73 LogdogExitKind exitKind = LogdogExitKind.normal; |
52 throw new LogdogException.fromProcessResult(result); | 74 Process process = await Process.start(cit, args); |
| 75 StringBuffer stdout = new StringBuffer(); |
| 76 StringBuffer stderr = new StringBuffer(); |
| 77 StreamSubscription stdoutSubscription = |
| 78 process.stdout.transform(UTF8.decoder).listen(stdout.write); |
| 79 StreamSubscription stderrSubscription = |
| 80 process.stderr.transform(UTF8.decoder).listen((String text) { |
| 81 stderr.write(text); |
| 82 if (exitOnError) { |
| 83 exitKind = LogdogExitKind.error; |
| 84 log('Error on `${args.join(' ')}`: $text'); |
| 85 process.kill(); |
| 86 } |
| 87 }); |
| 88 Timer timer; |
| 89 if (timeout != null) { |
| 90 timer = new Timer(timeout, () { |
| 91 exitKind = LogdogExitKind.timeout; |
| 92 log('Timeout on `${args.join(' ')}`'); |
| 93 process.kill(); |
| 94 }); |
| 95 } |
| 96 int exitCode = await process.exitCode; |
| 97 // Cancel the timer; it might still be running. |
| 98 timer?.cancel(); |
| 99 // Cancel the stdout/stderr subscriptions; if the process is killed the |
| 100 // streams might not have closed. |
| 101 stdoutSubscription.cancel(); |
| 102 stderrSubscription.cancel(); |
| 103 if (exitCode == 0) return stdout.toString(); |
| 104 throw new LogdogException( |
| 105 args, exitCode, stdout.toString(), stderr.toString(), exitKind); |
53 } | 106 } |
54 | 107 |
55 String cat(String log) { | 108 Future<String> cat(String log) async { |
56 return logdog(["cat", "-raw", log]); | 109 return logdog(["cat", "-raw", log]); |
57 } | 110 } |
58 | 111 |
59 /// Returns the content for [path], for instance the available build numbers | 112 /// Returns the content for [path], for instance the available build numbers |
60 /// for 'dart2js-linux-chromeff-1-4-be' using the path | 113 /// for 'dart2js-linux-chromeff-1-4-be' using the path |
61 /// `chromium/bb/client.dart/dart2js-linux-chromeff-1-4-be`. | 114 /// `chromium/bb/client.dart/dart2js-linux-chromeff-1-4-be`. |
62 String ls(String path) { | 115 Future<String> ls(String path) async { |
63 return logdog(["ls", path]); | 116 return logdog(["ls", path]); |
64 } | 117 } |
65 | 118 |
66 class LogResult<T> { | 119 class LogResult<T> { |
67 final String log; | 120 final String log; |
68 final T result; | 121 final T result; |
69 | 122 |
70 LogResult(this.log, this.result); | 123 LogResult(this.log, this.result); |
71 } | 124 } |
72 | 125 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 })).listen((logResult) { | 180 })).listen((logResult) { |
128 print("--------------------------"); | 181 print("--------------------------"); |
129 if (logResult.result == null) { | 182 if (logResult.result == null) { |
130 print("${logResult.log} - empty"); | 183 print("${logResult.log} - empty"); |
131 } else { | 184 } else { |
132 print(logResult.result.substring(0, 200)); | 185 print(logResult.result.substring(0, 200)); |
133 } | 186 } |
134 }); | 187 }); |
135 } | 188 } |
136 */ | 189 */ |
OLD | NEW |