forked from flutter/flutter
-
Notifications
You must be signed in to change notification settings - Fork 7
/
find_engine_commit.dart
130 lines (118 loc) · 3.54 KB
/
find_engine_commit.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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';
}