Skip to content

Commit 0954499

Browse files
[tool] Provide a --base-branch flag (flutter#3322)
[tool] Provide a --base-branch flag
1 parent 7ec6a77 commit 0954499

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

script/tool/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,24 @@ code changes across many packages:
117117
cd <repository root>
118118
dart run script/tool/bin/flutter_plugin_tools.dart update-release-info \
119119
--version=minimal \
120+
--base-branch=upstream/main \
120121
--changelog="Fixes violations of new analysis option some_new_option."
121122
```
122123

123124
The `minimal` option for `--version` will skip unchanged packages, and treat
124125
each changed package as either `bugfix` or `next` depending on the files that
125126
have changed in that package, so it is often the best choice for a bulk change.
126127

127-
For cases where you know the change time, `minor` or `bugfix` will make the
128+
For cases where you know the change type, `minor` or `bugfix` will make the
128129
corresponding version bump, or `next` will update only `CHANGELOG.md` without
129130
changing the version.
130131

132+
If you have a standard repository setup, `--base-branch=upstream/main` will
133+
usually give the behavior you want, finding all packages changed relative to
134+
the branch point from `upstream/main`. For more complex use cases where you want
135+
a different diff point, you can pass a different `--base-branch`, or use
136+
`--base-sha` to pick the exact diff point.
137+
131138
### Publish a Release
132139

133140
**Releases are automated for `flutter/packages`.**

script/tool/lib/src/common/git_version_finder.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import 'package:yaml/yaml.dart';
1111
/// Finding diffs based on `baseGitDir` and `baseSha`.
1212
class GitVersionFinder {
1313
/// Constructor
14-
GitVersionFinder(this.baseGitDir, String? baseSha) : _baseSha = baseSha;
14+
GitVersionFinder(this.baseGitDir, {String? baseSha, String? baseBranch})
15+
: assert(baseSha == null || baseBranch == null,
16+
'At most one of baseSha and baseBranch can be provided'),
17+
_baseSha = baseSha,
18+
_baseBranch = baseBranch ?? 'FETCH_HEAD';
1519

1620
/// The top level directory of the git repo.
1721
///
@@ -21,6 +25,9 @@ class GitVersionFinder {
2125
/// The base sha used to get diff.
2226
String? _baseSha;
2327

28+
/// The base branche used to find a merge point if baseSha is not provided.
29+
final String _baseBranch;
30+
2431
static bool _isPubspec(String file) {
2532
return file.trim().endsWith('pubspec.yaml');
2633
}
@@ -101,13 +108,13 @@ class GitVersionFinder {
101108
}
102109

103110
io.ProcessResult baseShaFromMergeBase = await baseGitDir.runCommand(
104-
<String>['merge-base', '--fork-point', 'FETCH_HEAD', 'HEAD'],
111+
<String>['merge-base', '--fork-point', _baseBranch, 'HEAD'],
105112
throwOnError: false);
106113
final String stdout = (baseShaFromMergeBase.stdout as String? ?? '').trim();
107114
final String stderr = (baseShaFromMergeBase.stderr as String? ?? '').trim();
108115
if (stderr.isNotEmpty || stdout.isEmpty) {
109116
baseShaFromMergeBase = await baseGitDir
110-
.runCommand(<String>['merge-base', 'FETCH_HEAD', 'HEAD']);
117+
.runCommand(<String>['merge-base', _baseBranch, 'HEAD']);
111118
}
112119
baseSha = (baseShaFromMergeBase.stdout as String).trim();
113120
_baseSha = baseSha;

script/tool/lib/src/common/package_command.dart

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,17 @@ abstract class PackageCommand extends Command<void> {
9494
help: 'The base sha used to determine git diff. \n'
9595
'This is useful when $_runOnChangedPackagesArg is specified.\n'
9696
'If not specified, merge-base is used as base sha.');
97+
argParser.addOption(_baseBranchArg,
98+
help: 'The base branch whose merge base is used as the base SHA if '
99+
'--$_baseShaArg is not provided. \n'
100+
'If not specified, FETCH_HEAD is used as the base branch.');
97101
argParser.addFlag(_logTimingArg,
98102
help: 'Logs timing information.\n\n'
99103
'Currently only logs per-package timing for multi-package commands, '
100104
'but more information may be added in the future.');
101105
}
102106

107+
static const String _baseBranchArg = 'base-branch';
103108
static const String _baseShaArg = 'base-sha';
104109
static const String _excludeArg = 'exclude';
105110
static const String _logTimingArg = 'log-timing';
@@ -188,6 +193,11 @@ abstract class PackageCommand extends Command<void> {
188193
return (argResults![key] as String?) ?? '';
189194
}
190195

196+
/// Convenience accessor for String arguments.
197+
String? getNullableStringArg(String key) {
198+
return argResults![key] as String?;
199+
}
200+
191201
/// Convenience accessor for List<String> arguments.
192202
List<String> getStringListArg(String key) {
193203
// Clone the list so that if a caller modifies the result it won't change
@@ -338,7 +348,7 @@ abstract class PackageCommand extends Command<void> {
338348
if (lastCommitOnly) {
339349
print(
340350
'--$_packagesForBranchArg: using parent commit as the diff base.');
341-
changedFileFinder = GitVersionFinder(await gitDir, 'HEAD~');
351+
changedFileFinder = GitVersionFinder(await gitDir, baseSha: 'HEAD~');
342352
} else {
343353
changedFileFinder = await retrieveVersionFinder();
344354
}
@@ -361,7 +371,7 @@ abstract class PackageCommand extends Command<void> {
361371
}
362372
} else if (getBoolArg(_runOnDirtyPackagesArg)) {
363373
final GitVersionFinder gitVersionFinder =
364-
GitVersionFinder(await gitDir, 'HEAD');
374+
GitVersionFinder(await gitDir, baseSha: 'HEAD');
365375
print('Running for all packages that have uncommitted changes\n');
366376
// _changesRequireFullTest is deliberately not used here, as this flag is
367377
// intended for use in CI to re-test packages changed by
@@ -473,10 +483,12 @@ abstract class PackageCommand extends Command<void> {
473483
///
474484
/// Throws tool exit if [gitDir] nor root directory is a git directory.
475485
Future<GitVersionFinder> retrieveVersionFinder() async {
476-
final String baseSha = getStringArg(_baseShaArg);
486+
final String? baseSha = getNullableStringArg(_baseShaArg);
487+
final String? baseBranch =
488+
baseSha == null ? getNullableStringArg(_baseBranchArg) : null;
477489

478-
final GitVersionFinder gitVersionFinder =
479-
GitVersionFinder(await gitDir, baseSha);
490+
final GitVersionFinder gitVersionFinder = GitVersionFinder(await gitDir,
491+
baseSha: baseSha, baseBranch: baseBranch);
480492
return gitVersionFinder;
481493
}
482494

script/tool/test/common/git_version_finder_test.dart

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ void main() {
3838
});
3939

4040
test('No git diff should result no files changed', () async {
41-
final GitVersionFinder finder = GitVersionFinder(gitDir, 'some base sha');
41+
final GitVersionFinder finder =
42+
GitVersionFinder(gitDir, baseSha: 'some base sha');
4243
final List<String> changedFiles = await finder.getChangedFiles();
4344

4445
expect(changedFiles, isEmpty);
@@ -49,7 +50,8 @@ void main() {
4950
file1/file1.cc
5051
file2/file2.cc
5152
''';
52-
final GitVersionFinder finder = GitVersionFinder(gitDir, 'some base sha');
53+
final GitVersionFinder finder =
54+
GitVersionFinder(gitDir, baseSha: 'some base sha');
5355
final List<String> changedFiles = await finder.getChangedFiles();
5456

5557
expect(changedFiles, equals(<String>['file1/file1.cc', 'file2/file2.cc']));
@@ -60,7 +62,8 @@ file2/file2.cc
6062
file1/pubspec.yaml
6163
file2/file2.cc
6264
''';
63-
final GitVersionFinder finder = GitVersionFinder(gitDir, 'some base sha');
65+
final GitVersionFinder finder =
66+
GitVersionFinder(gitDir, baseSha: 'some base sha');
6467
final List<String> changedFiles = await finder.getChangedPubSpecs();
6568

6669
expect(changedFiles, equals(<String>['file1/pubspec.yaml']));
@@ -73,8 +76,28 @@ file1/pubspec.yaml
7376
file2/file2.cc
7477
''';
7578

76-
final GitVersionFinder finder = GitVersionFinder(gitDir, null);
79+
final GitVersionFinder finder = GitVersionFinder(gitDir);
7780
await finder.getChangedFiles();
81+
verify(gitDir.runCommand(
82+
<String>['merge-base', '--fork-point', 'FETCH_HEAD', 'HEAD'],
83+
throwOnError: false));
84+
verify(gitDir.runCommand(
85+
<String>['diff', '--name-only', mergeBaseResponse, 'HEAD']));
86+
});
87+
88+
test('uses correct base branch to find base sha if specified', () async {
89+
mergeBaseResponse = 'shaqwiueroaaidf12312jnadf123nd';
90+
gitDiffResponse = '''
91+
file1/pubspec.yaml
92+
file2/file2.cc
93+
''';
94+
95+
final GitVersionFinder finder =
96+
GitVersionFinder(gitDir, baseBranch: 'upstream/main');
97+
await finder.getChangedFiles();
98+
verify(gitDir.runCommand(
99+
<String>['merge-base', '--fork-point', 'upstream/main', 'HEAD'],
100+
throwOnError: false));
78101
verify(gitDir.runCommand(
79102
<String>['diff', '--name-only', mergeBaseResponse, 'HEAD']));
80103
});
@@ -85,7 +108,8 @@ file2/file2.cc
85108
file1/pubspec.yaml
86109
file2/file2.cc
87110
''';
88-
final GitVersionFinder finder = GitVersionFinder(gitDir, customBaseSha);
111+
final GitVersionFinder finder =
112+
GitVersionFinder(gitDir, baseSha: customBaseSha);
89113
await finder.getChangedFiles();
90114
verify(gitDir
91115
.runCommand(<String>['diff', '--name-only', customBaseSha, 'HEAD']));
@@ -97,7 +121,8 @@ file2/file2.cc
97121
file1/pubspec.yaml
98122
file2/file2.cc
99123
''';
100-
final GitVersionFinder finder = GitVersionFinder(gitDir, customBaseSha);
124+
final GitVersionFinder finder =
125+
GitVersionFinder(gitDir, baseSha: customBaseSha);
101126
await finder.getChangedFiles(includeUncommitted: true);
102127
// The call should not have HEAD as a final argument like the default diff.
103128
verify(gitDir.runCommand(<String>['diff', '--name-only', customBaseSha]));

0 commit comments

Comments
 (0)