flutter/dev/tools/find_engine_commit.dart
Matan Lurey 71d50a1616
Start using bin/cache/engine.{stamp|realm} instead of bin/internal/engine.{realm|version}. (#164352)
Towards https://github.com/flutter/flutter/issues/164315.

See also:
https://github.com/flutter/flutter/blob/master/docs/tool/Engine-artifacts.md.

There are more usages in `flutter/flutter`, but some will require more
specialized review (i.e. from release folks, or the Dart SDK team), so
I'll split those off.

~~Requires https://github.com/flutter/flutter/pull/164317 to merge
first.~~ 
2025-03-02 00:54:33 +00:00

121 lines
3.5 KiB
Dart

// 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/cache/engine.stamp').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';
}