Unverified Commit 045ba2b6 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Migrate dev/bots to null safety (#86522)

parent 2f3bf078
This diff is collapsed.
......@@ -6,7 +6,6 @@ import 'dart:async';
import 'dart:io' as io;
import 'package:flutter_devicelab/framework/browser.dart';
import 'package:meta/meta.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_static/shelf_static.dart';
......@@ -21,13 +20,13 @@ import 'package:shelf_static/shelf_static.dart';
/// request to "/test-result" containing result data as plain text body of the
/// request. This function has no opinion about what that string contains.
Future<String> evalTestAppInChrome({
@required String appUrl,
@required String appDirectory,
required String appUrl,
required String appDirectory,
int serverPort = 8080,
int browserDebugPort = 8081,
}) async {
io.HttpServer server;
Chrome chrome;
io.HttpServer? server;
Chrome? chrome;
try {
final Completer<String> resultCompleter = Completer<String>();
server = await io.HttpServer.bind('localhost', serverPort);
......@@ -63,13 +62,13 @@ class AppServer {
AppServer._(this._server, this.chrome, this.onChromeError);
static Future<AppServer> start({
@required String appUrl,
@required String appDirectory,
@required String cacheControl,
required String appUrl,
required String appDirectory,
required String cacheControl,
int serverPort = 8080,
int browserDebugPort = 8081,
bool headless = true,
List<Handler> additionalRequestHandlers,
List<Handler>? additionalRequestHandlers,
}) async {
io.HttpServer server;
Chrome chrome;
......@@ -106,7 +105,7 @@ class AppServer {
final Chrome chrome;
Future<void> stop() async {
chrome?.stop();
await _server?.close();
chrome.stop();
await _server.close();
}
}
......@@ -5,8 +5,6 @@
import 'dart:convert';
import 'dart:io';
import 'package:meta/meta.dart';
final Stopwatch _stopwatch = Stopwatch();
/// A wrapper around package:test's JSON reporter.
......@@ -75,7 +73,7 @@ class FlutterCompactFormatter {
///
/// Callers are responsible for splitting multiple lines before calling this
/// method.
TestResult processRawOutput(String raw) {
TestResult? processRawOutput(String raw) {
assert(raw != null);
// We might be getting messages from Flutter Tool about updating/building.
if (!raw.startsWith('{')) {
......@@ -83,7 +81,7 @@ class FlutterCompactFormatter {
return null;
}
final Map<String, dynamic> decoded = json.decode(raw) as Map<String, dynamic>;
final TestResult originalResult = _tests[decoded['testID']];
final TestResult? originalResult = _tests[decoded['testID']];
switch (decoded['type'] as String) {
case 'done':
stdout.write(_clearLine);
......@@ -104,9 +102,9 @@ class FlutterCompactFormatter {
_tests[testData['id'] as int] = TestResult(
id: testData['id'] as int,
name: testData['name'] as String,
line: testData['root_line'] as int ?? testData['line'] as int,
column: testData['root_column'] as int ?? testData['column'] as int,
path: testData['root_url'] as String ?? testData['url'] as String,
line: testData['root_line'] as int? ?? testData['line'] as int,
column: testData['root_column'] as int? ?? testData['column'] as int,
path: testData['root_url'] as String? ?? testData['url'] as String,
startTime: decoded['time'] as int,
);
break;
......@@ -173,9 +171,9 @@ class FlutterCompactFormatter {
case TestStatus.failed:
failed.addAll(<String>[
'$_bold${_red}Failed ${result.name} (${result.pathLineColumn}):',
result.errorMessage,
result.errorMessage!,
_noColor + _red,
result.stackTrace,
result.stackTrace!,
]);
failed.addAll(result.messages);
failed.add(_noColor);
......@@ -209,12 +207,12 @@ enum TestStatus {
/// The detailed status of a test run.
class TestResult {
TestResult({
@required this.id,
@required this.name,
@required this.line,
@required this.column,
@required this.path,
@required this.startTime,
required this.id,
required this.name,
required this.line,
required this.column,
required this.path,
required this.startTime,
this.status = TestStatus.started,
}) : assert(id != null),
assert(name != null),
......@@ -254,13 +252,13 @@ class TestResult {
/// The error message from the test, from an `expect`, an [Exception] or
/// [Error].
String errorMessage;
String? errorMessage;
/// The stacktrace from a test failure.
String stackTrace;
String? stackTrace;
/// The time, in milliseconds relative to suite startup, that the test ended.
int endTime;
int? endTime;
/// The total time, in milliseconds, that the test took.
int get totalTime => (endTime ?? _stopwatch.elapsedMilliseconds) - startTime;
......
......@@ -11,7 +11,6 @@ import 'package:args/args.dart';
import 'package:crypto/crypto.dart';
import 'package:crypto/src/digest_sink.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart' show required;
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart' show Platform, LocalPlatform;
import 'package:process/process.dart';
......@@ -32,7 +31,7 @@ class PreparePackageException implements Exception {
PreparePackageException(this.message, [this.result]);
final String message;
final ProcessResult result;
final ProcessResult? result;
int get exitCode => result?.exitCode ?? -1;
@override
......@@ -41,7 +40,7 @@ class PreparePackageException implements Exception {
if (message != null) {
output += ': $message';
}
final String stderr = result?.stderr as String ?? '';
final String stderr = result?.stderr as String? ?? '';
if (stderr.isNotEmpty) {
output += ':\n$stderr';
}
......@@ -60,7 +59,6 @@ String getBranchName(Branch branch) {
case Branch.stable:
return 'stable';
}
return null;
}
Branch fromBranchName(String name) {
......@@ -81,7 +79,7 @@ Branch fromBranchName(String name) {
/// properly without dropping any.
class ProcessRunner {
ProcessRunner({
ProcessManager processManager,
ProcessManager? processManager,
this.subprocessOutput = true,
this.defaultWorkingDirectory,
this.platform = const LocalPlatform(),
......@@ -102,10 +100,10 @@ class ProcessRunner {
/// Sets the default directory used when `workingDirectory` is not specified
/// to [runProcess].
final Directory defaultWorkingDirectory;
final Directory? defaultWorkingDirectory;
/// The environment to run processes with.
Map<String, String> environment;
late Map<String, String> environment;
/// Run the command and arguments in `commandLine` as a sub-process from
/// `workingDirectory` if set, or the [defaultWorkingDirectory] if not. Uses
......@@ -115,7 +113,7 @@ class ProcessRunner {
/// command completes with a non-zero exit code.
Future<String> runProcess(
List<String> commandLine, {
Directory workingDirectory,
Directory? workingDirectory,
bool failOk = false,
}) async {
workingDirectory ??= defaultWorkingDirectory ?? Directory.current;
......@@ -125,7 +123,7 @@ class ProcessRunner {
final List<int> output = <int>[];
final Completer<void> stdoutComplete = Completer<void>();
final Completer<void> stderrComplete = Completer<void>();
Process process;
late Process process;
Future<int> allComplete() async {
await stderrComplete.future;
await stdoutComplete.future;
......@@ -197,10 +195,10 @@ class ArchiveCreator {
this.revision,
this.branch, {
this.strict = true,
ProcessManager processManager,
ProcessManager? processManager,
bool subprocessOutput = true,
this.platform = const LocalPlatform(),
HttpReader httpReader,
HttpReader? httpReader,
}) : assert(revision.length == 40),
flutterRoot = Directory(path.join(tempDir.path, 'flutter')),
httpReader = httpReader ?? http.readBytes,
......@@ -252,9 +250,9 @@ class ArchiveCreator {
/// [http.readBytes].
final HttpReader httpReader;
File _outputFile;
String _version;
String _flutter;
late File _outputFile;
late String _version;
late String _flutter;
/// Get the name of the channel as a string.
String get branchName => getBranchName(branch);
......@@ -446,14 +444,14 @@ class ArchiveCreator {
}
}
Future<String> _runFlutter(List<String> args, {Directory workingDirectory}) {
Future<String> _runFlutter(List<String> args, {Directory? workingDirectory}) {
return _processRunner.runProcess(
<String>[_flutter, ...args],
workingDirectory: workingDirectory ?? flutterRoot,
);
}
Future<String> _runGit(List<String> args, {Directory workingDirectory}) {
Future<String> _runGit(List<String> args, {Directory? workingDirectory}) {
return _processRunner.runProcess(
<String>['git', ...args],
workingDirectory: workingDirectory ?? flutterRoot,
......@@ -462,7 +460,7 @@ class ArchiveCreator {
/// Unpacks the given zip file into the currentDirectory (if set), or the
/// same directory as the archive.
Future<String> _unzipArchive(File archive, {Directory workingDirectory}) {
Future<String> _unzipArchive(File archive, {Directory? workingDirectory}) {
workingDirectory ??= Directory(path.dirname(archive.absolute.path));
List<String> commandLine;
if (platform.isWindows) {
......@@ -532,7 +530,7 @@ class ArchivePublisher {
this.version,
this.outputFile,
this.dryRun, {
ProcessManager processManager,
ProcessManager? processManager,
bool subprocessOutput = true,
this.platform = const LocalPlatform(),
}) : assert(revision.length == 40),
......@@ -662,7 +660,7 @@ class ArchivePublisher {
Future<String> _runGsUtil(
List<String> args, {
Directory workingDirectory,
Directory? workingDirectory,
bool failOk = false,
}) async {
if (dryRun) {
......@@ -671,7 +669,7 @@ class ArchivePublisher {
}
if (platform.isWindows) {
return _processRunner.runProcess(
<String>['python', path.join(platform.environment['DEPOT_TOOLS'], 'gsutil.py'), '--', ...args],
<String>['python', path.join(platform.environment['DEPOT_TOOLS']!, 'gsutil.py'), '--', ...args],
workingDirectory: workingDirectory,
failOk: failOk,
);
......@@ -699,14 +697,14 @@ class ArchivePublisher {
}
Future<String> _cloudCopy({
@required String src,
@required String dest,
int cacheSeconds,
required String src,
required String dest,
int? cacheSeconds,
}) async {
// We often don't have permission to overwrite, but
// we have permission to remove, so that's what we do.
await _runGsUtil(<String>['rm', dest], failOk: true);
String mimeType;
String? mimeType;
if (dest.endsWith('.tar.xz')) {
mimeType = 'application/x-gtar';
}
......@@ -841,7 +839,7 @@ Future<void> main(List<String> rawArguments) async {
final Branch branch = fromBranchName(parsedArguments['branch'] as String);
final ArchiveCreator creator = ArchiveCreator(tempDir, outputDir, revision, branch, strict: parsedArguments['publish'] as bool);
int exitCode = 0;
String message;
late String message;
try {
final String version = await creator.initializeRepo();
final File outputFile = await creator.createArchive();
......
......@@ -2,7 +2,7 @@ name: tests_on_bots
description: Scripts which run on bots.
environment:
sdk: ">=2.2.2 <3.0.0"
sdk: ">=2.12.0 <3.0.0"
dependencies:
args: 2.1.1
......
......@@ -19,12 +19,12 @@ import 'utils.dart';
/// code fails the test immediately by exiting the test process with exit code
/// 1.
Stream<String> runAndGetStdout(String executable, List<String> arguments, {
String workingDirectory,
Map<String, String> environment,
String? workingDirectory,
Map<String, String>? environment,
bool expectNonZeroExit = false,
}) async* {
final StreamController<String> output = StreamController<String>();
final Future<CommandResult> command = runCommand(
final Future<CommandResult?> command = runCommand(
executable,
arguments,
workingDirectory: workingDirectory,
......@@ -52,8 +52,8 @@ class Command {
final io.Process process;
final Stopwatch _time;
final Future<List<List<int>>> _savedStdout;
final Future<List<List<int>>> _savedStderr;
final Future<List<List<int>>>? _savedStdout;
final Future<List<List<int>>>? _savedStderr;
/// Evaluates when the [process] exits.
///
......@@ -63,8 +63,8 @@ class Command {
_time.stop();
// Saved output is null when OutputMode.print is used.
final String flattenedStdout = _savedStdout != null ? _flattenToString(await _savedStdout) : null;
final String flattenedStderr = _savedStderr != null ? _flattenToString(await _savedStderr) : null;
final String? flattenedStdout = _savedStdout != null ? _flattenToString((await _savedStdout)!) : null;
final String? flattenedStderr = _savedStderr != null ? _flattenToString((await _savedStderr)!) : null;
return CommandResult._(exitCode, _time.elapsed, flattenedStdout, flattenedStderr);
}
}
......@@ -80,10 +80,10 @@ class CommandResult {
final Duration elapsedTime;
/// Standard output decoded as a string using UTF8 decoder.
final String flattenedStdout;
final String? flattenedStdout;
/// Standard error output decoded as a string using UTF8 decoder.
final String flattenedStderr;
final String? flattenedStderr;
}
/// Starts the `executable` and returns a command object representing the
......@@ -97,11 +97,11 @@ class CommandResult {
/// `outputMode` controls where the standard output from the command process
/// goes. See [OutputMode].
Future<Command> startCommand(String executable, List<String> arguments, {
String workingDirectory,
Map<String, String> environment,
String? workingDirectory,
Map<String, String>? environment,
OutputMode outputMode = OutputMode.print,
bool Function(String) removeLine,
void Function(String, io.Process) outputListener,
bool Function(String)? removeLine,
void Function(String, io.Process)? outputListener,
}) async {
final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}';
final String relativeWorkingDir = path.relative(workingDirectory ?? io.Directory.current.path);
......@@ -113,7 +113,7 @@ Future<Command> startCommand(String executable, List<String> arguments, {
environment: environment,
);
Future<List<List<int>>> savedStdout, savedStderr;
Future<List<List<int>>>? savedStdout, savedStderr;
final Stream<List<int>> stdoutSource = process.stdout
.transform<String>(const Utf8Decoder())
.transform(const LineSplitter())
......@@ -150,27 +150,22 @@ Future<Command> startCommand(String executable, List<String> arguments, {
/// an indefinitely running process, for example, by waiting until the process
/// emits certain output.
///
/// Returns the result of the finished process, or null if `skip` is true.
/// Returns the result of the finished process.
///
/// `outputMode` controls where the standard output from the command process
/// goes. See [OutputMode].
Future<CommandResult> runCommand(String executable, List<String> arguments, {
String workingDirectory,
Map<String, String> environment,
String? workingDirectory,
Map<String, String>? environment,
bool expectNonZeroExit = false,
int expectedExitCode,
String failureMessage,
int? expectedExitCode,
String? failureMessage,
OutputMode outputMode = OutputMode.print,
bool skip = false,
bool Function(String) removeLine,
void Function(String, io.Process) outputListener,
bool Function(String)? removeLine,
void Function(String, io.Process)? outputListener,
}) async {
final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}';
final String relativeWorkingDir = path.relative(workingDirectory ?? io.Directory.current.path);
if (skip) {
printProgress('SKIPPING', relativeWorkingDir, commandDescription);
return null;
}
final Command command = await startCommand(executable, arguments,
workingDirectory: workingDirectory,
......
......@@ -5,7 +5,6 @@
import 'dart:async';
import 'dart:io';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:shelf/shelf.dart';
......@@ -37,7 +36,7 @@ Future<void> _setAppVersion(int version) async {
);
}
Future<void> _rebuildApp({ @required int version }) async {
Future<void> _rebuildApp({ required int version }) async {
await _setAppVersion(version);
await runCommand(
_flutter,
......@@ -56,7 +55,7 @@ Future<void> _rebuildApp({ @required int version }) async {
/// A drop-in replacement for `package:test` expect that can run outside the
/// test zone.
void expect(Object actual, Object expected) {
void expect(Object? actual, Object? expected) {
final Matcher matcher = wrapMatcher(expected);
final Map<Object, Object> matchState = <Object, Object>{};
if (matcher.matches(actual, matchState)) {
......@@ -68,7 +67,7 @@ void expect(Object actual, Object expected) {
}
Future<void> runWebServiceWorkerTest({
@required bool headless,
required bool headless,
}) async {
await _rebuildApp(version: 1);
......@@ -78,25 +77,25 @@ Future<void> runWebServiceWorkerTest({
requestedPathCounts.clear();
}
AppServer server;
AppServer? server;
Future<void> waitForAppToLoad(Map<String, int> waitForCounts) async {
print('Waiting for app to load $waitForCounts');
await Future.any(<Future<void>>[
await Future.any(<Future<Object?>>[
() async {
while (!waitForCounts.entries.every((MapEntry<String, int> entry) => (requestedPathCounts[entry.key] ?? 0) >= entry.value)) {
await Future<void>.delayed(const Duration(milliseconds: 100));
}
}(),
server.onChromeError.then((String error) {
server!.onChromeError.then((String error) {
throw Exception('Chrome error: $error');
}),
]);
}
String reportedVersion;
String? reportedVersion;
Future<void> startAppServer({
@required String cacheControl,
required String cacheControl,
}) async {
final int serverPort = await findAvailablePort();
final int browserDebugPort = await findAvailablePort();
......@@ -113,7 +112,7 @@ Future<void> runWebServiceWorkerTest({
(Request request) {
final String requestedPath = request.url.path;
requestedPathCounts.putIfAbsent(requestedPath, () => 0);
requestedPathCounts[requestedPath] += 1;
requestedPathCounts[requestedPath] = requestedPathCounts[requestedPath]! + 1;
if (requestedPath == 'CLOSE') {
reportedVersion = request.url.queryParameters['version'];
return Response.ok('OK');
......@@ -158,7 +157,7 @@ Future<void> runWebServiceWorkerTest({
reportedVersion = null;
print('With cache: test page reload');
await server.chrome.reloadPage();
await server!.chrome.reloadPage();
await waitForAppToLoad(<String, int>{
'CLOSE': 1,
'flutter_service_worker.js': 1,
......@@ -175,7 +174,7 @@ Future<void> runWebServiceWorkerTest({
await _rebuildApp(version: 2);
// Since we're caching, we need to ignore cache when reloading the page.
await server.chrome.reloadPage(ignoreCache: true);
await server!.chrome.reloadPage(ignoreCache: true);
await waitForAppToLoad(<String, int>{
'CLOSE': 1,
'flutter_service_worker.js': 2,
......@@ -195,7 +194,7 @@ Future<void> runWebServiceWorkerTest({
expect(reportedVersion, '2');
reportedVersion = null;
await server.stop();
await server!.stop();
//////////////////////////////////////////////////////
......@@ -231,7 +230,7 @@ Future<void> runWebServiceWorkerTest({
reportedVersion = null;
print('No cache: test page reload');
await server.chrome.reloadPage();
await server!.chrome.reloadPage();
await waitForAppToLoad(<String, int>{
'CLOSE': 1,
'flutter_service_worker.js': 1,
......@@ -254,7 +253,7 @@ Future<void> runWebServiceWorkerTest({
// refresh when running Chrome manually as normal. At the time of writing
// this test I wasn't able to figure out what's wrong with the way we run
// Chrome from tests.
await server.chrome.reloadPage(ignoreCache: true);
await server!.chrome.reloadPage(ignoreCache: true);
await waitForAppToLoad(<String, int>{
'CLOSE': 1,
'flutter_service_worker.js': 1,
......
This diff is collapsed.
......@@ -74,16 +74,16 @@ void main() {
});
});
group('ArchiveCreator for $platformName', () {
ArchiveCreator creator;
Directory tempDir;
late ArchiveCreator creator;
late Directory tempDir;
Directory flutterDir;
Directory cacheDir;
FakeProcessManager processManager;
late FakeProcessManager processManager;
final List<List<String>> args = <List<String>>[];
final List<Map<Symbol, dynamic>> namedArgs = <Map<Symbol, dynamic>>[];
String flutter;
late String flutter;
Future<Uint8List> fakeHttpReader(Uri url, {Map<String, String> headers}) {
Future<Uint8List> fakeHttpReader(Uri url, {Map<String, String>? headers}) {
return Future<Uint8List>.value(Uint8List(0));
}
......@@ -118,7 +118,7 @@ void main() {
final String archiveName = path.join(tempDir.absolute.path,
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
processManager.addCommands(convertResults(<String, List<ProcessResult>>{
processManager.addCommands(convertResults(<String, List<ProcessResult>?>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
'git reset --hard $testRef': null,
'git remote set-url origin https://github.com/flutter/flutter.git': null,
......@@ -147,7 +147,7 @@ void main() {
final String createBase = path.join(tempDir.absolute.path, 'create_');
final String archiveName = path.join(tempDir.absolute.path,
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
'git reset --hard $testRef': null,
'git remote set-url origin https://github.com/flutter/flutter.git': null,
......@@ -197,7 +197,7 @@ void main() {
final String createBase = path.join(tempDir.absolute.path, 'create_');
final String archiveName = path.join(tempDir.absolute.path,
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
'git reset --hard $testRef': null,
'git remote set-url origin https://github.com/flutter/flutter.git': null,
......@@ -239,7 +239,7 @@ void main() {
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
final ProcessResult codesignFailure = ProcessResult(1, 1, '', 'code object is not signed at all');
final String binPath = path.join(tempDir.path, 'flutter', 'bin', 'cache', 'dart-sdk', 'bin', 'dart');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
'git reset --hard $testRef': null,
'git remote set-url origin https://github.com/flutter/flutter.git': null,
......@@ -286,8 +286,8 @@ void main() {
});
group('ArchivePublisher for $platformName', () {
FakeProcessManager processManager;
Directory tempDir;
late FakeProcessManager processManager;
late Directory tempDir;
final String gsutilCall = platform.isWindows
? 'python ${path.join("D:", "depot_tools", "gsutil.py")}'
: 'gsutil.py';
......@@ -346,7 +346,7 @@ void main() {
''';
File(jsonPath).writeAsStringSync(releasesJson);
File(archivePath).writeAsStringSync('archive contents');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{
// This process fails because the file does NOT already exist
'$gsutilCall -- stat $gsArchivePath': <ProcessResult>[ProcessResult(0, 1, '', '')],
'$gsutilCall -- rm $gsArchivePath': null,
......@@ -442,7 +442,7 @@ void main() {
''';
File(jsonPath).writeAsStringSync(releasesJson);
File(archivePath).writeAsStringSync('archive contents');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{
// This process fails because the file does NOT already exist
'$gsutilCall -- stat $gsArchivePath': <ProcessResult>[ProcessResult(0, 1, '', '')],
'$gsutilCall -- rm $gsArchivePath': null,
......@@ -552,7 +552,7 @@ void main() {
''';
File(jsonPath).writeAsStringSync(releasesJson);
File(archivePath).writeAsStringSync('archive contents');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{
'$gsutilCall -- rm $gsArchivePath': null,
'$gsutilCall -- -h Content-Type:$archiveMime cp $archivePath $gsArchivePath': null,
'$gsutilCall -- cp $gsJsonPath $jsonPath': null,
......@@ -567,10 +567,10 @@ void main() {
}
}
List<FakeCommand> convertResults(Map<String, List<ProcessResult>> results) {
List<FakeCommand> convertResults(Map<String, List<ProcessResult>?> results) {
final List<FakeCommand> commands = <FakeCommand>[];
for (final String key in results.keys) {
final List<ProcessResult> candidates = results[key];
final List<ProcessResult>? candidates = results[key];
final List<String> args = key.split(' ');
if (candidates == null) {
commands.add(FakeCommand(
......@@ -581,8 +581,8 @@ List<FakeCommand> convertResults(Map<String, List<ProcessResult>> results) {
commands.add(FakeCommand(
command: args,
exitCode: result.exitCode,
stderr: result.stderr?.toString(),
stdout: result.stdout?.toString(),
stderr: result.stderr.toString(),
stdout: result.stdout.toString(),
));
}
}
......
......@@ -12,10 +12,10 @@ void main() {
test('We are in a directory with a space in it', () async {
// The Flutter SDK should be in a directory with a space in it, to make sure
// our tools support that.
final String expectedName = Platform.environment['FLUTTER_SDK_PATH_WITH_SPACE'];
final String? expectedName = Platform.environment['FLUTTER_SDK_PATH_WITH_SPACE'];
expect(expectedName, 'flutter sdk');
expect(expectedName, contains(' '));
final List<String> parts = path.split(Directory.current.absolute.path);
expect(parts.reversed.take(3), <String>['bots', 'dev', expectedName]);
expect(parts.reversed.take(3), <String?>['bots', 'dev', expectedName]);
}, skip: true); // https://github.com/flutter/flutter/issues/62919
}
......@@ -23,7 +23,7 @@ void expectExitCode(ProcessResult result, int expectedExitCode) {
void main() {
group('verifyVersion()', () {
MemoryFileSystem fileSystem;
late MemoryFileSystem fileSystem;
setUp(() {
fileSystem = MemoryFileSystem.test();
......@@ -97,7 +97,7 @@ void main() {
const ProcessManager processManager = LocalProcessManager();
Future<ProcessResult> runScript(
[Map<String, String> environment, List<String> otherArgs = const <String>[]]) async {
[Map<String, String>? environment, List<String> otherArgs = const <String>[]]) async {
final String dart = path.absolute(
path.join('..', '..', 'bin', 'cache', 'dart-sdk', 'bin', 'dart'));
final ProcessResult scriptProcess = processManager.runSync(<String>[
......
......@@ -32,7 +32,7 @@ class UnpublishException implements Exception {
UnpublishException(this.message, [this.result]);
final String message;
final ProcessResult result;
final ProcessResult? result;
int get exitCode => result?.exitCode ?? -1;
@override
......@@ -41,7 +41,7 @@ class UnpublishException implements Exception {
if (message != null) {
output += ': $message';
}
final String stderr = result?.stderr as String ?? '';
final String stderr = result?.stderr as String? ?? '';
if (stderr.isNotEmpty) {
output += ':\n$stderr';
}
......@@ -60,10 +60,9 @@ String getChannelName(Channel channel) {
case Channel.stable:
return 'stable';
}
return null;
}
Channel fromChannelName(String name) {
Channel fromChannelName(String? name) {
switch (name) {
case 'beta':
return Channel.beta;
......@@ -87,7 +86,6 @@ String getPublishedPlatform(PublishedPlatform platform) {
case PublishedPlatform.windows:
return 'windows';
}
return null;
}
PublishedPlatform fromPublishedPlatform(String name) {
......@@ -135,10 +133,10 @@ class ProcessRunner {
/// Sets the default directory used when `workingDirectory` is not specified
/// to [runProcess].
final Directory defaultWorkingDirectory;
final Directory? defaultWorkingDirectory;
/// The environment to run processes with.
Map<String, String> environment;
late Map<String, String> environment;
/// Run the command and arguments in `commandLine` as a sub-process from
/// `workingDirectory` if set, or the [defaultWorkingDirectory] if not. Uses
......@@ -148,7 +146,7 @@ class ProcessRunner {
/// command completes with a non-zero exit code.
Future<String> runProcess(
List<String> commandLine, {
Directory workingDirectory,
Directory? workingDirectory,
bool failOk = false,
}) async {
workingDirectory ??= defaultWorkingDirectory ?? Directory.current;
......@@ -158,7 +156,7 @@ class ProcessRunner {
final List<int> output = <int>[];
final Completer<void> stdoutComplete = Completer<void>();
final Completer<void> stderrComplete = Completer<void>();
Process process;
late Process process;
Future<int> allComplete() async {
await stderrComplete.future;
await stdoutComplete.future;
......@@ -221,12 +219,12 @@ class ArchiveUnpublisher {
this.channels,
this.platform, {
this.confirmed = false,
ProcessManager processManager,
ProcessManager? processManager,
bool subprocessOutput = true,
}) : assert(revisionsBeingRemoved.length == 40),
metadataGsPath = '$gsReleaseFolder/${getMetadataFilename(platform)}',
_processRunner = ProcessRunner(
processManager: processManager,
processManager: processManager ?? const LocalProcessManager(),
subprocessOutput: subprocessOutput,
);
......@@ -249,8 +247,8 @@ class ArchiveUnpublisher {
final Map<Channel, Map<String, String>> paths = await _getArchivePaths(releases);
releases.removeWhere((Map<String, String> value) => revisionsBeingRemoved.contains(value['hash']) && channels.contains(fromChannelName(value['channel'])));
releases.sort((Map<String, String> a, Map<String, String> b) {
final DateTime aDate = DateTime.parse(a['release_date']);
final DateTime bDate = DateTime.parse(b['release_date']);
final DateTime aDate = DateTime.parse(a['release_date']!);
final DateTime bDate = DateTime.parse(b['release_date']!);
return bDate.compareTo(aDate);
});
jsonData['releases'] = releases;
......@@ -277,12 +275,12 @@ class ArchiveUnpublisher {
final Set<String> hashes = <String>{};
final Map<Channel, Map<String, String>> paths = <Channel, Map<String, String>>{};
for (final Map<String, String> revision in releases) {
final String hash = revision['hash'];
final String hash = revision['hash']!;
final Channel channel = fromChannelName(revision['channel']);
hashes.add(hash);
if (revisionsBeingRemoved.contains(hash) && channels.contains(channel)) {
paths[channel] ??= <String, String>{};
paths[channel][hash] = revision['archive'];
paths[channel]![hash] = revision['archive']!;
}
}
final Set<String> missingRevisions = revisionsBeingRemoved.difference(hashes.intersection(revisionsBeingRemoved));
......@@ -330,7 +328,7 @@ class ArchiveUnpublisher {
Future<String> _runGsUtil(
List<String> args, {
Directory workingDirectory,
Directory? workingDirectory,
bool failOk = false,
bool confirm = false,
}) async {
......@@ -351,7 +349,7 @@ class ArchiveUnpublisher {
final List<String> files = <String>[];
print('${confirmed ? 'Removing' : 'Would remove'} the following release archives:');
for (final Channel channel in paths.keys) {
final Map<String, String> hashes = paths[channel];
final Map<String, String> hashes = paths[channel]!;
for (final String hash in hashes.keys) {
final String file = '$gsReleaseFolder/${hashes[hash]}';
files.add(file);
......@@ -367,7 +365,7 @@ class ArchiveUnpublisher {
// We often don't have permission to overwrite, but
// we have permission to remove, so that's what we do first.
await _runGsUtil(<String>['rm', dest], failOk: true, confirm: confirmed);
String mimeType;
String? mimeType;
if (dest.endsWith('.tar.xz')) {
mimeType = 'application/x-gtar';
}
......@@ -497,8 +495,8 @@ Future<void> main(List<String> rawArguments) async {
final List<String> platformOptions = platformArg.isNotEmpty ? platformArg : allowedPlatformNames;
final List<PublishedPlatform> platforms = platformOptions.map<PublishedPlatform>((String value) => fromPublishedPlatform(value)).toList();
int exitCode = 0;
String message;
String stack;
late String message;
late String stack;
try {
for (final PublishedPlatform platform in platforms) {
final ArchiveUnpublisher publisher = ArchiveUnpublisher(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment