Script to find Flutter earliest Flutter revision that contains an engine revision (#50948)

diff --git a/dev/tools/find_engine_commit.dart b/dev/tools/find_engine_commit.dart
new file mode 100644
index 0000000..8b87553
--- /dev/null
+++ b/dev/tools/find_engine_commit.dart
@@ -0,0 +1,130 @@
+// 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:io';
+
+void _validate(List<String> args) {
+  bool errors = false;
+  if (!File('bin/internal/engine.version').existsSync()) {
+    errors = true;
+    print('This program must be run from the root of your flutter repository.');
+  }
+  if (!File('../engine/src/flutter/DEPS').existsSync()) {
+    errors = true;
+    print('This program assumes the engine directory is a sibling to the flutter repository directory.');
+  }
+  if (args.length != 1) {
+    errors = true;
+    print('This program takes the engine revision as a single argument.');
+  }
+  if (errors) {
+    exit(-1);
+  }
+}
+
+const String engineRepo = '../engine/src/flutter';
+
+Future<void> main(List<String> args) async {
+  _validate(args);
+  await _fetchUpstream();
+  await _fetchUpstream(engineRepo);
+  String flutterRevision;
+  await for (final FlutterEngineRevision revision in _logEngineVersions()) {
+    if (!await containsRevision(args[0], revision.engineRevision)) {
+      if (flutterRevision == null) {
+        print('Revision not found.');
+        exit(-1);
+      }
+      print('earliest revision: $flutterRevision');
+      print('Tags that contain this engine revision:');
+      print(await _tagsForRevision(flutterRevision));
+      exit(0);
+    }
+    flutterRevision = revision.flutterRevision;
+  }
+}
+
+Future<void> _fetchUpstream([String workingDirectory = '.']) async {
+  print('Fetching remotes for "$workingDirectory" - you may be prompted for SSH credentials by git.');
+  final ProcessResult fetchResult = await Process.run(
+    'git',
+    <String>[
+      'fetch',
+      '--all',
+    ],
+    workingDirectory: workingDirectory,
+  );
+  if (fetchResult.exitCode != 0) {
+    throw Exception('Failed to fetch upstream in repository $workingDirectory');
+  }
+}
+
+Future<String> _tagsForRevision(String flutterRevision) async {
+  final ProcessResult tagResult = await Process.run(
+    'git',
+    <String>[
+      'tag',
+      '--contains',
+      flutterRevision,
+    ],
+  );
+  return tagResult.stdout as String;
+}
+
+Future<bool> containsRevision(String ancestorRevision, String revision) async {
+  final ProcessResult result = await Process.run(
+    'git',
+    <String>[
+      'merge-base',
+      '--is-ancestor',
+      ancestorRevision,
+      revision,
+    ],
+    workingDirectory: engineRepo,
+  );
+  return result.exitCode == 0;
+}
+
+Stream<FlutterEngineRevision> _logEngineVersions() async* {
+  final ProcessResult result = await Process.run(
+    'git',
+    <String>[
+      'log',
+      '--oneline',
+      '-p',
+      '--',
+      'bin/internal/engine.version',
+    ],
+  );
+  if (result.exitCode != 0) {
+    print(result.stderr);
+    throw Exception('Failed to log bin/internal/engine.version');
+  }
+
+  final List<String> lines = (result.stdout as String).split('\n');
+  int index = 0;
+  while (index < lines.length - 1) {
+    final String flutterRevision = lines[index].split(' ').first;
+    index += 1;
+    while (!lines[index].startsWith('+') || lines[index].startsWith('+++')) {
+      index += 1;
+    }
+    if (index >= lines.length) {
+      break;
+    }
+    final String engineRevision = lines[index].substring(1);
+    yield FlutterEngineRevision(flutterRevision, engineRevision);
+    index += lines[index + 1].startsWith(r'\ ') ? 2 : 1;
+  }
+}
+
+class FlutterEngineRevision {
+  const FlutterEngineRevision(this.flutterRevision, this.engineRevision);
+
+  final String flutterRevision;
+  final String engineRevision;
+
+  @override
+  String toString() => '$flutterRevision: $engineRevision';
+}