blob: 9474ca0b30b863bfe67313690cff16d8e5a4e9a3 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:core' as core_internals show print;
import 'dart:core' hide print;
import 'dart:io' as system show exit;
import 'dart:io' hide exit;
import 'package:meta/meta.dart';
final bool hasColor = stdout.supportsAnsiEscapes;
final String bold = hasColor ? '\x1B[1m' : ''; // used for shard titles
final String red = hasColor ? '\x1B[31m' : ''; // used for errors
final String green = hasColor ? '\x1B[32m' : ''; // used for section titles, commands
final String yellow = hasColor ? '\x1B[33m' : ''; // used for skips
final String cyan = hasColor ? '\x1B[36m' : ''; // used for paths
final String reverse = hasColor ? '\x1B[7m' : ''; // used for clocks
final String reset = hasColor ? '\x1B[0m' : '';
final String redLine = '$red━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$reset';
typedef PrintCallback = void Function(Object line);
// Allow print() to be overridden, for tests.
PrintCallback print = core_internals.print;
bool get hasError => _hasError;
bool _hasError = false;
Iterable<String> get errorMessages => _errorMessages;
List<String> _errorMessages = <String>[];
void foundError(List<String> messages) {
assert(messages.isNotEmpty);
print(redLine);
messages.forEach(print);
print(redLine);
_errorMessages.addAll(messages);
_hasError = true;
}
@visibleForTesting
void resetErrorStatus() {
_hasError = false;
_errorMessages.clear();
}
Never reportErrorsAndExit() {
print(redLine);
print('For your convenience, the error messages reported above are repeated here:');
_errorMessages.forEach(print);
print(redLine);
system.exit(1);
}
String get clock {
final DateTime now = DateTime.now();
return '$reverse▌'
'${now.hour.toString().padLeft(2, "0")}:'
'${now.minute.toString().padLeft(2, "0")}:'
'${now.second.toString().padLeft(2, "0")}'
'▐$reset';
}
String prettyPrintDuration(Duration duration) {
String result = '';
final int minutes = duration.inMinutes;
if (minutes > 0) {
result += '${minutes}min ';
}
final int seconds = duration.inSeconds - minutes * 60;
final int milliseconds = duration.inMilliseconds - (seconds * 1000 + minutes * 60 * 1000);
result += '$seconds.${milliseconds.toString().padLeft(3, "0")}s';
return result;
}
void printProgress(String action, String workingDir, String command) {
print('$clock $action: cd $cyan$workingDir$reset; $green$command$reset');
}
int _portCounter = 8080;
/// Finds the next available local port.
Future<int> findAvailablePort() async {
while (!await _isPortAvailable(_portCounter)) {
_portCounter += 1;
}
return _portCounter++;
}
Future<bool> _isPortAvailable(int port) async {
try {
final RawSocket socket = await RawSocket.connect('localhost', port);
socket.shutdown(SocketDirection.both);
await socket.close();
return false;
} on SocketException {
return true;
}
}