[imitation_game] Migrate imitation game to null safety (#2483)

diff --git a/packages/imitation_game/CHANGELOG.md b/packages/imitation_game/CHANGELOG.md
index d775621..9a0072c 100644
--- a/packages/imitation_game/CHANGELOG.md
+++ b/packages/imitation_game/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.0.2
+
+* Migrate to null safety.
+
 ## 0.0.1
 
 * Initial version (TBD).
diff --git a/packages/imitation_game/bin/imitation_game.dart b/packages/imitation_game/bin/imitation_game.dart
index 587546c..175a20d 100644
--- a/packages/imitation_game/bin/imitation_game.dart
+++ b/packages/imitation_game/bin/imitation_game.dart
@@ -8,14 +8,14 @@
 
 import 'package:args/args.dart';
 import 'package:imitation_game/readme_template.dart';
-import 'package:mustache/mustache.dart';
+import 'package:mustache_template/mustache.dart';
 
 // ignore_for_file: avoid_as
 
 const int _port = 4040;
 
-Future<String> _findIpAddress() async {
-  String result;
+Future<String?> _findIpAddress() async {
+  String? result;
   final List<NetworkInterface> interfaces = await NetworkInterface.list();
   for (final NetworkInterface interface in interfaces) {
     for (final InternetAddress address in interface.addresses) {
@@ -41,7 +41,7 @@
 }
 
 typedef FileFilter = bool Function(FileSystemEntity);
-Future<List<FileSystemEntity>> findFiles(Directory dir, {FileFilter where}) {
+Future<List<FileSystemEntity>> findFiles(Directory dir, {FileFilter? where}) {
   final List<FileSystemEntity> files = <FileSystemEntity>[];
   final Completer<List<FileSystemEntity>> completer =
       Completer<List<FileSystemEntity>>();
@@ -68,7 +68,8 @@
 /// have their values from [newResults] and the symmetric difference will have the
 /// value from their respective sets.
 Map<String, dynamic> _integrate(
-    {Map<String, dynamic> oldResults, Map<String, dynamic> newResults}) {
+    {required Map<String, dynamic> oldResults,
+    required Map<String, dynamic> newResults}) {
   final Map<String, dynamic> result = Map<String, dynamic>.from(oldResults);
   newResults.forEach((String test, dynamic testValue) {
     final Map<String, dynamic> testMap = testValue as Map<String, dynamic>;
@@ -90,7 +91,7 @@
 }
 
 class _Script {
-  _Script({this.path});
+  _Script({required this.path});
   String path;
 }
 
@@ -98,15 +99,15 @@
   _ScriptRunner(this._scriptPaths);
 
   final List<String> _scriptPaths;
-  Process _currentProcess;
-  StreamSubscription<String> _stdoutSubscription;
-  StreamSubscription<String> _stderrSubscription;
+  Process? _currentProcess;
+  late StreamSubscription<String> _stdoutSubscription;
+  late StreamSubscription<String> _stderrSubscription;
 
-  Future<_Script> runNext() async {
+  Future<_Script?> runNext() async {
     if (_currentProcess != null) {
       _stdoutSubscription.cancel();
       _stderrSubscription.cancel();
-      _currentProcess.kill();
+      _currentProcess!.kill();
       _currentProcess = null;
     }
 
@@ -119,11 +120,11 @@
       _currentProcess = await Process.start('sh', <String>[path]);
       // TODO(gaaclarke): Implement a timeout.
       _stdoutSubscription =
-          _currentProcess.stdout.transform(utf8.decoder).listen((String data) {
+          _currentProcess!.stdout.transform(utf8.decoder).listen((String data) {
         print(data);
       });
       _stderrSubscription =
-          _currentProcess.stderr.transform(utf8.decoder).listen((String data) {
+          _currentProcess!.stderr.transform(utf8.decoder).listen((String data) {
         print(data);
       });
       return _Script(path: path);
@@ -160,8 +161,8 @@
 
 class _ImitationGame {
   final Map<String, dynamic> results = <String, dynamic>{};
-  _ScriptRunner _scriptRunner;
-  _Script _currentScript;
+  late _ScriptRunner _scriptRunner;
+  _Script? _currentScript;
 
   Future<bool> start(List<String> iosScripts) {
     _scriptRunner = _ScriptRunner(iosScripts);
@@ -170,7 +171,7 @@
 
   Future<bool> handleResult(Map<String, dynamic> data) {
     final String test = data['test'];
-    final String platform = data['platform'];
+    final String? platform = data['platform'];
     results.putIfAbsent(test, () => <String, dynamic>{});
     results[test].putIfAbsent(platform, () => <String, dynamic>{});
     data['results'].forEach((String k, dynamic v) {
@@ -204,7 +205,7 @@
     InternetAddress.anyIPv4,
     _port,
   );
-  final String ipaddress = await _findIpAddress();
+  final String? ipaddress = await _findIpAddress();
   print('Listening on $ipaddress:${server.port}');
 
   for (final FileSystemEntity entity in await findFiles(Directory.current,
diff --git a/packages/imitation_game/pubspec.yaml b/packages/imitation_game/pubspec.yaml
index 725fc15..38ae95c 100644
--- a/packages/imitation_game/pubspec.yaml
+++ b/packages/imitation_game/pubspec.yaml
@@ -2,11 +2,11 @@
 description: Testing framework for comparing multiple frameworks' performance.
 repository: https://github.com/flutter/packages/tree/main/packages/imitation_game
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+imitation_game%22
-version: 0.0.1
+version: 0.0.2
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  args: ^1.6.0
-  mustache: ^1.1.1
+  args: ^2.3.1
+  mustache_template: ^2.0.0
diff --git a/packages/imitation_game/run.sh b/packages/imitation_game/run.sh
index fb3ee33..ce82fcd 100755
--- a/packages/imitation_game/run.sh
+++ b/packages/imitation_game/run.sh
@@ -6,4 +6,4 @@
   echo "usage: run.sh [android | ios]"
 fi
 
-pub run imitation_game --platform=$1
+dart run imitation_game --platform=$1